[MRM 스레드] 에피소드 5 — RAG + LanceDB · 감사 인프라가 결국 검색 문제인 이유
EN English version →“MRM 스레드” 5편. 지난 에피소드 4에서는 아키텍처가 추론의 부산물로 설명을 산출해 내기 때문에, 감사 로그가 매 예측마다 구조화된 설명(게이트 가중치, CEH 기여도, 마할라노비스 OOD 플래그)을 담을 수 있다는 점을 정리했다. 이번 에피소드 5에서는 한 계층 더 위로 올라가, 그 로그가 어떻게 질의되는지 살펴본다. 우리가 가장 피하고 싶었던 실수는 감사 로그를 분기에 한 번씩 누군가 일괄으로 읽어보는 ‘쓰기 전용 저장소’로 취급하는 것이었다. 감사 로그가 실시간으로 질의 가능한 지식 베이스가 되어야만, 우리가 이 시스템을 구축한 다른 모든 목적들이 제대로 작동할 수 있다.
인적 감독 큐의 어느 시나리오
리스크 담당자가 밤 10시 30분에 on-call 대기 중이다. 이때 HumanReviewQueue가 Tier-2 알림을 띄운다. 어느 고객에 대한 추천 한 건이 Causal Guardrail (에피소드 4의 마할라노비스 OOD 플래그) 발동으로 인해 에스컬레이션된 것이다. 담당자는 5분 안에 모델의 결정을 덮어쓸 것인지, 야간 검토를 위해 대기시킬 것인지, 아니면 그대로 통과시킬 것인지 결정해야 한다.
이 긴박한 순간, 담당자에게 필요한 정보는 다음과 같다:
- 해당 예측의 전체 기록 (입력 피처, 게이트 가중치, CEH 기여도, OOD 거리 점수)
- 과거의 유사한 예측들 (같은 고객이거나 비슷한 피처 패턴을 보였을 때, 과거에 모델은 어떤 결론을 내렸는가?)
- 최근 동일 상품 카테고리에서 OOD 플래그가 켜진 예측들 (이것이 이례적인 단일 사건인가, 아니면 데이터 드리프트의 신호인가?)
- 현재 모델 버전의 학습 데이터 스냅샷 기준점 (입력값이 실제로 모델이 학습한 범위를 벗어났는지 확인하기 위한 건전성 검증용)
이 네 가지 요구사항 중 세 가지가 단순한 단일 레코드 조회가 아닌 검색 쿼리다. 기본 키로 단건을 찾는 것이 아니라, 유사도 조건과 시간 윈도우가 포함된 복합적인 검색이다.
만약 감사 로그가 평면적인 추가 전용 Parquet 테이블 구조라면, 이 쿼리들을 처리하기 위해 전체 스캔이 발생하여 수 분이 걸리게 되고 담당자의 5분 결정 윈도우는 무너지고 만다. 하지만 감사 로그가 벡터 인식 컬럼형 저장소 위에서 RAG 형태로 노출되면, 이 모든 검색이 단 몇 초 안에 끝난다.
감사 로그가 쓰기 전용이 아닌 이유
금융권에서 감사 로그를 바라보는 기본적인 멘탈 모델은 *‘규제 당국 제출용 아카이브’*다. 이벤트 발생 시점에 로그를 기록하고, 각 엔트리에 해시 체인(에피소드 3 참고)을 걸어 무결성을 확보하며, 규정이 요구하는 기간(에피소드 4의 5년 보존 케이스 등) 동안 보관하다가 요청이 오면 응답하는 식이다. 읽기 접근은 매우 드물며, 주로 일괄 처리 방식으로 이루어진다.
하지만 AI MRM(모델 리스크 관리) 환경에서는 이러한 전통적 모델이 다음 세 가지 이유로 깨지게 된다.
1. 실시간 감독에는 실시간 검색이 필요하다. 앞선 예시처럼 5분 안에 유사 케이스의 맥락을 파악해야 하는 리스크 담당자의 업무는 분기별 일괄 쿼리가 아니다. 이는 대화형 의사결정 지원 워크로드이며, 매우 엄격한 지연 시간 요건을 가진다. 감사 로그를 단순한 콜드 스토리지로 취급하면, 감독 팀은 검색을 위해 별도의 작업용 저장소를 구축해야만 한다. 이는 곧 ‘단일 진실 공급원’ 원칙을 훼손하며, 두 저장소 간의 데이터 불일치 문제를 야기한다.
2. 공정성 모니터링은 운영 스트림 위에서 실행된다. 이질적 영향 (Disparate Impact), 통계적 패리티 차이 (Statistical Parity Difference), 균등 기회 차이 (Equal Opportunity Difference) 같은 공정성 지표들은 분기에 한 번 검증 샘플 위에서 계산되고 끝나는 것이 아니다. 공정성을 진지하게 다루는 운영 AI 시스템이라면, 실제 추론 스트림 위에서 보호 속성 그룹별로 연속적으로 계산되어야 한다. 그리고 그 추론 스트림의 원천 데이터는 바로 감사 로그 안에 존재한다. 만약 감사 로그가 near-real-time 으로 질의 불가능하다면, 공정성 모니터링 시스템은 시차가 있는 낡은 프록시 데이터를 사용하거나 별도의 중복 스트림을 유지해야만 한다.
3. 규제 산출물 생성 자체가 하나의 쿼리다. 에피소드 4에서 5가지 규제 산출물 생성기(한국 AI 기본법 FRIA, EU AI Act FRIA, Annex IV, 개인정보 영향평가, 금융위 공시)를 다루며 이 논지를 이미 펼친 바 있다. 각 생성기는 감사 로그 위에서 실행되는 집계 쿼리로 동작한다. 만약 이 쿼리가 완료되는 데 몇 시간이 걸린다면, 분기별 산출물 파이프라인은 누구도 쉽게 디버깅할 수 없는 무거운 batch job이 되어버린다. 반면 단 몇 초 안에 끝난다면, 생성기 로직이 변경될 때마다 on-demand로 즉시 재실행하고 결과를 확인할 수 있다.
감사 로그는 단순히 데이터가 묻히는 최종 목적지가 아니다. 시스템 내의 다른 모든 컴포넌트가 적극적으로 질의하는 단일 진실 공급원이어야 한다.
두 저장소 운영이라는 안티 패턴
감사 로그가 실시간 쿼리에 너무 느리다는 사실을 깨달은 개발 팀이 흔히 빠지는 함정은 두 번째 저장소를 구축하는 것이다. 즉, 감사 로그는 불변의 Parquet 아카이브로 남겨두고, 운영 쿼리를 위해 별도의 PostgreSQL이나 Elasticsearch를 띄운 뒤 CDC(Change Data Capture)나 일괄 작업으로 두 저장소를 동기화하는 방식이다.
이 방식의 치명적인 문제는 데이터 불일치다. 두 저장소는 필연적으로 동일한 이벤트에 대해 미묘하게 다른 뷰를 갖게 된다. 동기화 지연, 스키마 드리프트, 복제 실패, 보존 정책의 불일치 등 이 모든 것이 외부 감독관의 눈에 띄는 ‘감사 로그와 운영 데이터 간의 불일치’ 요인이 된다. 더 큰 문제는 6개월 뒤 그 불일치가 발견되었을 때, 두 저장소 중 어느 쪽도 왜 그런 차이가 발생했는지 명확히 설명하지 못한다는 점이다.
그래서 우리는 단일 저장소 원칙을 고수한다. 감사 로그가 유일한 기록의 원천이며, 운영 쿼리는 그 로그 위에서 직접 실행되어야 한다. 이 원칙은 기술적 부담을 스토리지 계층으로 고스란히 떠넘긴다. 스토리지는 컴플라이언스를 위한 불변의 추가 전용 쓰기 성능과, 운영을 위한 빠른 인덱싱 검색을 동시에 지원해야만 한다. LanceDB는 바로 이 까다로운 양립을 가능하게 만들어준 선택이었다.
LanceDB를 선택한 이유
이 복합적인 워크로드를 소화하는 데 있어 간과하기 쉽지만 매우 중요한 LanceDB의 몇 가지 속성이 있다.
1. 벡터 네이티브 인덱싱과 컬럼형 저장. LanceDB는 데이터를 Apache Arrow 기반의 컬럼형 포맷으로 저장한다. 이는 특정 시간 범위 필터링, 보호 속성별 집계, 불필요한 데이터를 건너뛰는 단일 컬럼 스캔 등 감사 로그 분석 쿼리에 최적화된 구조다. 더욱이 그 위에 IVF-PQ 벡터 인덱스를 네이티브로 지원하기 때문에, 설명 컬럼(매 예측의 게이트 가중치와 CEH 기여도)을 단순한 일치 검색이 아닌 벡터 유사도 기반으로 검색할 수 있다.
2. 버전을 인식하는 시간 여행. 데이터가 쓰일 때마다 버전이 관리되는 새로운 스냅샷이 생성된다. 즉, 현재 시점의 감사 로그뿐만 아니라 2026-04-15 14:00:00 UTC 시점의 감사 로그에도 정확히 질의할 수 있다. 이 기능이야말로 감독관의 15개월 전 과거 재구성 쿼리가 완벽하게 작동하게 만드는 핵심이다. 특정 시점의 모델 레지스트리, 추론 로그, 기여도 로그가 시간의 오차 없이 일관되게 join된다.
3. 설계 단계부터 내재된 추가 전용 구조. 새로운 쓰기 작업은 항상 새로운 버전을 생성할 뿐, 기존 버전을 덮어쓰지 않는다. 이 속성이 에피소드 3에서 다룬 HMAC 해시 체인과 결합하면, 감사 로그에 필수적인 불변성 요건을 스토리지 계층과의 기술적 충돌 없이 자연스럽게 달성할 수 있다.
4. 가벼운 임베디드 환경. 별도의 클러스터나 전담 operator가 필요하지 않다. in-process 혹은 사이드카 형태로 가볍게 실행된다. 운영 및 감사 인프라 관리가 야간 당직자 한 명의 여러 업무 중 하나일 뿐인 소규모 팀에게, 이 가벼움은 겉보기보다 훨씬 더 결정적인 장점이다.
물론 이 선택에 따른 비용(단점)도 실재한다. LanceDB는 PostgreSQL이나 Elasticsearch에 비해 역사가 짧고, 운영자를 위한 도구의 성숙도가 낮으며, 커뮤니티 생태계도 작다. 하지만 우리는 두 개의 저장소를 유지하며 발생하는 데이터 불일치의 위험을 감수하느니, 단일 저장소를 유지하기 위해 이 정도의 초기 도입 비용을 지불하는 것이 낫다고 판단했다.
설명 컬럼 위의 RAG (Retrieval-Augmented Generation)
retrieval-augmented 요소는 실시간 인적 감독 워크플로우를 실제로 구동 가능하게 만드는 핵심이다.
리스크 담당자가 OOD 플래그가 발동된 특정 예측 건을 검토할 때, RAG 계층은 그 예측의 설명 벡터(7차원의 게이트 가중치 벡터 + CEH 기여도의 sparse 피처 벡터 + OOD 거리 스칼라값)를 추출하여 최근 90일간의 전체 추천 기록 위에서 벡터 유사도 검색을 수행한다. 그 결과로 고객 ID나 추천 상품의 종류와는 무관하게, 추론 방식 자체가 구조적으로 유사한 과거 예측들의 랭킹 리스트를 지정된 시간 윈도우 내에서 즉시 반환한다.
이것은 단순한 SQL의 WHERE customer_id = X 쿼리가 아니다. *“모델이 이번과 같은 방식으로 사고 과정을 거쳐 결론을 내렸던 예측들을 모두 찾아라”*라는 의미에 가깝다. 현재 발생한 OOD 플래그가 일회성 이상치인지 아니면 새롭게 등장한 패턴인지를 결정해야 하는 담당자에게, 이것은 정확히 시스템이 답해주어야 할 핵심 질문이다.
이러한 벡터 검색 패턴은 감독 업무뿐만 아니라 다음 세 가지 주요 워크로드에도 동일하게 서비스된다.
- 데이터 드리프트 탐지: 이번 주에 발생한 예측들이 지난 분기와 동일한 전문가 모델 조합 비율을 보이고 있는가? 게이트 가중치 벡터 분포의 시간적 변화를 추적하면, 전통적인 드리프트 지표들이 이상을 감지하기 몇 주 전부터 이미 피처 분포의 변화를 선행 지표로서 알아차릴 수 있다.
- 반사실적 검토: 특정 추천이 발생했을 때, 만약 입력 피처 중 하나를 살짝 변경했다면 이와 유사한 고객들은 과연 어떤 추천을 받았을까? RAG가 비교 대상이 될 데이터 셋을 검색해 오면, 반사실적 평가 계층(Paper 2 참조)이 그 위에서 비교 연산을 수행한다.
- 설명 일관성 체크: 모델이 유사한 입력에 대해 과연 유사한 ‘설명’을 내놓고 있는가? 설명 컬럼 위에서 동작하는 RAG는 단순히 출력값이 일관된지를 넘어, 모델의 추론 과정 자체가 안정적인지를 검증하게 해준다. 이는 단순한 출력 일관성보다 훨씬 더 엄격하고 수준 높은 속성이다.
실시간 공정성 파이프라인
연속 공정성 모니터링 모듈은 감사 로그 위에서 보호 속성 슬라이스를 대상으로 하는 스트리밍 쿼리 형태로 동작한다. 성별, 연령대, 지역, 소득 계층, 장애 여부라는 5가지 보호 속성별 이질적 영향 (Disparate Impact) 수치가, 정제된 검증 샘플이 아닌 실제 운영 중인 예측 데이터의 최근 24시간 롤링 윈도우 위에서 실시간으로 계산된다.
하부에 LanceDB가 탄탄하게 깔려 있기에 비로소 가능해진 두 가지 설계적 이점은 다음과 같다.
1. 반사실적 챔피언-챌린저 비교: 공정성 계층은 단순히 *“현재 운영 중인 챔피언 모델이 공정한가?”*만 묻지 않는다. 나아가 *“만약 챌린저 모델이 같은 운영 스트림을 처리했다면 더 공정했을까, 덜 공정했을까?”*를 묻는다. RAG가 현재 운영 스트림에서 매칭된 입력 batch를 검색해 오면, 챌린저 모델이 그 데이터를 바탕으로 오프라인 예측을 수행하고 챔피언과 공정성을 비교한다. 이 비교 결과가 담긴 Parquet 아카이브 역시 LanceDB 테이블로 저장되므로, 일반 추론 로그와 완전히 동일한 방식으로 질의하고 분석할 수 있다.
2. 실시간 임계값 위반 알림: 특정 보호 속성 그룹이 롤링 윈도우 내에서 공정성 허용 임계값을 위반하면, HumanReviewQueue에 즉시 최고 수준인 Tier-3 알림이 전송된다. 이는 OOD 플래그가 켜진 예측들이 흘러가는 것과 동일한 큐이며, 단지 심각도 단계만 다를 뿐이다. 두 종류의 알림 모두 기저의 동일한 검색 인프라를 타고 흐른다.
여기서 중요한 점은 우리가 단순히 화려한 공정성 모니터링 대시보드를 구축했다는 사실이 아니다. 인적 감독과 로깅 등 다른 필수적인 목적을 위해 검색 인프라를 탄탄하게 구축해 둔 덕분에, 실시간 공정성 모니터링을 구현하는 비용이 극적으로 저렴해졌다는 것이 핵심이다. 훌륭한 인프라 아키텍처의 선택은 언제나 이런 식이다. 처음에는 전혀 의도하지 않았던 영역에서조차 지속적으로 아키텍처의 dividend을 창출해 낸다.
인적 감독(Oversight) 파이프라인
EU AI Act 제14조가 요구하는 ‘인적 감독’ 의무는 우리 시스템에서 단순한 티켓 처리 큐가 아니라, 명확한 API 엔드포인트의 집합으로 구현되어 작동한다. 이는 다음 세 가지 흐름으로 나뉜다.
1. 킬 스위치(Kill Switch): 시스템 전체의 새로운 예측을 즉시 중단시키는 강력한 기능이다. 철저한 보안을 위해 운영자의 2단계 인증(2FA)을 거친 단일 API 호출로만 실행된다. 킬 스위치가 발동되는 이벤트 그 자체도 감사 로그의 log_operation 테이블에 기록되므로, 시스템을 중단시킨 정확한 이유와 맥락이 나중에 언제든 복구되고 감사될 수 있다.
2. Tier 2 및 Tier 3 에스컬레이션: 인적 검토 큐는 심각도에 따라 계층화되어 있다. Tier 2는 OOD 플래그가 발동되거나, 특정 그룹의 공정성 지표가 임계값에 근접하거나, 감사 에이전트 간의 합의 중재(에피소드 3 참고)에서 소수 의견이 발생했을 때 발령된다. 반면 Tier 3은 공정성 임계값이 실제로 위반되거나, 다수의 연관된 예측에서 동시다발적으로 OOD 플래그가 켜지거나, 킬 스위치가 발동되는 등 심각한 비상 상황을 의미한다. 각 단계는 자체적인 검색 템플릿을 가지고 있으며, 담당자는 해당 상황의 맥락을 파악하기 위해 시스템이 미리 검색해 둔 유사 케이스 데이터들을 제공받는다.
3. 자동 승격 금지(auto_promote=false) 원칙: 모델을 운영 환경으로 승격시키려면 반드시 운영자의 명시적인 승인이 필요하다(에피소드 2의 챔피언-챌린저 구조 참고). 이 권한이 인적 감독 섹션에 속하는 이유는, 운영자의 승인 결정 과정 자체가 감사 로그 위에서 이루어지는 하나의 쿼리이기 때문이다. 챌린저 모델의 공정성 지표는 모두 녹색(안전)이었는가? 테스트 기간 동안 비정상적인 OOD 플래그 발동은 없었는가? 합의 중재자는 어떤 의견을 내놓았는가? RAG는 승인 인터페이스의 이면에서 이러한 결정적 맥락들을 한데 묶어 제공함으로써, 운영자가 데이터에 기반한 현명한 결정을 내릴 수 있도록 도우면서도 정보의 과부하를 막아준다.
이 세 가지 흐름의 결과는 모두 빠짐없이 감사 로그에 다시 기록된다. 즉, 인적 감독은 시스템 외부에서 일어나는 별개의 행위가 아니다. 감독 행위 그 자체가 시스템 내부에서 철저히 기록되며, 다른 운영 데이터와 마찬가지로 언제든 질의 가능한 대상이 된다.
여전히 풀리지 않는 과제들
감사 로그 위에서 RAG와 LanceDB를 구동하는 이 강력한 접근 방식에도 숨길 수 없는 몇 가지 기술적 한계가 존재한다.
1. 임베딩 드리프트: 설명 컬럼의 벡터 표현은 우리가 초기에 선택한 임베딩 모델과 아키텍처에 강하게 종속된다. 만약 모델 아키텍처가 크게 변경되면(새로운 전문가 모델이 추가되거나, 게이트 차원이 변경되는 등), 기존에 저장된 설명 벡터는 새로운 구조의 벡터와 더 이상 유사도를 비교할 수 없게 된다. 버전을 분리하여 임베딩 저장소를 관리하는 방식으로 대응하고 있지만, 아키텍처의 거대한 변화를 가로지르는 장기적인 횡단 검색이 동일 버전 내의 검색보다 훨씬 까다롭다는 본질적인 한계는 여전하다. 에피소드 6에서 다룰 ‘모듈성’은 이 문제를 필요 이상으로 악화시키지 않기 위한 방어 전략이기도 하다.
2. 콜드 스타트 문제: 과거의 예측 데이터가 아예 존재하지 않는 완전한 신규 배포 모델은 유사도 검색의 혜택을 누릴 수 없다. 첫 몇 주 동안은 데이터가 충분히 쌓이지 않아 인적 감독 워크플로우가 단순한 단일 레코드 조회 수준으로 격하된다. 이는 RAG 기반 시스템의 널리 알려진 한계다. 이에 대한 실무적인 우회책은 스테이징(Staging) 환경에서 대량의 합성 벤치마크 데이터를 발생시켜 설명 저장소(Store)를 미리 채워두는 것이다. 이렇게 하면 프로덕션 배포 첫날부터 RAG 시스템이 검색할 수 있는 최소한의 ‘과거 데이터’를 확보할 수 있다.
3. 쿼리 작성의 전문성 요구: 벡터 유사도 검색은 전통적인 SQL 쿼리보다 논리적으로 오류를 범하기가 훨씬 쉽다. 잘못된 거리 측정 방식을 선택하거나 부적절한 시간 윈도우를 설정한 채 *“유사한 예측을 찾아라”*라고 명령하면, 전혀 엉뚱한 결과물(False Neighbor)만 산더미처럼 반환된다. 이를 방지하기 위해 우리는 일반 운영자의 인터페이스에는 안전하게 사전 정의된 소수의 ‘검색 템플릿’만을 노출시키며, 자유롭게 질의를 입력하는 텍스트 박스는 제공하지 않는다. 비정형적인 심층 쿼리는 데이터 사이언스 팀만이 접근할 수 있는 제한된 노트북 환경을 통해서만 수행된다.
다음 이야기
에피소드 6이 이 시리즈의 마무리를 장식한다. 우리의 장기적인 핵심 명제는 분명하다. “규제는 반드시 변한다.” 한국 AI 기본법의 구체적인 시행령이 등장할 것이고, EU AI Act는 지속적으로 개정될 것이며, 미국의 새로운 규제 프레임워크가 통과되면 또 다른 형태의 전용 산출물 생성기를 요구할 것이다. 우리가 Paper 2에서 구축한 5개의 규제 산출물 생성기(한국 FRIA, EU FRIA, Annex IV, PIA, 공시 생성기)는 정적인 문서가 아니라 유연한 모듈이다. 아키텍처 전체를 뒤엎지 않고도, 변함없이 탄탄한 감사 로그 인프라 위에서 새로운 규제를 새 모듈 플러그인 형태로 부드럽게 수용하도록 설계된 모듈식 적응성에 대해 이야기한다.
소스: Paper 2 (Zenodo)의 운영 아키텍처. LanceDB의 세부적인 선택 기준과 검색 템플릿 구현체는 오픈소스 저장소의 core/audit/ 및 core/retrieval/ 디렉터리에서 확인할 수 있다.