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. 이름 후보와 결정
| 후보 | 장점 | 단점 | 평가 |
|---|---|---|---|
| ModelGateway | ExploreGateway와 짝을 이루는 이름, "모델 접근"이라는 책임이 이름에 드러남 | 검색·색인까지 포함한다고 오해할 수 있음(책임 표로 해소) | ✅ 확정 |
| 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/completions | OpenAI 호환 본문 그대로 — @hohyun94/portal-ai의 createOpenAiCompatibleProvider 무변경 사용 |
| POST | /v1/embeddings | OpenAI 호환(임베딩도 게이트웨이 경유로 통일 권장) |
귀속·감사 헤더(선택 → 권장)
기계 판독 계약(OpenAPI 3.1): ModelGateway/docs/openapi.json — 5개 경로와 요청·응답·오류 스키마, 귀속 헤더 파라미터. ModelGateway/tests/contract.test.ts가 문서와 실제 서버 동작(경로 존재·401 본문 형태·스키마 참조)이 일치하는지 검증한다.
| 헤더 | 예 | 용도 |
|---|---|---|
authorization | Bearer <MODEL_GATEWAY_SERVICE_TOKEN> | 서비스 토큰(소비자별). 회전 시 MODEL_GATEWAY_SERVICE_TOKENS(쉼표 구분)로 다중 동시 유효 |
x-portal-id | process-center | 비용·쿼터 귀속 |
x-purpose | process.version-summary | 목적별 모델·프롬프트·비용 분류 |
x-actor | a-user | 감사 추적(로그 전용, 권한 미사용) |
x-tenant-id / x-organization-id | 7 / 3 | 비용 배분(선택) |
- 헤더가 없으면 게이트웨이는 비용을 미분류로 기록한다(추정하지 않음 → 감사 정확도 유지).
- 응답은 OpenAI 호환을 유지하고, 게이트웨이 메타데이터는 응답 헤더로 노출한다:
x-request-id,x-model,x-usage-total-tokens.
5. 비용·감사 모델
감사 레코드(본문 미저장)
{
"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를 기준으로 한다.
이유:
- AI를 쓰는 기능은 계속 늘어난다(번역 → 실시간 번역, 요약 → 영역 추론, 검색 → RAG). 기능을 고정 enum으로 두면 확장마다 서비스·스키마·화면을 함께 고쳐야 한다.
- 화면을 서비스별로 각각 만들면(게이트웨이 화면 + 검색 화면 + 색인 화면) 관리자가 여러 곳을 오가고, "어느 포털에 어떤 AI 기능이 적용됐는지"를 볼 단일 지점이 사라진다.
- 사용자·조직·포털·접근권한을 이미 소유한 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안 확정 선행)