RAG 개인정보 보호: 문서 업로드부터 벡터DB 삭제까지 실제 설계하기
RAG 개인정보 보호는 단순히 “문서를 AI에 올리지 말자”는 문제가 아닙니다. RAG(Retrieval-Augmented Generation) 구조에서는 한 개의 문서가 원본 파일, 추출 텍스트, 여러 개의 청크, 임베딩 벡터, 메타데이터, 검색 로그처럼 여러 형태로 나뉘어 저장될 수 있습니다.
그래서 사용자가 문서를 삭제했거나 개인정보 삭제 요청이 들어왔을 때 원본 파일만 지우면 처리가 끝났다고 보기 어렵습니다. 검색 인덱스에 남은 청크, 벡터DB의 레코드, 캐시, 디버그 로그까지 함께 확인해야 합니다.
이번 글에서는 사내 문서를 검색해 답변하는 RAG 시스템을 예로 들어, 개인정보가 어디에서 생기고 어떤 지점에서 통제해야 하는지 실제 백엔드 설계 관점으로 정리해보겠습니다.
RAG에서 개인정보가 여러 번 복제되는 이유
일반적인 RAG 서비스는 문서를 그대로 모델에게 전달하지 않습니다. 먼저 파일에서 텍스트를 추출하고, 검색하기 좋은 크기로 나눈 뒤, 각 청크를 임베딩으로 변환해 벡터DB에 저장합니다.
사용자 파일
→ 텍스트 추출
→ 청크 분할
→ 임베딩 생성
→ 벡터DB 저장
→ 사용자 질문
→ 관련 청크 검색
→ 프롬프트 구성
→ 생성형 AI 응답
이 과정에서 개인정보가 존재할 수 있는 위치는 생각보다 많습니다. 원본 PDF에 이름과 이메일이 들어 있을 수 있고, 추출된 텍스트에도 그대로 남을 수 있으며, 검색 편의를 위해 metadata 필드에 작성자나 부서 정보를 넣었다면 별도의 구조화 데이터로도 존재하게 됩니다.
먼저 데이터 위치부터 목록으로 만든다
RAG 개인정보 보호를 시작할 때 가장 먼저 할 일은 모델을 바꾸는 것이 아니라 저장 위치를 표로 만드는 것입니다. 아래처럼 “무엇이 어디에 남는가”를 먼저 정리하면 삭제 정책과 접근 권한을 설계하기 쉬워집니다.
| 저장 위치 | 저장되는 예 | 개인정보 위험 | 관리 포인트 |
| 원본 파일 저장소 | PDF, DOCX, XLSX | 높음 | 접근 권한·보관기간 |
| 추출 텍스트 | 문서 전체 텍스트 | 높음 | 마스킹·삭제 동기화 |
| 청크 저장소 | 문단 단위 텍스트 | 높음 | document_id 연결 |
| 벡터DB | embedding + metadata | 중간~높음 | 원문/메타데이터 최소화 |
| 검색 캐시 | 질문·검색 결과 | 중간 | 짧은 TTL |
| 애플리케이션 로그 | request_id, 오류 | 설계에 따라 다름 | 원문 로그 금지 |
1. 업로드 단계에서 문서 범위를 먼저 줄인다
RAG 시스템에 문서를 넣기 전에 가장 효과적인 방법은 애초에 필요하지 않은 정보를 넣지 않는 것입니다. 예를 들어 사내 규정 검색이 목적이라면 직원 연락처가 포함된 부록이나 고객 명단이 들어 있는 페이지까지 색인할 필요는 없습니다.
업로드 화면에서 허용 파일 형식만 제한하는 것보다 “이 문서가 검색 대상이어야 하는가”를 판단하는 단계가 더 중요합니다. 부서 공용 규정, 업무 매뉴얼, 공개 가능한 기술 문서처럼 목적이 명확한 자료부터 RAG 데이터셋에 포함하는 것이 관리하기 쉽습니다.
2. 임베딩 전에 개인정보를 검사한다
문서를 청크로 나눈 뒤 바로 임베딩을 생성하면 이미 개인정보가 검색 인덱스에 들어간 뒤가 됩니다. 따라서 텍스트 추출 직후 또는 청크 생성 직후에 개인정보 패턴을 검사하는 단계가 필요합니다.
이메일, 전화번호처럼 일정한 형식은 자동 탐지 규칙을 적용할 수 있고, 고객명이나 프로젝트명처럼 문맥이 필요한 정보는 조직의 금칙어 목록이나 별도 분류 로직과 함께 관리할 수 있습니다.
원본 청크: “담당자 김OO / 연락처 010-1234-5678 / 장애 대응 절차 …”
색인용 청크: “담당자 [NAME] / 연락처 [PHONE] / 장애 대응 절차 …”
여기서 중요한 점은 원본 문서 자체를 무조건 변경하는 것이 아니라, “업무 원본”과 “AI 검색용 텍스트”를 분리하는 것입니다. 그러면 원본 보관 정책과 AI 검색 인덱스 정책을 각각 적용할 수 있습니다.
3. metadata에는 검색에 필요한 값만 넣는다
벡터DB는 임베딩만 저장하는 경우보다 검색 필터를 위해 metadata를 함께 저장하는 경우가 많습니다. 이때 편의를 위해 작성자 이메일, 담당자 전화번호, 고객명까지 넣기 시작하면 구조화된 개인정보 저장소가 하나 더 생깁니다.
검색 필터에 실제로 필요한 값만 남기는 편이 좋습니다. 예를 들어 아래 정도만으로도 부서별 문서 검색을 구성할 수 있습니다.
{
“document_id”: “doc_2026_00125”,
“tenant_id”: “company_a”,
“department”: “engineering”,
“category”: “operation_manual”,
“version”: 3
}
반대로 name, email, phone 같은 값이 검색 조건으로 사용되지 않는다면 metadata에 넣지 않는 편이 관리 범위를 줄일 수 있습니다.
4. 검색 권한과 문서 권한을 같은 기준으로 연결한다
RAG의 개인정보 문제는 저장뿐 아니라 검색에서도 발생합니다. 사용자가 직접 열 수 없는 문서를 RAG 검색에서는 조회할 수 있다면, 모델이 해당 내용을 답변에 포함할 수 있습니다.
따라서 “벡터DB에 들어갔으니 모두 검색 가능”한 구조보다 tenant_id, department, access_group 같은 필터를 이용해 원래 문서 접근 권한과 검색 권한을 연결하는 것이 안전합니다.
사용자 질문
→ 사용자/조직 권한 확인
→ 접근 가능한 document_id 필터
→ 벡터 검색
→ 허용된 청크만 프롬프트에 포함
이때 권한 검사는 모델에게 “이 문서는 보여주지 마”라고 프롬프트로 요청하는 것이 아니라 검색 단계에서 적용하는 것이 핵심입니다. 모델이 보기 전에 데이터 접근 자체를 제한하는 구조가 더 명확합니다.
5. 프롬프트와 검색 로그에는 원문을 남기지 않는다
RAG 장애를 분석하려다 보면 사용자의 질문과 검색된 청크 전체를 로그에 남기고 싶어집니다. 하지만 그러면 벡터DB와 별개로 로그 시스템에 개인정보가 복제됩니다.
운영 로그에서는 request_id, document_id, 검색 결과 수, latency, status 같은 기술 정보 위주로 남기고, 실제 질문 원문이나 검색된 문단 전체는 기본 로그에서 제외하는 방식이 좋습니다.
| 권장 로그 | 피해야 할 로그 |
| request_id | 사용자의 질문 전체 |
| retrieved_document_ids | 검색된 청크 원문 전체 |
| result_count | 이메일·전화번호 |
| latency_ms | AI 응답 원문 전체 |
| error_code | 업로드 문서 전체 내용 |
6. 삭제 요청은 원본부터 벡터까지 하나의 작업으로 처리한다
RAG 시스템에서 가장 놓치기 쉬운 부분이 삭제입니다. 원본 문서를 삭제한 뒤 벡터DB에 청크가 남으면 검색 결과에서 계속 노출될 수 있습니다. 반대로 벡터만 지우고 원본 파일이 남아 있어도 삭제 정책이 완성되지 않습니다.
그래서 문서마다 document_id를 하나 부여하고, 이 ID를 원본 파일, 추출 텍스트, 청크, 벡터 레코드가 모두 공유하도록 설계하면 삭제 범위를 추적하기 쉬워집니다.
delete_document(document_id)
1. 원본 파일 삭제 또는 보관정책 적용
2. 추출 텍스트 삭제
3. chunk 저장소 삭제
4. vector records 삭제
5. 검색 cache 무효화
6. 삭제 결과만 audit log에 기록
백업처럼 즉시 삭제가 어려운 저장소가 있다면 “운영 데이터 삭제”와 “백업 만료 시점”을 구분해서 문서화하는 것이 좋습니다.
7. 삭제 후에는 실제 검색 결과로 검증한다
삭제 API가 성공을 반환했다고 해서 실제 검색 결과에서 데이터가 사라졌다고 단정하면 안 됩니다. 인덱스 갱신 지연, 캐시, 비동기 작업 실패 때문에 삭제된 문서가 잠시 검색될 수 있기 때문입니다.
삭제 테스트에서는 document_id가 저장소에서 사라졌는지 확인하는 것과 함께, 해당 문서에만 존재하던 고유 문장을 질문했을 때 더 이상 검색되지 않는지도 확인하는 편이 좋습니다.
RAG 개인정보 보호 실무 점검표
RAG에 포함할 문서 범위가 정의되어 있는가?
원본 파일과 AI 검색용 텍스트를 분리하고 있는가?
임베딩 생성 전에 개인정보를 검사하는가?
벡터DB metadata에 불필요한 개인정보가 없는가?
원래 문서 권한과 벡터 검색 권한이 연결되어 있는가?
질문·검색 청크 원문을 운영 로그에 남기지 않는가?
모든 저장소가 document_id로 연결되어 있는가?
문서 삭제 시 청크·벡터·캐시도 함께 제거되는가?
삭제 이후 실제 검색 결과까지 검증하는가?

