Skip to content

ModelGateway(모델 게이트웨이) 범위·이름 확정 ​

작성 시각: 2026-09-13 · 상태: 확정(2026-09-13) — docs/SERVICE_BOUNDARIES.md·docs/DECISION_LOG.md 반영 완료 관련 결정: docs/DECISION_LOG.md(2026-09-13) — UI플랫폼은 AI 미관장, RAG·검색은 ExploreGateway, 모델·키·비용·감사는 ModelGateway

1. 목적 ​

LLM 완성(요약·번역·정합성 분석 등)을 쓰는 소비 포털이 모델 접근을 단일 창구로 사용하도록 하는 서비스의 이름과 책임 경계를 확정한다. 현재는 각 포털이 PRIVATE_LLM_URL(사내 LLM)을 직접 호출하며, 키·쿼터·비용·감사가 포털마다 분산된다.

2. 이름 후보와 결정 ​

후보장점단점평가
ModelGatewayExploreGateway와 짝을 이루는 이름, "모델 접근"이라는 책임이 이름에 드러남검색·색인까지 포함한다고 오해할 수 있음(책임 표로 해소)✅ 확정
AiGateway포괄적검색·RAG·운영 콘솔까지 포함한다는 오해, 책임 과대❌
Ai-Core(서비스)짧음공용 라이브러리 @hohyun94/portal-ai(ai-core)와 이름 충돌❌
LlmGateway기술적으로 정확embedding·모델 카탈로그 등 LLM 외 모델 접근을 포괄하지 못함❌

확정 이름: ModelGateway(한국어: 모델 게이트웨이) · 저장소 디렉터리 ModelGateway(FileStore·PortalConsole와 동일한 서비스 네이밍 규칙)

3. 범위 ​

소유(IN)

책임내용
모델 접근 프록시OpenAI 호환 유지 — /v1/chat/completions·/v1/embeddings(소비자 코드 변경 최소화)
모델 카탈로그·라우팅목적별 기본 모델(요약·번역·정합성·임베딩), 테넌트·포털별 모델 정책, 장애 시 폴백
키 관리외부 클라우드 키 보관·회전(사내 LLM은 무키) — 키는 게이트웨이에만 존재
쿼터·레이트리밋포털·목적·테넌트 단위 토큰 한도, 초과 시 429
비용 집계포털·테넌트·목적별 토큰 사용량/비용 리포트
감사requestId·portalId·purpose·actor·model·토큰·지연·상태 — 본문·응답 미저장
프롬프트 버전표준 템플릿(요약·번역·정합성)의 버전 관리 + 소비자 purpose 매핑
헬스·가용성모델 가용성·지연·장애 상태 제공(사내 LLM 장애 시 명확한 오류)

비소유(OUT)

대상소유자
문서 색인·벡터 검색·유사도·근거 기반 응답ExploreGateway
파일 원본·보관·스캔·색인 발행FileStore
공통 UI 패키지·테마·릴리스·배포UI플랫폼
사용자·조직·인증·포털 접근권한PortalConsole
AI 적용 결정(무엇을 요약/번역할지)·업무 규칙각 소비 포털
AI 계약·유틸 라이브러리(@hohyun94/portal-ai)portal-foundation

4. 소비자 인터페이스 (OpenAI 호환 + 귀속 헤더) ​

메서드경로비고
GET/v1/health모델 가용성·지연
GET/v1/models사용 가능한 모델 카탈로그(목적 매핑 포함)
POST/v1/chat/completionsOpenAI 호환 본문 그대로 — @hohyun94/portal-ai의 createOpenAiCompatibleProvider 무변경 사용
POST/v1/embeddingsOpenAI 호환(임베딩도 게이트웨이 경유로 통일 권장)

귀속·감사 헤더(선택 → 권장)

기계 판독 계약(OpenAPI 3.1): ModelGateway/docs/openapi.json — 5개 경로와 요청·응답·오류 스키마, 귀속 헤더 파라미터. ModelGateway/tests/contract.test.ts가 문서와 실제 서버 동작(경로 존재·401 본문 형태·스키마 참조)이 일치하는지 검증한다.

헤더예용도
authorizationBearer <MODEL_GATEWAY_SERVICE_TOKEN>서비스 토큰(소비자별). 회전 시 MODEL_GATEWAY_SERVICE_TOKENS(쉼표 구분)로 다중 동시 유효
x-portal-idprocess-center비용·쿼터 귀속
x-purposeprocess.version-summary목적별 모델·프롬프트·비용 분류
x-actora-user감사 추적(로그 전용, 권한 미사용)
x-tenant-id / x-organization-id7 / 3비용 배분(선택)
  • 헤더가 없으면 게이트웨이는 비용을 미분류로 기록한다(추정하지 않음 → 감사 정확도 유지).
  • 응답은 OpenAI 호환을 유지하고, 게이트웨이 메타데이터는 응답 헤더로 노출한다: x-request-id, x-model, x-usage-total-tokens.

5. 비용·감사 모델 ​

감사 레코드(본문 미저장)

