AWS 기술 블로그
실리콘투의 사내 지식 MCP 게이트웨이 구축기
실리콘투는 한국의 뷰티 브랜드를 전 세계 고객에게 유통하는 글로벌 플랫폼 기업입니다. 수많은 브랜드와 상품, 국가별 물류가 실시간으로 맞물려 돌아가고, 이 방대한 흐름을 CMS, WMS, OMS를 비롯한 여러 사내 시스템이 나눠 맡습니다. 사업이 커질수록 업무 규칙도 함께 불어났고, 그 규칙은 저장 프로시저(SP, Stored Procedure. 데이터베이스에 넣어 두고 불러 쓰는 SQL 로직 묶음), 소스 코드, 그리고 여기저기 흩어진 문서에 조금씩 나뉘어 쌓여 갔습니다.

AI를 업무에 들이기 시작하면서 이 분산이 문제로 드러났습니다. 예를 들어 “재고가 입고된 순간부터 출고되기까지, 우리 ERP는 어떤 단계를 거치지?” 라는, 신입에게 자주 나오는 평범한 질문 하나에도 답이 사람마다 달랐습니다. 근거가 SP와 코드, 흩어진 문서(문서 900건, 운영 데이터베이스 10개)에 나뉘어 있고 출처도 분명치 않으니, 답을 맞춰 보는 데만 길게는 수십 분이 걸리곤 했습니다. AI 모델은 충분히 똑똑했지만, 정작 우리 회사를 몰랐던 셈입니다.
그래서 저희가 내린 결론은 “더 좋은 모델을 고르자”가 아니었습니다. 흩어진 사내 지식을 AI가 신뢰하고 바로 쓸 수 있도록 한곳에 모으는 일, 즉 기반 지식 체계(데이터 파운데이션) 를 먼저 세우는 일이었습니다. 저희는 이 지식을 권한이 통제되는 단 하나의 입구로 모았습니다. 모델과 도구를 잇는 표준인 MCP(Model Context Protocol) 위에 올린 게이트웨이, S2 Domain Knowledge Gateway입니다.
이 글에는 저희가 실제로 걸어온 두 걸음이 담겨 있습니다. 첫걸음은 현재 규모에 가장 비용 효율적인 온프렘, 임베디드 프로토타입으로 토대를 세운 것이고, 두 번째 걸음은 이 토대가 사내 공용 플랫폼으로 인정받으면서 상태, 감사, 배포 계층을 AWS 관리형 서비스로 이전한 것입니다. 지금은 개발자와 여러 사내 AI 에이전트가 이 한 입구로 회사 지식을 조회하고 있고, 비개발 임직원을 위한 Slack 챗봇도 연동하여 운영 중입니다.
이 글에서 나누고 싶은 이야기는 세 가지입니다.
- 첫 번째, AI-DLC(AWS가 제시한 AI 주도 개발 방법론, AI-Driven Development Lifecycle)로 어떻게 빠르고 올바르게 만들었는가?
- 두 번째, 왜 처음에는 온프렘, 임베디드가 비용 대비 가장 효율적인 선택이었는가?
- 세 번째, 사내 표준으로 인정받은 뒤 어떤 원칙을 지키며 AWS로 옮겼고 무엇이 아직 남아 있는가?