RAG 개인정보 보호에서 중요한 것은 “벡터DB만” 보는 것이 아니다
RAG 시스템은 하나의 문서를 여러 형태로 변환하기 때문에 개인정보 보호도 전체 데이터 흐름을 기준으로 설계해야 합니다. 원본 파일을 안전하게 관리해도 추출 텍스트와 청크가 남아 있으면 충분하지 않고, 벡터DB만 삭제해도 로그나 캐시에 원문이 남아 있을 수 있습니다.
가장 관리하기 쉬운 구조는 문서가 들어오는 순간부터 document_id를 기준으로 원본, 추출 텍스트, 청크, 임베딩, 검색 권한, 삭제 작업을 연결하는 것입니다. 그리고 개인정보가 필요하지 않은 곳에는 처음부터 넣지 않는 원칙을 적용합니다.
이런 구조는 특정 벡터DB 제품이나 특정 생성형 AI 모델에만 적용되는 방법이 아닙니다. 어떤 RAG 스택을 사용하더라도 “무엇을 저장하는가, 누가 검색할 수 있는가, 언제 어떻게 삭제하는가”를 명확히 만들면 데이터 관리 범위를 크게 줄일 수 있습니다.
참고할 공식 자료
개인정보 처리와 AI 위험 관리를 더 체계적으로 검토하려면 NIST Privacy Framework와 NIST AI Risk Management Framework의 개인정보·위험관리 관점을 함께 참고할 수 있습니다. 실제 적용 시에는 국내 개인정보 보호 관련 법령과 개인정보보호위원회의 최신 안내도 함께 확인하는 것이 좋습니다.
댓글 0
첫 댓글을 남겨보세요.