티스토리 뷰

반응형

영업팀 신입사원이 사내 AI 어시스턴트에 "올해 연봉 인상 가이드라인이 뭐예요?"라고 물었더니, 본인은 열람 권한이 없는 인사팀 내부 문서의 내용이 친절하게 인용되어 돌아왔다. 출처 링크는 막혀 있지만, 응답 본문에 핵심 내용이 그대로 박혀 있다. 보안팀에 문의하니 "AI는 그 문서에 접근하지 않았어야 한다"는 답이 돌아온다. 그러나 모델은 이미 답했다. 이미 본 것이다.

이 사고는 추상적인 가정이 아니다. RAG(Retrieval-Augmented Generation)를 도입한 사내 챗봇과 AI 어시스턴트에서 가장 흔히 발생하는 권한 경계 붕괴 패턴이다. 검색 단계에서 사용자 권한을 강제하지 않으면, 모델 응답이 곧 권한 우회 경로가 된다. 이 글은 RAG 권한 경계가 무너지는 구조와, 운영자가 어떤 지점에서 경계를 다시 세워야 하는지를 정리한다.

요약

RAG 시스템에서 벡터 검색은 기본적으로 권한 개념이 없다. 사내 문서를 임베딩한 순간 원본의 ACL이 사라지고, 검색은 "의미가 가까운 문서"를 반환할 뿐 "이 사용자가 볼 수 있는 문서"를 반환하지 않는다. 권한 경계는 검색 결과를 모델에 전달하기 전에 강제되어야 하며, 가장 흔한 안티패턴은 검색 후 필터링(post-filtering)이다. 실무에서는 사용자 신원 전파, 메타데이터 기반 ACL, 인덱싱 시점 권한 동기화, 감사 로그 네 축을 함께 설계해야 권한 경계가 유지된다.

이 글이 필요한 사람

사내 위키, 인사 시스템, 영업 자료, 고객 문서, 계약서를 데이터 소스로 사용하는 RAG 챗봇이나 AI 에이전트를 만들고 있고, 검색·임베딩·권한 경계 설계를 책임지는 백엔드 엔지니어, 플랫폼 엔지니어, 보안 담당자.

왜 지금 이 주제인가

엔터프라이즈 보안 리뷰에서 RAG 도입 프로젝트가 가장 자주 막히는 지점은 모델의 정확도가 아니라 문서 단위 권한 강제(document-level permission enforcement)이다. Google Drive, Confluence, SharePoint, Notion 같은 소스의 ACL을 벡터 인덱스로 가져오지 못하면, AI 어시스턴트가 곧 권한 우회 도구가 된다.

여기에 두 가지 흐름이 더해진다. 첫째, Azure AI Search는 2026-05-01-preview API에서 SharePoint ACL을 인덱스에 동기화하고 쿼리 시점에 사용자 토큰의 Entra 주체를 ACL과 매칭하는 문서 단위 접근 제어를 제공한다. 둘째, Amazon Bedrock Knowledge Bases는 metadata filtering으로 사용자 속성과 문서 속성을 매칭해 다중 테넌트와 권한 경계를 강제하는 방향으로 정리되고 있다. 즉 클라우드 제공사 자체가 "RAG는 검색 단계에서 권한이 강제되어야 한다"는 입장을 표준화하는 중이다.

문제는 많은 팀이 여전히 옛 패턴으로 시스템을 만들고 있다는 점이다. 임베딩, 검색, 프롬프트 합성, 응답까지 한번 굴려 본 뒤 권한은 "나중에 붙이는 미들웨어"로 미룬다. 그 미들웨어는 보통 응답 후 출처 링크에만 적용되고, 본문은 이미 권한 밖의 정보를 담은 채로 사용자에게 도착한다.

RAG 권한 경계가 무너지는 4가지 구조

1. 임베딩 시점에 ACL이 사라진다

원본 문서에는 누가 볼 수 있는지가 ACL로 정의되어 있다. 그러나 문서를 청크로 자르고 벡터로 변환해 인덱스에 넣는 순간, 이 ACL 정보는 사라진다. 벡터 인덱스는 "의미가 가까운가"만 본다. 인사팀 문서의 청크와 영업팀 문서의 청크가 같은 인덱스에 섞여 있고, 검색은 두 청크를 동일한 자격으로 평가한다.

이 단계에서 ACL을 함께 임베딩 메타데이터로 동기화하지 않으면, 그다음에 무엇을 해도 권한 경계가 회복되지 않는다. 사용자 권한과 매칭할 수 있는 키 자체가 인덱스에 없기 때문이다.

2. 사용자 신원이 검색까지 전파되지 않는다

게이트웨이 앞에서는 JWT나 OAuth 토큰으로 인증이 끝나 있지만, 그 신원이 검색 호출까지 도달하지 않는 경우가 많다. RAG 파이프라인이 백엔드 서비스 계정 하나로 벡터 DB에 접근하고, 결과는 모두 같은 권한으로 끌어온다. 모델 응답에 "이 사용자에게만 보여야 할 정보"를 거르는 코드는 그 뒤 어디에도 없다.