1. AI-DLC로 만든 과정
AI-DLC의 첫 단계(Inception)에서, 저희는 코드를 한 줄도 짜기 전에 타협하지 않을 네 가지 원칙부터 정했습니다.
- 권한은 검색 전에 차단하고 검색 결과를 사후에 걸러내는 게 아니라 애초에 못 읽게 한다.
- 임베딩은 사내에서 수행하며 색인검색 과정에서 지식이 회사 밖으로 나가지 않는다(외부 유출, 즉 egress 0).
- 모든 호출은 감사되며 누가 무엇을 물었는지 부인할 수 없게 기록한다.
- 게이트웨이는 검색만 담당하며 최종 답변 생성은 다운스트림(소비자 LLM)의 몫으로 분리한다.
이 원칙들은 “나중에 보안을 붙이자”가 아니라 1일차 설계 제약이었습니다. 그다음 구현 단계(Construction)에서는 역할별 AI 에이전트(기획, 백엔드, DBA, 리뷰어)가 검증 게이트를 통과하는 짧은 반복으로 코드를 채워 나갔고, 약 3주 만에 검색, 권한, 라이브 DB, 감사(Phase 0–3)를 완성했습니다. 위험을 먼저 못 박아 둔 덕분에, 보안과 감사가 “다음 분기”로 밀리지 않았습니다.
AI-DLC는 만든 것을 고쳐 나가는 근거도 함께 남겨 줍니다. 이 글 후반에서 보듯, 감사, 저장, 배포 계층은 이후 실제 운영 요구에 맞춰 온프렘 구현에서 AWS 관리형으로 결정 기록(ADR)을 남기며 이전했습니다.
2. 왜 (처음에는) 온프렘, 임베디드였나
가장 자주 받는 질문은 “왜 처음부터 관리형 벡터 검색(예: 상시 클러스터)을 쓰지 않았는가” 입니다. 답은 의도적인 비용 최적화였습니다.
먼저 규모를 짚고 가겠습니다. 저희가 다루는 지식의 총량, 곧 문서와 그 문서를 검색하기 좋게 잘게 나눈 조각(청크)의 모음인 코퍼스(corpus)는 현재 문서 900건, 청크 5,420개입니다. 이 규모에서 상시 가동되는 검색 클러스터는 월 수백 달러의 고정비를 발생시키는데, 초기 검증 단계에서 얻는 이점은 크지 않았습니다.
반면 임베디드 구조, 곧 검색 인덱스(SQLite FTS5)와 벡터 저장소를 애플리케이션과 같은 프로세스에 두는 방식은 이점이 뚜렷했습니다. 임베딩이 같은 프로세스 안에서 일어나 데이터가 네트워크로 나가지 않고(egress 0), 외부 의존성이 없어 무거운 ML 라이브러리 없이 키워드 검색만으로도 완전히 동작하며(우아한 성능 저하), 온프렘에서 즉시 구동돼 낮은 비용으로 빠르게 토대를 세울 수 있었습니다.
정리하면 검증 단계에서는 온프렘, 임베디드가 비용 대비 가장 효율적이었고, 이 토대가 사내에서 실효를 인정받아 사용자와 소비자가 늘어난 시점에 AWS로 확장하는 것이 합리적이었습니다. 그리고 뒤에서 보겠지만 확장할 때도 “불필요한 상시 고정비를 만들지 않는다”는 기준은 그대로 이어집니다.
3. 검색 전에 권한을 막는다
이 게이트웨이가 일반 검색 시스템과 가장 다른 점은 권한을 적용하는 시점입니다. 왜 이렇게까지 시점을 앞당겼는지부터 말씀드리겠습니다.
이 입구를 호출하는 주체는 대개 사람이 아니라 자동으로 움직이는 AI 에이전트입니다. 에이전트는 사람보다 훨씬 빠르고 많이 질의하고, 스스로 판단해 도구를 연달아 호출합니다. “결과가 나오면 사람이 눈으로 한 번 걸러 준다”는 전제가 성립하지 않는다는 뜻입니다. 게다가 이 입구는 개발자뿐 아니라 비개발 부서와 사내 챗봇에까지 열 계획이었습니다. 그래서 권한 밖 정보는 애초에 검색 결과에 실리지 못하게 막는 것만이 안전했습니다.
표준 MCP는 “이 사람이 누구인가(인증)”까지는 다루지만, “이 도구를 호출해도 되는가(인가)”는 서버가 알아서 하도록 비워 둡니다. 그래서 일반적인 MCP 서버는 도구를 호출하면 그냥 실행됩니다. 저희는 그 빈자리에 서버 측 인가 계층을 직접 구현해, 권한을 결과가 나온 뒤가 아니라 검색이 시작되기 전, 세 지점에서 막습니다.
- 도구 게이트: 도구 호출 자체를 인가합니다.
- 검색 전 문서 필터: 볼 수 없는 문서는 순위를 매기기도 전에 후보에서 제외합니다. 그래서 점수로도 미리보기 조각으로도 새지 않습니다.
- 필드 마스킹: 문서를 통째로 볼 때 민감한 항목을 가립니다.
권한 규칙의 진실원은 AWS가 만든 정책 언어 Cedar 한 벌이며, 명시적으로 허용되지 않은 것은 모두 거부합니다(default-deny). 이 RBAC/인가 계층은 아래에서 이야기할 감사, 저장 계층의 AWS 이전과 무관하게 그대로 유지됩니다. 아래는 역할이 가진 권한(scope)에 따라 SP, 테이블 식별자를 가리는 실제 코드입니다.
def scrub_identifiers(text: str, principal: Principal) -> tuple[str, list[str]]:
"""DB 권한(scope)이 없는 역할에게는 SP/테이블 식별자를 가린다 (마스킹)."""
if not text:
return text, []
scopes = principal.scopes
out, removed = text, []
if "db:spdef" not in scopes: # SP 정의 권한 없음
out, n = _SP_RE.subn("[REDACTED:SP]", out) # (사내 SP 명명 패턴)
if n:
removed.append("sp")
if "db:schema" not in scopes: # 스키마 권한 없음
out, n = _TBL_RE.subn("[REDACTED:TABLE]", out) # (사내 테이블/뷰 명명 패턴)
if n:
removed.append("tables")
out, n = _DBO_RE.subn("[REDACTED:DBO]", out) # (스키마 소유자 접두)
if n:
removed.append("dbo")
return out, removed # developer/dba/admin은 권한 보유 → 원문 그대로
목표는 분명했습니다. 같은 질문에도 역할별로 다르게 답하되, 민감 정보는 절대 새지 않아야 합니다. 이를 실제 코퍼스 전체로 측정했습니다. business 역할에게 노출될 수 있는 본문 속 스키마 식별자 3,076개가 전부 마스킹되어, 잔존 누수는 0이었습니다. 권한, 마스킹 테스트도 모두 통과합니다. 다만 이 수치는 현재 코퍼스와 정해진 사내 명명 규칙을 기준으로 한 측정값이지 일반적인 보증은 아니며, 규칙을 벗어난 새 식별자는 회귀 테스트가 잡도록 설계했습니다.
4. RRF를 통한 하이브리드 검색
권한 범위가 정해지면 그 안에서 검색이 일어납니다. 저희는 두 방식을 함께 씁니다. 하나는 저장 프로시저 이름처럼 정확히 일치해야 하는 식별자에 강한 키워드 검색(BM25, SQLite FTS5 기반), 다른 하나는 뜻이 비슷한 문서를 찾는 의미 기반 벡터 검색(온프렘 임베딩 모델 BGE-M3, 1024차원) 입니다. 점수 척도가 전혀 다른 두 결과를, 점수가 아니라 순위만으로 합치는 것이 RRF(Reciprocal Rank Fusion, 상호 순위 융합) 입니다. 핵심은 7줄입니다.
def rrf_fuse(ranked_lists: list[list[str]], k: int = 60) -> dict[str, float]:
"""각 리스트는 best-first 정렬된 chunk_id. 점수가 아니라 '순위'만 쓴다 → 스케일 무관."""
scores: dict[str, float] = {}
for ids in ranked_lists:
for rank, chunk_id in enumerate(ids, start=1):
scores[chunk_id] = scores.get(chunk_id, 0.0) + 1.0 / (k + rank)
return scores
융합한 결과는 마지막으로 크로스인코더(질의와 문서를 함께 보고 다시 채점하는 모델)로 상위 후보만 정밀 재정렬합니다. 여기서 확인하고 싶었던 것은 키워드만으로는 못 찾는 의미 질의를 얼마나 회수하느냐였고, 세 구성을 같은 조건에서 측정했습니다.
| 구성 | recall@10 (95% CI) | MRR (95% CI) |
|---|---|---|
| 키워드(BM25)만 | 0.70 (0.56–0.81) | 0.42 (0.32–0.54) |
| + 벡터 | 0.98 (0.90–1.00) | 0.74 (0.63–0.83) |
| + 리랭킹 | 0.94 (0.84–0.98) | 0.81 (0.71–0.89) |
여기서 recall@10은 정답을 상위 10개에 포함한 비율, MRR은 정답이 위에 올수록 높아지는 지표입니다(표본 n=50 파일럿이라 신뢰구간이 넓습니다). 키워드만 쓰다 벡터를 더하자 recall이 0.70에서 0.98로 뛰었고, 두 구간의 신뢰구간이 겹치지 않아 통계적으로 유의합니다. BM25가 놓친 의미 질의 14건을 벡터가 회수한 결과입니다. 리랭킹에서 recall이 0.98에서 0.94로 살짝 내려가는데, 이는 유의차가 아닙니다. 상위 후보만 다시 채점하다 보니 원래 10위권 밖이던 정답이 컷 근처에서 밀린 현상입니다. 대신 정답을 위로 끌어올리는 MRR이 0.74에서 0.81로 개선되어, 상위 한두 건만 보는 소비자(챗봇, LLM)에게 유리합니다.
융합 방식으로는 점수 정규화도 같은 코퍼스에서 함께 비교했습니다. 정규화가 융합 단계에서는 조금 더 정확했지만, 뒤이어 리랭커가 순서를 다시 매기고 나면 그 차이는 사라졌습니다. RRF는 튜닝할 값이 없고 점수 척도에 휘둘리지 않아, 저희는 RRF를 택했습니다.
초기 프로토타입은 벡터를 임베디드 저장소(LanceDB)에 두었습니다. 이 벡터 저장 계층은 이후 사내 중앙 Amazon RDS PostgreSQL 16 + pgvector로 이전했습니다. 검색 로직 (RRF, 하이브리드, 리랭킹)과 응답 계약은 그대로이고, 바뀐 것은 dense 벡터가 어디에 저장되느냐뿐입니다.
5. 감사와 비밀은 관리형에 맡긴다
이 계층은 프로토타입에서 관리형으로 넘어오며 가장 크게 바뀐 부분이고, 그 변화 자체가 이 프로젝트의 이야기이기도 합니다.
프로토타입 단계에서 저희는 감사를 앱 안에서 처리했습니다. 모든 도구 호출이 직전 기록의 ID를 가리키고 Ed25519로 서명되는 해시체인 영수증을 로컬 파일에 남겼습니다. 온프렘 단일 노드에서는 이 방식이 “운영자조차 뒤늦게 못 고친다”는 위변조 저항을 앱만으로 달성하는 좋은 수단이었습니다.
그런데 이 토대가 사내 공용 플랫폼으로 인정받아 여러 컨테이너로 수평 확장하고 상태를 중앙 RDS PostgreSQL로 통합하게 되면서, 전제가 바뀌었습니다.
- 단일 파일 해시체인은 다중 컨테이너에서 동시에 쓸 수 없습니다. 반면 RDS로 통합하면 트랜잭션시퀀스로 공유, 정렬, 동시 안전 append가 자연스럽게 해결됩니다.
- 관리형 RDS PostgreSQL은 pgaudit 확장으로 엔진단 감사 로그를 남깁니다. 앱이 직접 암호 서명을 유지검증하지 않아도, DB 엔진 수준에서 “누가, 언제, 무엇을”을 기록할 수 있습니다.
- 서명키API 키 같은 비밀은 앱이 들고 있으면 안 됩니다. 이 값들은 AWS Secrets Manager로 옮겨 컨테이너에 환경변수로 주입하고, 코드, 이미지, 저장소에는 절대 두지 않습니다.
그래서 저희는 앱단 서명 영수증 서브시스템을 걷어내고, 감사를 RDS 엔진단 감사(pgaudit)로, 비밀 관리를 Secrets Manager로 이전했습니다. 감사와 인가는 원래 별개의 관심사였고, 프로토타입에서 한 데코레이터로 묶여 있던 것을 이 과정에서 분리했습니다. RBAC/Cedar 인가 계층(3지점 enforcement, 마스킹)은 그대로입니다. 바뀐 것은 “기록을 어디에 어떻게 남기는가”이지, “누구에게 무엇을 보여줄 것인가”가 아닙니다.
이 전환을 “더 강한 보안”으로 포장하지는 않겠습니다. 성격이 다른 트레이드오프에 가깝습니다. 서명 해시체인은 암호학적 위변조 증명(non-repudiation)을 주고, 엔진단 감사는 접근 제어에 기반한 위변조 저항을 줍니다. 온프렘 단일 노드에서는 앱만으로 위변조 증명을 얻는 서명 영수증이 맞는 선택이었고, 다중 컨테이너, 관리형 RDS 환경에서는 암호학적 증명을 내려놓는 대신 엔진단 감사와 접근 제어(IAM, Secrets Manager)로 운영을 단순화하고 다중 컨테이너 동시 쓰기 문제까지 함께 해결하는 쪽을 택했습니다. 근거가 바뀐 지점에서 결정을 갱신한 이 과정도 결정 기록으로 남겼습니다.
라이브 DB 조회 자체의 안전장치는 그대로입니다. 1차 보증은 접속 계정이 읽기 전용이고 허용 문장이 단일 SELECT/WITH로 제한된다는 점이며, 그 위에 SQL 정책 파서가 금지 토큰과 필수 조건을 한 번 더 검사해 방어를 겹쳐 둡니다. 이 파서는 정규식 기반이라 어디까지나 2차 방어입니다.
6. 이미 회사의 토대입니다
이 게이트웨이는 “언젠가 쓸” 시스템이 아니라, 저희 팀이 매일 쓰는 사내 AI 에이전트 체계의 토대(Layer 1) 입니다. 저희는 두 가지를 분리했습니다. 무엇을 아는가(회사 업무 지식) 는 이 DomainMCP(Layer 1)가, 어떻게 일하는가(팀의 작업 방식, 규칙) 는 공용 플러그인(Layer 2)이 담습니다. 그리고 프로젝트마다 이 둘을 얹고 차이분만 더해 피처 에이전트(Layer 3) 를 만듭니다.

