한국어 개인정보 탐지 데이터셋을 직접 구축한 이유
KoPII-Pipeline의 데이터셋 구축 배경, 합성·공개 데이터 결합 과정, 한국어 PII 모델 평가 결과를 정리한다.
한 줄 요약
한국어 문서에서 개인정보를 안전하게 다루려면 단순히 이름과 숫자를 지우는 모델이 아니라, 한국어 조사 경계·한국 고유 식별자·업무 문맥 보존·오탐 제어를 함께 평가할 수 있는 데이터셋이 필요했다. 그래서 ko-pii-ner-100k를 만들고, 그 데이터로 ko-pii-ner-roberta-base를 학습했다.
- 데이터셋:
seongyeon1/ko-pii-ner-100k - 모델:
seongyeon1/ko-pii-ner-roberta-base - 공개 저장소:
KoPII-Pipeline
왜 직접 만들었나
문서 검색이나 RAG 시스템을 만들다 보면 생각보다 빨리 개인정보 문제를 만난다. 이름, 전화번호, 이메일, 주소처럼 명확한 정보도 있지만, 사번, 닉네임, 계좌번호, 주민등록번호, 여권번호처럼 문맥에 따라 더 민감해지는 값도 있다.
처음에는 기존 PII 탐지 모델을 가져다 쓰면 되지 않을까 생각했다. 하지만 한국어 문서에서는 몇 가지 문제가 바로 드러났다.
첫째, 한국어 조사 경계가 문제다.
예를 들어 김하늘이, 김하늘의, 김하늘에게 같은 표현에서 실제 개인정보는 김하늘이다. 모델이나 추출기가 단어 단위 경계를 기준으로 움직이면 이름과 조사를 같이 잡거나, 이름 일부만 놓치기 쉽다. 개인정보 탐지에서 이런 경계 오류는 단순 점수 문제가 아니다. 이름을 정확히 잘라내지 못하면 후속 마스킹, 조직 정보 매칭, 검색 인덱싱 품질이 모두 흔들린다.
둘째, 한국 고유 식별자가 있다.
주민등록번호, 외국인등록번호, 운전면허번호, 여권번호, 사업자등록번호, 계좌번호, 카드번호처럼 한국 문서에서 자주 등장하는 값들은 영어권 PII 데이터셋만으로 충분히 커버하기 어렵다. 포맷은 정규식으로 어느 정도 잡을 수 있지만, 실제 문서에서는 전화번호, 주문번호, 접수번호, 버전 번호, 금액, 날짜와 섞여 나온다. “숫자처럼 생겼으니 일단 개인정보”라고 판단하면 오탐이 폭발한다.
셋째, 내가 풀고 싶었던 문제는 단순 마스킹이 아니었다.
문서에서 이름을 전부 [MASK]로 지우면 개인정보는 줄어들지만, 업무 문맥도 같이 사라진다.
김하늘이 배포 일정을 확인했습니다.
이 문장에서 이름 자체는 보호해야 하지만, “어느 조직의 담당자가 배포 일정을 확인했는지”는 검색과 요약에 유용한 정보일 수 있다. 그래서 목표는 단순 삭제가 아니라 개인정보 탐지와 업무 문맥 보존을 분리하는 구조였다.
김하늘이 배포 일정을 확인했습니다.
→[이름:플랫폼개발팀 보호]이 배포 일정을 확인했습니다.
여기서 중요한 점은 모델이 이름만 보고 소속을 추측하지 않는다는 것이다. 모델은 개인정보의 위치와 유형을 찾고, 소속은 별도의 인사·조직 정보에서 확인한다. 탐지 모델과 치환 정책을 분리해야 실제 서비스에서 안전하게 다룰 수 있다.
이 요구사항을 만족하는 공개 한국어 PII 데이터셋이 필요했고, 그래서 ko-pii-ner-100k를 구축했다.
데이터셋의 목표
데이터셋의 목표는 단순히 “PII가 들어간 문장 많이 만들기”가 아니었다. 목표는 세 가지였다.
- 한국어 개인정보 탐지 모델을 학습할 수 있을 것
- 한국어 조사와 문자 경계를 평가할 수 있을 것
- 실제 문서 처리 서비스에서 문제가 되는 오탐·미탐을 같이 확인할 수 있을 것
특히 세 번째가 중요했다. 개인정보 탐지 모델은 recall이 중요하다. 놓치면 개인정보가 그대로 남기 때문이다. 하지만 recall만 올리려고 하면 주문번호, 접수번호, 제품명, 버전 문자열까지 개인정보로 잡기 쉽다. 실제 서비스에서는 이것도 치명적이다. 문서가 계속 잘못 마스킹되면 검색 품질과 사용자 신뢰가 같이 떨어진다.
그래서 데이터셋에는 개인정보가 있는 문서뿐 아니라, 개인정보가 없는 hard negative 문서도 넣었다. 예를 들어 주문번호, 대표번호, 버전 번호, 제품명처럼 PII처럼 보이지만 실제로는 개인정보가 아닌 값을 포함한 문서들이다.
데이터는 어떻게 구성했나
최종 데이터셋은 총 100,851건이다.
| 구간 | 레코드 수 | 용도 |
|---|---|---|
| 학습 | 78,963 | 모델 학습 |
| 검증 | 9,994 | 모델 선택·점검 |
| 내부 테스트 | 9,888 | 구축 데이터 내 성능 점검 |
| KDPII 기반 별도 평가 | 2,006 | 학습에 쓰지 않은 홀드아웃 평가 |
| 합계 | 100,851 | 전체 데이터셋 |
데이터는 크게 네 계열을 섞었다.
- 공개 한국어 대화의 문맥과 개인정보 표시를 활용한 자료
- 공개 데이터의 한국어 문맥에 한국식 개인정보 값을 반영한 자료
- 고객상담·사내메일·의료·금융·공공민원·채용 양식의 합성 문서
- 주문번호·제품명 등을 개인정보로 잘못 판단하는지 확인하기 위한 비개인정보 문서
여기서 “합성 데이터셋”이라고 부르더라도 전체가 새로 만든 가상 개인정보만으로 구성된 것은 아니다. 공개 원문을 활용한 구간에서는 원래 값을 유지한 경우도 있다. 그래서 이 데이터셋은 단순한 toy corpus가 아니라, 공개 한국어 자료와 템플릿 기반 업무 문서 합성을 결합한 데이터셋에 가깝다.
합성 데이터에서 중요하게 본 것
PII 합성 데이터는 만들기 쉬워 보이지만, 실제로는 그냥 값만 뿌리면 안 된다.
예를 들어 문장마다 무작위 이름과 전화번호를 넣으면 표면적으로는 PII 데이터가 된다.
김민수 고객님의 연락처는 010-0000-0000입니다.
박지영 고객님의 연락처는 010-1111-1111입니다.
하지만 실제 서비스에서 필요한 평가는 여기서 끝나지 않는다.
같은 사람이 여러 문서에 반복 등장하는지, 같은 문서 안에서 이름·닉네임·사번·이메일이 일관되게 연결되는지, 이름 뒤 조사가 자연스럽게 붙는지, 표 안에서 숫자 값과 개인정보가 섞일 때 오탐하지 않는지까지 봐야 한다.
그래서 설계 단계에서는 문서를 먼저 만들고 PII를 뿌리는 방식이 아니라, 먼저 가상 조직과 인구를 만들고 그 사람들을 문서 템플릿에 배치하는 방식을 잡았다.
구조는 2단계다.
Stage 1 가상 조직 생성 → 사람 N명 + 조직 트리 + 채번된 사번
Stage 2 문서 생성 → 템플릿 × 인구 샘플링 + span offset 기록Stage 1에서는 사람, 소속, 직급, 사번, 연락처를 만든다. 같은 사람이 여러 문서에 반복 등장할 수 있게 하고, 사번 포맷이나 조직 구조를 실험 가능하게 분리한다.
Stage 2에서는 사내메일, 회의록, 인사공지, 결재 문서, 채팅 로그, 이슈 티켓 같은 장르별 문서를 만든다. 템플릿에 값을 넣는 시점에 span offset을 기록하고, 이후 표기 흔들림을 넣은 뒤 offset을 다시 검증한다.
특히 span offset은 매우 중요하다. NER 데이터셋에서는 text[start:end] == value가 항상 성립해야 한다. 이게 틀리면 학습도 평가도 조용히 망가진다. 그래서 모든 span은 문자 offset 기준으로 검증했고, 변형 후에도 offset이 맞는지 확인하는 구조를 뒀다.
라벨 체계
모델은 20개 유형, BIO 기준 41개 클래스를 학습하도록 구성했다.
| 묶음 | 유형 |
|---|---|
| 식별번호 | 주민등록번호, 외국인등록번호, 여권번호, 운전면허번호 |
| 이름·연락처·기타 식별 정보 | 이름, 전화번호, 이메일, 주소, 계좌번호, 카드번호, 사업자등록번호, 사용자 ID, 개인 URL, 차량번호, IP 주소 |
| 문맥상 보호 여부를 정하는 정보 | 생년월일, 나이, 소속, 직위, 민감 속성 |
중요한 점은 “학습한 유형”과 “서비스에서 실제 치환하는 유형”을 구분했다는 것이다.
예를 들어 소속이나 직위는 문맥에 따라 보호해야 할 수도 있고, 업무 검색을 위해 남겨야 할 수도 있다. 그래서 모델은 넓게 탐지하되, 실제 치환 정책은 문서 공개 범위와 업무 목적에 따라 선택하는 구조가 맞다.
모델 학습 결과
이 데이터셋으로 klue/roberta-base를 토큰 분류 과제에 맞춰 파인튜닝했다. 공개한 모델은 ko-pii-ner-roberta-base다.
중요한 평가는 학습·검증에 쓰지 않은 KDPII 기반 홀드아웃 2,006건에서 봤다. 모델 카드 기준으로 이 홀드아웃에서 F5 0.9344를 기록했다.
PII 탐지에서는 F1보다 F5를 더 중요하게 봤다. 개인정보 탐지에서 오탐도 문제지만, 미탐은 개인정보가 그대로 남는 문제라 더 치명적이다. F5는 recall을 훨씬 크게 반영하는 지표라 이 목적에 더 맞다.
다만 내부 test 전체 수치만 보면 안 된다. 내부 test에는 합성 구간이 많이 포함되어 있고, 합성 구간에서는 점수가 과대평가되기 쉽다. 실제로 모델 카드에서도 내부 test 전체 F5는 0.9937이지만, 이 숫자는 합성 구간의 높은 점수 영향을 크게 받는다. 그래서 인용해야 할 핵심 수치는 KDPII 홀드아웃 기준 F5 0.9344다.
공개 PII 모델과 비교해 본 결과
추가로 현재 문서 처리 서비스에서 쓸 모델을 판단하기 위해, 공개 PII 모델들과 같은 평가 데이터에서 비교했다.
평가 조건은 다음과 같다.
- KDPII 기반 2,006건
- 개인정보가 없는 합성 문서 580건
- 총 2,586건
- 공통 13개 범주 기준
- 문자 시작·끝과 유형이 모두 맞아야 정답으로 계산
- Apple M4 Pro / PyTorch MPS 로컬 평가
비교 대상은 세 모델이다.
| 모델 | Exact F1 | 이름 Exact 재현율 | 비개인정보 문서 오탐 |
|---|---|---|---|
| KoPII RoBERTa base | 91.10% | 96.05% | 0 / 580 |
| NVIDIA GLiNER-PII | 8.73% | 12.43% | 559 / 580 |
| Fastino GLiNER2-PII | 19.87% | 18.36% | 182 / 580 |
이 결과만 보면 차이가 매우 크게 보인다. 하지만 해석은 조심해야 한다.
이번 비교는 한국어로 파인튜닝한 RoBERTa와 한국어 추가 학습·라벨 표현·임계값 최적화 없이 그대로 적용한 공개 GLiNER 체크포인트를 비교한 것이다. 각 모델의 최적 성능이나 모든 언어에서의 우열을 뜻하지 않는다.
특히 GLiNER 계열은 기본 단어 경계에서 한국어 이름과 조사를 함께 취급할 수 있다. 실제 감사 결과, 이름 정답 354개 중 244개는 기본 단어 시작·끝 경계로 정확히 표현하기 어려웠다. 즉 낮은 Exact 점수에는 모델 가중치의 문제뿐 아니라 한국어 경계 처리 제약도 들어 있다.
그래도 이 비교에서 확인한 것은 분명하다. 현재 설정 그대로 한국어 문서 처리 서비스에 연결할 목적이라면, 한국어 PII 데이터로 파인튜닝한 RoBERTa가 더 적합했다. 특히 이름을 정확히 잘라내는 성능이 중요했다. 이름 문자열은 이후 인사·조직 정보 조회의 입력이 되기 때문이다. 이름에 조사가 붙거나 일부만 잘리면 소속 조회가 실패하거나 잘못될 수 있다.
얻은 결론
이번 작업에서 가장 크게 느낀 것은, 개인정보 비식별화는 “탐지 모델 하나”의 문제가 아니라는 점이다.
PII 처리는 최소한 세 층으로 나뉜다.
- 어디가 개인정보인지 찾는 탐지 모델
- 그 개인정보를 어떤 수준으로 바꿀지 정하는 정책
- 바뀐 문서를 검색·요약·검수 흐름에 어떻게 연결할지에 대한 서비스 설계
이 세 가지를 섞으면 위험하다. 모델이 이름을 찾는 것과, 그 이름을 부서명으로 바꿀지, 가명으로 바꿀지, 완전히 보호 표시로 바꿀지는 다른 문제다. 소속도 모델이 추측하면 안 되고, 별도의 인사·조직 정보에서 확인해야 한다.
또 하나의 결론은 한국어 PII에서는 경계가 매우 중요하다는 점이다.
영어권 데이터셋에서 잘 동작하는 모델이라도 한국어 조사, 한국식 식별번호, 사내 문서 관습, 숫자형 오탐 문제를 그대로 해결해주지는 않는다. 특히 “개인정보 문자를 대충 덮는 것”과 “정확한 span을 정확한 유형으로 잡는 것”은 다르다. 실제 서비스에서는 후자가 필요하다.
마지막으로, 합성 데이터는 필요하지만 합성 평가만 믿으면 안 된다.
합성 데이터는 모델 학습과 반복 실험에 매우 유용하다. 하지만 템플릿이 만든 문장은 템플릿의 한계를 갖는다. 실제 업무 문서에는 오타, 줄바꿈, 표, OCR 잡음, 예외적인 표현이 계속 나온다. 그래서 합성 데이터셋은 출발점이지, 실제 운영 품질의 보증서는 아니다. 실서비스에 넣기 전에는 실제 업무 문서 표본에서 유형별 누락과 오탐을 별도로 측정해야 한다.
공개한 것과 공개하지 않은 것
이번 브랜치에서 공개한 것은 다음과 같다.
- 한국어 PII 데이터셋:
ko-pii-ner-100k - 한국어 PII RoBERTa 모델:
ko-pii-ner-roberta-base - 모델 비교 코드와 평가 결과
- 문서 처리 서비스에 적용하는 일반화된 흐름 설명
- 초기 설계 문서와 합성 코퍼스 구현 계획
반대로 공개 저장소에는 포함하지 않은 것도 있다.
- 데이터 생성·학습 전체 내부 도구
- 운영 문서 처리 서비스 코드
- 직원 명부
- 실제 조직 정보
- 서비스 접속 정보나 비밀키
- 실제 업무 문서
저장소만 clone해서 전체 문서 처리 서비스를 바로 실행할 수 있는 형태는 아니다. 공개 범위는 데이터셋, 모델, 설계 문서, 비교 재현 코드다.
마무리
처음에는 한국어 개인정보 탐지 모델을 만들기 위한 데이터셋 구축으로 시작했다. 하지만 작업을 진행할수록 핵심은 단순 NER이 아니라, 개인정보 보호와 업무 문맥 보존 사이의 균형이라는 점이 분명해졌다.
이름을 무조건 지우면 안전해 보이지만 문서의 의미가 사라진다. 반대로 이름을 너무 많이 남기면 검색 품질은 좋아질 수 있어도 재식별 위험이 커진다. 그래서 필요한 것은 “마스킹할지 말지”의 이분법이 아니라, 탐지와 치환 정책을 분리하고 문서 목적에 맞게 보호 수준을 조정하는 구조다.
ko-pii-ner-100k와 ko-pii-ner-roberta-base는 그 구조를 만들기 위한 첫 번째 기반이다.
한국어 문서에서 개인정보를 정확히 찾고, 조사 경계를 다루고, 한국 고유 식별자를 포함하고, 동시에 hard negative로 오탐을 확인할 수 있는 데이터셋이 필요했다. 직접 만든 이유는 간단하다. 내가 필요한 문제를 제대로 평가할 수 있는 데이터가 없었기 때문이다.
그리고 이번 결과는 적어도 하나의 판단을 뒷받침한다.
한국어 문서 처리 서비스에서 개인정보 탐지와 업무 문맥 보존을 같이 다루려면, 한국어 데이터와 한국어 경계 문제를 정면으로 반영한 모델이 필요하다. 기존 공개 모델을 그대로 붙이는 것만으로는 충분하지 않았다.