신원 전파는 RAG 권한 설계의 출발점이다. 사용자 ID, 소속 그룹, 역할, 데이터 분류 등급이 검색 쿼리에 함께 실려야, 인덱스의 메타데이터 필터가 의미를 갖는다.

3. Post-filtering이라는 위험한 안티패턴

검색 결과를 먼저 가져온 뒤 응답 단계에서 "이 사용자에게는 안 보여줘야 할 청크"를 잘라내는 패턴이 자주 보인다. 빠르고 구현이 쉬워 보이지만, 이 구조는 두 가지 문제를 동시에 만든다.

첫째, 모델은 이미 그 청크를 컨텍스트로 받아 답을 만든다. 출처를 가려도, 모델 응답 본문에는 금지된 문서의 요지가 녹아 있다. 둘째, 권한 외 문서가 검색 결과에 포함된다는 사실 자체가 정보가 된다. "검색은 됐는데 보여주지 않는다"는 것이 곧 "그런 문서가 존재한다"는 신호다.

엔터프라이즈 RAG에서 권장되는 패턴은 검색 자체를 권한 범위 안에서만 수행하는 pre-filtering이다. 사용자 식별자를 검색 쿼리에 결합하고, 벡터 인덱스는 권한 메타데이터로 1차 필터링된 부분 공간에서만 ANN 검색을 수행한다.

4. 권한 변화가 인덱스에 따라잡지 못한다

ACL은 살아 있는 데이터다. 직원이 부서를 옮기고, 프로젝트 권한이 종료되고, 외부 협력사가 계약을 마친다. 그러나 벡터 인덱스의 권한 메타데이터는 종종 한 번 임베딩할 때의 스냅샷으로 고정된다. 그 결과 권한이 끊긴 사용자가 여전히 옛 권한으로 검색 결과를 받는다.

Azure AI Search가 SharePoint 인덱서에서 ACL 변경을 인덱서 실행마다 다시 동기화하도록 한 이유가 여기에 있다. 권한 동기화는 1회성 작업이 아니라 인덱싱 파이프라인의 일부로 설계되어야 한다.

권한 경계를 다시 세우는 4가지 축

신원 전파(Identity Propagation)

게이트웨이에서 인증된 사용자 신원을 검색 호출까지 전달한다. 호출 체인이 길어도 사용자 식별자, 소속 그룹, 역할은 컨텍스트로 따라간다. 백엔드 서비스 계정 하나로 모든 검색을 수행하지 않는다.

메타데이터 ACL과 Pre-filtering

문서를 임베딩할 때 원본의 ACL 정보를 함께 메타데이터로 인덱싱한다. 검색 쿼리에는 사용자 식별자와 그룹을 함께 넣어, 권한이 있는 청크 부분 공간에서만 ANN 검색이 일어나도록 강제한다. AWS에서는 Bedrock Knowledge Bases의 metadata filtering, Azure에서는 AI Search의 security trimming이나 SharePoint ACL 인덱서, OSS 스택에서는 pgvector의 Row Level Security와 OPA·Cedar 같은 정책 엔진이 이 역할을 한다.

인덱싱 파이프라인의 ACL 동기화

ACL 변경은 인덱서가 주기적으로 다시 가져온다. 부서 이동, 프로젝트 종료, 외부 협력사 계약 만료 같은 이벤트가 인덱스에 반영되는 SLA를 정한다. 동기화 지연이 곧 권한 경계의 구멍이라는 사실을 모니터링 지표로 추적한다.

감사 로그와 출처 검증

요청·검색·응답을 한 묶음으로 감사 로그에 남긴다. 어떤 사용자 권한으로 어떤 문서 ID가 검색되었고, 어떤 청크가 모델에 전달되었으며, 응답에 어떤 출처가 표시되었는지를 추적할 수 있어야 한다. 권한 사고가 발생했을 때 "검색은 정상이었는가" "필터링은 어디서 깨졌는가"를 분리해 분석할 수 있어야 한다.

AWS / Azure 관점

AWS:

  • Amazon Bedrock Knowledge Bases의 metadata filtering으로 문서 속성(부서, 분류 등급, 테넌트 ID)과 사용자 속성을 매칭해 검색 단계에서 1차 권한 필터를 강제한다.
  • Amazon Verified Permissions(Cedar 기반)와 결합해 검색 호출 직전에 인가 결정을 수행하고, 결과 메타데이터에 어떤 정책이 적용되었는지 남긴다.
  • OpenSearch ServiceAurora pgvector를 벡터 저장소로 사용할 때는 인덱스 메타데이터 필터와 RLS, IAM Identity Center의 사용자 속성 전파를 함께 설계한다.
  • 감사 로그는 CloudTrail, CloudWatch Logs, OpenSearch Audit Logs로 분산되기 쉽다. RAG 한 요청을 재구성할 수 있는 상관관계 ID를 표준 스키마에 포함한다.