핵심은 모든 계층이 지식을 자기 안에 복제하지 않고, 필요할 때 Layer 1에 런타임으로 물어본다는 점입니다. 덕분에 지식이 갱신되면 모든 에이전트가 즉시 같은 최신 사실을 봅니다. 같은 역할 에이전트(예: 백엔드)가 CMS든 WMS든 프로젝트를 가리지 않고 동작하는 것도, “이번 업무가 무엇인지”를 피처 에이전트가 알려주고 그 사실의 정확성을 DomainMCP가 책임지기 때문입니다.
바로 이 구조 덕분에, 저희는 이 토대를 사내 표준으로 굳히고 그 위에 계속 새 AI를 붙이는 방향으로 가고 있습니다. 권한이 검색 전에 막히고(누수 0), 모든 접근이 감사되며, 임베딩이 사내에 머무르기(유출 0) 때문에, 개발자 전용 도구를 넘어 비개발 부서와 사내 챗봇에까지 같은 입구를 안전하게 열 수 있습니다. 저희가 가장 공들인 결과물은 새 기능이 아니라 이렇게 안전하게 넓힐 수 있는 토대 자체입니다.
실제로 이미 Slack 챗봇이 이 게이트웨이에 붙어 운영되고 있습니다. 사내 프로젝트에서 Slack API로 만든 이 봇은, 임직원이 채널에서 질문하거나 이모지 반응으로 워크플로우를 발동하면 DomainMCP를 조회해 자동으로 답을 돌려줍니다. MCP API 키 하나로 새 소비자를 손쉽게 붙일 수 있는 구조 덕분에 가능한 일입니다. 다음 단계로 채널별 역할 권한 차등과 개인 단위 인증(Amazon Cognito, OIDC) 을 붙이면, 지금 에이전트에 적용 중인 Cedar 정책을 사람에게도 그대로 확장해 사람과 에이전트를 같은 규칙으로 평가할 수 있습니다.
7. AWS로 옮긴 것, 그리고 남은 것