jsonc
{
  "requestId": "mg-0f1c…",
  "portalId": "process-center",
  "purpose": "process.version-summary",
  "actor": "a-user",
  "model": "llama3",
  "promptTokens": 1832, "completionTokens": 214,
  "latencyMs": 2840,
  "status": 200,
  "createdAt": "2026-09-13T01:00:00Z"
}
  • 요청·응답 본문은 저장하지 않는다(문서 내용·개인정보 최소화). 업무 맥락이 필요하면 소비자가 자기 DB 감사 로그에 남긴다.
  • 보존 기간·조회 주체는 §8-5에서 결정한다.

쿼터·비용

  • 쿼터: portalId × purpose 기준 분당·일별 토큰 한도, 초과 시 429 + Retry-After.
  • 비용: 토큰 사용량 기반 집계, tenantId·portalId·purpose별 리포트(조회 화면 소유자는 §8-7).

6. 배포 프로필 ​

프로필모델 경로비고
CLOUD외부 모델 API(키 필요) 또는 사내 LLM키는 게이트웨이 secret에만
ON_PREM사내 LLM·임베딩 엔드포인트만(외부 차단 허용)기존 PRIVATE_LLM_URL 설정을 게이트웨이가 흡수
미설정게이트웨이 없이 로컬 직접 호출 유지소비자는 aiCompletionEnabled() false → 기능 SKIPPED(현행 동작 유지)

7. 소비자 마이그레이션 (ProcessCenter 기준) ​

단계내용소비자 변경
P1게이트웨이 배포 후 PRIVATE_LLM_URL을 게이트웨이 주소로 교체, 키를 게이트웨이로 이동환경변수만(코드 변경 0)
P2귀속 헤더(x-portal-id·x-purpose·x-actor) 추가 → 비용·감사 귀속 활성화server/ai/aiClient.ts 1곳
P3프롬프트를 purpose ID 기반 표준 템플릿으로 전환(선택)서비스 계층 1곳

P1만으로도 즉시 이득(키 중앙화·감사)이 생기고, P2·P3는 준비되면 순차 적용한다.