Azure:

  • Azure AI Search의 문서 단위 접근 제어는 2026-05-01-preview API에서 SharePoint ACL을 인덱서가 동기화하고, 쿼리 시점에 사용자 Entra 토큰의 주체를 ACL과 매칭한다. 빌트인 ACL을 쓰기 어려운 데이터 소스에는 search.in() 기반 security trimming 패턴을 사용한다.
  • Microsoft Purview의 sensitivity label과 DLP 정책을 인덱스 메타데이터에 매핑해, 라벨 기반 접근 제어를 검색 단계까지 끌어온다.
  • Microsoft Entra의 그룹·역할 정보를 검색 쿼리에 전파해 multi-tenant SaaS RAG에서도 테넌트 경계를 유지한다.
  • 감사 로그는 Log Analytics, Microsoft Sentinel에서 RAG 요청 단위로 묶고, "사용자에게 보여진 응답"과 "모델이 본 컨텍스트"를 함께 보존한다.

공통 원칙은 명확하다. 권한은 응답 단계가 아니라 검색 단계에서 강제한다. 사용자 신원은 게이트웨이에서 모델까지 끊김 없이 전파한다. ACL은 인덱싱 파이프라인의 일부로 다시 동기화한다.

실무 체크리스트

  • 사용자 신원을 게이트웨이에서 벡터 검색 호출까지 전파한다. 백엔드 서비스 계정 하나로 검색을 대신하지 않는다.
  • 문서 임베딩 시 원본 ACL을 메타데이터로 함께 인덱싱한다. 부서, 그룹, 분류 등급, 테넌트 ID, 만료일을 표준 필드로 둔다.
  • 검색은 Pre-filtering으로 수행한다. 권한 외 문서가 결과 집합에 들어왔다가 응답 단계에서 잘리는 구조를 만들지 않는다.
  • ACL 변경을 따라잡는 인덱서 SLA를 정의하고, 동기화 지연을 모니터링 지표로 노출한다.
  • 정책 결정은 코드 곳곳에 흩지 말고, OPA·Cedar 같은 정책 엔진이나 검색 서비스의 빌트인 ACL로 단일 지점에 모은다.
  • 감사 로그에 사용자 ID, 권한 정책 버전, 검색된 문서 ID, 컨텍스트로 사용된 청크 ID, 응답 출처를 함께 남긴다.
  • 다중 테넌트 RAG에서는 테넌트 식별자를 쿼리에 강제하고, 인덱스 분리·메타데이터 필터·정책 엔진 중 하나에 의존하지 않고 다층 방어로 구성한다.
  • 정기적으로 권한 회귀 테스트를 수행한다. 권한이 없는 사용자가 권한 외 문서의 내용을 응답으로 받을 수 있는지 자동으로 검증한다.

흔한 실수

  • 임베딩 후 ACL을 메타데이터로 보존하지 않음: 인덱스에 권한 키 자체가 없어 검색 단계에서 어떤 필터도 의미가 없다.
  • 출처 링크만 가리고 본문은 그대로 노출: 모델은 이미 권한 외 청크를 컨텍스트로 받아 답을 만들었기 때문에 본문에 내용이 녹아 있다.
  • Post-filtering으로 권한을 처리: 권한 외 문서의 존재 사실 자체가 정보로 새고, 모델 응답에 그 내용이 묻어 나간다.
  • 백엔드 서비스 계정 하나로 검색: 사용자 권한이 검색까지 도달하지 않아 모든 사용자가 동일한 권한으로 결과를 받는다.
  • ACL 한 번 동기화하고 끝: 부서 이동·계약 종료·프로젝트 만료가 인덱스에 반영되지 않아 권한이 사라진 사용자가 옛 결과를 계속 받는다.
  • 권한과 분류 등급을 혼동: "Confidential"이라는 라벨은 권한이 아니다. 누가 그 라벨의 문서를 볼 수 있는지 별도의 ACL이 필요하다.
  • 다중 테넌트 인덱스에 테넌트 ID를 옵션으로 둠: 누락 시 전 테넌트 데이터가 노출된다. 테넌트 ID는 옵션이 아니라 필수 필터다.

마무리

RAG의 보안 사고는 모델이 잘못 답해서 생기는 것이 아니라, 보지 말아야 할 문서가 컨텍스트로 들어가서 생긴다. 그래서 권한 경계는 모델 앞이 아니라 검색 앞에 세워야 한다. "신원은 전파한다, 권한은 인덱스 메타데이터로 강제한다, ACL은 인덱싱 파이프라인이 따라잡는다, 모든 검색은 감사 로그에 남긴다." 이 네 가지가 갖춰지면, AI 어시스턴트가 권한 우회 도구가 되는 가장 흔한 경로는 차단된다.


이 글이 유용했다면 다음 편도 확인해보세요.

다음 글: AI Agent의 Tool 호출을 안전하게 만드는 권한 모델: Read와 Write를 분리하는 이유

References

반응형
댓글
반응형
최근에 올라온 글
Total
Today
Yesterday