저희는 이 토대를 온프렘으로 시작했지만, 사내 공용 플랫폼으로 인정받으면서 상태, 감사, 배포 계층을 실제로 AWS 관리형으로 이전했습니다. 원칙은 하나였습니다. 불필요한 상시 고정비는 만들지 않되, 관리형이 더 잘 맞는 곳은 관리형에 맡긴다는 것입니다.
7-1. 배포: Windows 상주 서비스에서 리눅스 컨테이너 CI/CD로
프로토타입은 Windows 서버에서 상주 서비스로 돌았습니다. 이번에 운영체제를 리눅스로 옮기고, 그 위에서 Docker 컨테이너로 서빙하는 구조로 바꿨습니다. 이미지는 Amazon ECR(컨테이너 이미지 레지스트리)에 올리고, Amazon ECS(Fargate)의 리눅스 컨테이너로 실행합니다.
OS를 옮기면서 Windows 전용이던 부분도 함께 정리했습니다. 비밀번호 암호화에 쓰던 Windows DPAPI를 걷어내고 앞서 말한 Secrets Manager 주입으로 일원화했고, 라이브 DB 조회는 리눅스용 Microsoft ODBC Driver 18로 대체했습니다. 배포는 코드를 main에 머지하면 GitHub Actions가 OIDC로 AWS에 로그인해 이미지 빌드, ECR push, ECS 롤링 배포까지 자동으로 수행합니다(사내 공유 배포 파이프라인 사용, 시크릿 없이 무중단). 헬스체크 기반 롤링 업데이트라 다운타임도 없습니다.
7-2. 저장: 임베디드 벡터DB에서 중앙 pgvector로
프로토타입에서 벡터는 애플리케이션 프로세스 안의 임베디드 저장소(LanceDB)에 있었습니다. 사내에서 플랫폼 가치를 인정받아 중앙 인프라를 제공받으면서, 저희는 dense 벡터를 Amazon RDS for PostgreSQL 16 + pgvector로 이전했습니다. 이미 만들어 둔 벡터를 재임베딩 없이 그대로 옮겼고, 행 수, 벡터 스팟체크, 동일 쿼리벡터 top-10 대조의 3중 검증을 반복 통과한 뒤 임베디드 저장소를 제거했습니다. 이 덕분에 여러 컨테이너가 하나의 벡터, 감사 저장소를 공유하며 수평 확장할 수 있습니다(키워드 인덱스 FTS5는 부팅 시 S3에서 받아오는 read-only 아티팩트로 유지).
7-3. 감사, 비밀: 앱단 서명에서 관리형으로
5절에서 설명한 대로, 앱단 Ed25519 서명 영수증을 RDS 엔진단 감사(pgaudit)로, 서명키, API 키, DB 비밀번호를 AWS Secrets Manager로 이전했습니다. 다중 컨테이너 동시 쓰기 문제와 키 보관 문제를 관리형 서비스가 함께 해결합니다.
7-4. 성능: 콜드 지연 약 28초에서 평균 8.4초로
가장 체감이 큰 개선은 콜드 지연입니다. 새 세션의 첫 질문은 검색 품질을 담당하는 온프렘 모델 2개(임베딩 BGE-M3 + 리랭커, 합쳐 수 GB)를 메모리로 올리느라, 예전에는 모든 새 세션에서 약 28초가 걸렸습니다. 저희는 상시 워밍업과 주기적 keepalive로 모델을 항상 메모리에 상주시키고, 리랭킹 비용 노브(후보 수, 문서 길이 상한)로 신규 질의의 크로스인코더 부담을 낮췄습니다. 이제 콜드는 예외가 됐습니다. 대부분의 첫 질문은 이미 warm이라 0.1초 안팎이고, 워밍업이 놓친 진짜 콜드 질의만 평균 8.4초(대략 8.0~9.4초)로, 예전 약 28초에서 크게 내려왔습니다.
| 검색 구성 (현재) | p50 | p90 |
|---|---|---|
| 키워드(BM25) | 7ms | 24ms |
| + 벡터(pgvector) | 수 ms~수십 ms | — |
| + 리랭킹 (처음 보는 질의) | 평균 8.4초 (과거 약 28초) | 9.4초 |
최종 답변은 게이트웨이가 만들지 않습니다. 현재도 소비자 측은 Amazon Bedrock의 Claude로 인용된 근거 위에서 답을 합성합니다. 게이트웨이는 검색과 출처 인용까지만 책임지므로, 환각과 정책의 책임 경계가 깨끗하게 나뉩니다. 앞서 말한 “egress 0″은 게이트웨이의 색인, 검색이 데이터를 밖으로 내보내지 않는다는 뜻이고, 답 합성을 위해 인용 근거를 Bedrock으로 보내는 것은 소비자 쪽 책임 경계에 속합니다. 이 Bedrock 연동은 저희가 이미 운영 중인 AWS 접점입니다.
7-5. 앞으로
현재 구조와 성능에는 만족하고 있고, 이대로 운영하고 있습니다. 콜드 지연을 평균 8초대까지 줄이고 나니, 하루 수백 건 남짓한 사내 트래픽에는 지금처럼 컨테이너 안에서 검색을 처리하는 것으로도 충분하다는 것이 내부 판단입니다.
다만 앞으로 코퍼스가 크게 늘거나 리랭킹에 더 빠른 속도가 필요해지면, 검색 연산(리랭킹, 쿼리 임베딩)을 Amazon Bedrock 같은 관리형 서비스로 옮기는 선택지도 열어 두고 있습니다. 상시 GPU 같은 고정비 없이 필요할 때만 호출하는 방식이라 2절에서 지킨 원칙과도 맞습니다. 지금 당장 도입할 계획은 아니고, 필요가 분명해지는 시점에 검토할 생각입니다.
8. 맺으며
저희가 가장 신경 쓴 것은 검색 성능 자체가 아니라, 권한대로 누수 없이 감사되며 정확하게 검색한다는 신뢰의 토대였습니다. 작은 팀이 보안과 감사를 1일차 설계에 넣은 채 약 3주 만에 그 토대를 세울 수 있었던 힘은 AI-DLC에 있었다고 봅니다. 방법론이 정해진 순서를 강제한 덕분에, 혼자였다면 놓치거나 뒤로 미뤘을 모호한 지점과 빈틈을 초기에 끄집어내 아키텍처를 더 단단하게 잡을 수 있었습니다.
무엇보다 저희는 현재 규모에 가장 비용 효율적인 온프렘, 임베디드 구조로 첫 삽을 뜨고, 그것이 사내 공용 플랫폼으로 인정받은 뒤 상태, 감사, 배포 계층을 AWS 관리형으로 이전했습니다. 이전할 때도 원칙은 그대로였습니다. 불필요한 상시 고정비는 만들지 않되, 관리형이 더 잘 맞는 곳(RDS pgvector, 엔진단 감사, Secrets Manager, ECS Fargate)은 관리형에 맡깁니다. 지금은 검색부터 답 합성(Amazon Bedrock의 Claude)까지 이 구조로 안정적으로 돌고 있고, 더 큰 규모나 속도가 필요해지면 검색 연산도 관리형으로 옮기는 선택지를 열어 두었습니다. 근거로 결정하고 실측으로 확장한다는 것이, 저희가 이 공용 지식 토대를 만들어 온 방식입니다.