진행 상태(2026-09-13) — ProcessCenter P1·P2 완료

  • ProcessCenter/server/ai/aiClient.ts가 MODEL_GATEWAY_URL·MODEL_GATEWAY_SERVICE_TOKEN이 있으면 게이트웨이를 우선 사용하고, 귀속 헤더(x-portal-id·x-purpose·x-actor)를 자동으로 붙인다. 설정이 없으면 기존 PRIVATE_LLM_URL 직접 호출로 폴백하고, 둘 다 없으면 기능이 SKIPPED 처리된다.
  • 게시본 AI 요약은 purpose process.version-summary, actor는 승인자/재분석 요청자로 전달된다.
  • 테스트: server/ai/aiClient.test.ts — 게이트웨이 우선(URL·토큰·헤더 검증), 미설정 시 직접 호출 폴백, 둘 다 없을 때 비활성.
  • P3(프롬프트 표준 템플릿 전환)는 게이트웨이 프롬프트 소유권 결정(§8-1) 이후 진행한다.
  • 개발 스택 등록 완료: ProcessCenter/docker-compose.dev.yml에 model-gateway 서비스(호스트 3400 → 컨테이너 8080, 업스트림 http://host.docker.internal:11434, 개발용 서비스 토큰)를 추가하고 ProcessCenter에 MODEL_GATEWAY_URL=http://model-gateway:8080을 주입했다. 검증: 헬스 200(업스트림 주소·키 비노출) · 무토큰 401 · /v1/models 목록 반환.

8. 미해결·결정 필요 ​

#항목결정(2026-09-13)
1프롬프트 소유권각 포털 소유 — 프롬프트 내용(무엇을 어떻게 요약·번역할지)은 업무 규칙이다. 게이트웨이는 purpose·모델 매핑·감사·쿼터만 담당하고 표준 템플릿을 강제하지 않는다(선행 결정 "AI 적용 결정 = 각 포털"과 일치)
2모델 폴백MODEL_GATEWAY_FALLBACK_URL 옵션 · CLOUD에서 연결 실패·타임아웃 시 1회만 재시도(x-upstream-fallback: true) · ON_PREM은 폴백 금지(외부 경로 사용 안 함)
3임베딩 경유게이트웨이 경유로 통일 — 소비 포털은 MODEL_GATEWAY_URL 설정 시 임베딩도 게이트웨이로 보낸다(x-purpose: rag.embedding). 미설정이면 기존 PRIVATE_EMBEDDING_URL 직접 호출
4서비스 토큰소비자별 정적 토큰 · MODEL_GATEWAY_SERVICE_TOKENS(쉼표 구분)로 다중 동시 유효 → 소비자를 순차 교체해 무중단 회전 · 값은 배포 환경변수/secret으로만 주입
5감사 보존·조회PostgreSQL 영속(model_gateway_audit) + 읽기 전용 /v1/usage 조회 · 보존 기간 정리는 운영 정책(후속)
6비용 한도포털×목적 일별 토큰 한도(model_gateway_quota_policies) · 초과 시 429 + Retry-After · 정책 없으면 무제한
7운영 콘솔게이트웨이는 UI를 갖지 않는다 — 관리 API(/admin/api)만 제공하고, 운영 화면 소유자는 PortalConsole(제어평면 콘솔)로 확정(2026-09-14). 콘솔 서버가 서버 간 토큰(MODEL_GATEWAY_ADMIN_TOKEN(S))으로 호출하며, 브라우저는 게이트웨이에 직접 붙지 않는다(쿠키·CORS·핸드오프 없음)
8스트리밍1차 미지원(비스트리밍) — 구현은 stream: true를 400 INVALID_REQUEST로 명시 거부한다(빈 200 응답으로 깨지지 않도록). 실시간 번역 등 스트리밍이 필요한 기능을 도입할 때 재개한다(§9 · docs/AI_FEATURE_REGISTRY.md의 capabilities: ["streaming"])

9. AI 운영 표면과 AI 기능 레지스트리 (2026-09-14 확정) ​

결정: AI를 사용하는 공통기능(요약·번역·정합성·영역 추론·RAG·실시간 번역 등) 의 목록·세팅·사용량을 PortalConsole(제어평면 콘솔) 한 곳에서 관리한다. 중심 엔티티는 고정 목록이 아니라 열린 AI 기능(purpose) 레지스트리이며, 각 기능은 완성 연결(ModelGateway) 과 선택적 검색 연결(ExploreGateway·RagService) 을 갖고, 도입에 필요한 능력(예: streaming) 을 함께 기록한다. 스키마·능력 매트릭스·확장 절차는 docs/AI_FEATURE_REGISTRY.md를 기준으로 한다.

이유:

  1. AI를 쓰는 기능은 계속 늘어난다(번역 → 실시간 번역, 요약 → 영역 추론, 검색 → RAG). 기능을 고정 enum으로 두면 확장마다 서비스·스키마·화면을 함께 고쳐야 한다.
  2. 화면을 서비스별로 각각 만들면(게이트웨이 화면 + 검색 화면 + 색인 화면) 관리자가 여러 곳을 오가고, "어느 포털에 어떤 AI 기능이 적용됐는지"를 볼 단일 지점이 사라진다.
  3. 사용자·조직·포털·접근권한을 이미 소유한 PortalConsole가 적용 현황·사용량·정책을 통합해 보는 것이 제어평면의 역할과 일치한다.

영향:

  • 서비스는 분리 유지 — ModelGateway(완성: 모델·키·쿼터·비용·감사) · ExploreGateway(탐색 조합) · RagService(색인·검색·근거). 합치지 않는다.
  • 표면은 통합 — PortalConsole이 각 서비스의 관리 API를 서버 간 토큰으로 호출한다(§8-7). 브라우저가 각 서비스에 직접 붙지 않으므로 CORS·쿠키·SSO가 중복되지 않는다.
  • 공통기능 구현은 Asset 제공 — 2026-08-20 결정("공통 기능은 통합 운영이 아닌 Asset 제공")을 따른다. 재사용 구현·계약·패턴은 portal-foundation(@hohyun94/portal-ai)으로 제공하고, 중앙 런타임은 모델 접근·색인에만 둔다(키 격리·쿼터·비용·감사 때문).
  • RAG는 게이트웨이 소유가 아니다 — RAG 기능은 model + retrieval을 함께 연결한 기능으로 기록한다.
  • 스트리밍(§8-8) — 실시간 번역처럼 스트리밍이 필요한 기능은 레지스트리에 capabilities: ["streaming"]으로 등록하고, ModelGateway 스트리밍을 재개한 뒤 활성화한다(미비 시 enabled=false "준비 중").

10. 확정 시 반영 체크리스트 ​

  • [x] docs/SERVICE_BOUNDARIES.md의 "모델·키·비용·감사(LLM 완성) | ModelGateway(모델 게이트웨이)"로 확정(반영 완료)
  • [x] docs/DECISION_LOG.md에 결정 항목 추가(이름·범위·비소유, 2026-09-13)
  • [x] ProcessCenter/docs/DB_STRATEGY.md §8 소유자 표 갱신(ModelGateway 확정)
  • [x] ProcessCenter/docs/PROCESS_NODE_GOVERNANCE_PLAN.md 후속 항목에 반영
  • [x] 저장소 생성 시 서비스 표준 레이아웃(헬스·인증·감사·Dockerfile.dev) 적용 — ModelGateway 저장소 생성 완료(커밋 21767c3, tsc 0 errors · 테스트 8건 통과)
  • [x] 화면 소유자 확정(2026-09-14) — 게이트웨이는 API 전용(/admin/api, 서버 간 토큰), 운영 화면은 PortalConsole 관리자 메뉴 "모델 게이트웨이 관리"(ModelGateway #15 · PortalConsole #16)
  • [ ] docs/AI_FEATURE_REGISTRY.md 규격에 따라 포털 카탈로그의 고정 capabilities를 기능 레지스트리로 승격
  • [ ] RagService·ExploreGateway의 콘솔용 관리 API 계약 정의(경계 권장 A안 확정 선행)