제재 명단과 이름이 비슷하면 지급을 막아야 할까: 누락과 오탐 사이의 기준
목차
제재 스크리닝은 정산금을 판매자 계좌로 보내기 전에 수취인이 제재 명단에 있는지 확인하는 절차입니다. 이름이 조금만 비슷해도 지급을 멈춰야 하지만, 너무 넓게 잡으면 정상 판매자까지 지급이 막힙니다.
실제 UN 명단을 받아 돌려보니 파서가 세 군데 틀렸고, 한글 이름은 한 건도 없었습니다. 이름 매칭 점수 하나로 자동 통과를 결정할 수 없는 이유가 데이터 형식과 오탐 비용 양쪽에서 드러났습니다.
결론부터
- 이름 유사도는 후보를 찾는 신호이지, 지급을 자동 승인하는 증거로 쓰지 않습니다.
- 생년월일·국적 같은 식별자가 없으면 점수를 억지로 낮추지 않고 사람 검토로 보냅니다.
- 실제 명단 파싱과 지급 경로 연결을 함께 검증해야 합니다. 판정기가 있어도 호출되지 않으면 지급 차단 기능은 존재하지 않는 것과 같습니다.
정산금을 판매자 계좌로 보내기 전에 그 판매자가 제재 대상인지 명단과 대조하는 장치를 만들어
실제 지급 경로에 이었습니다. 제재 스크리닝은 은행과 결제사가 돈을 내보내기 전에 상대가 제재
명단에 올라 있는지 확인하는 절차입니다. UN과 미국 OFAC, EU가 각각 명단을 내고, 이름이
비슷하기만 해도 일단 사람에게 보내 확인합니다.
이 자리에는 정답이 없습니다. 놓치면 제재 위반이고, 과하게 잡으면 멀쩡한 지급이
멈춥니다. 정할 것은 “무엇을 잡을 것인가”가 아니라 “놓칠 것과 과하게 잡을 것 중 무엇을 더
견딜 것인가” 입니다. 실제 UN 통합 명단(2026년 9월 기준)에서 한국 관련 79건 중 한글로
적힌 이름이 0건이었습니다(4절).
1. 임계: 놓칠 것과 과하게 잡을 것 사이
몇 점부터 사람에게 보낼지 정하려고 표본을 손으로 만들었는데(실제 명단이 아니라 아래 두 사례를 지어 넣은 표본입니다) 두 사례가 같은 점수로 나왔습니다.
같은 사람 다른 로마자 Kim Cheol Su ↔ Kim Chul Soo 67점다른 사람 비슷한 이름 김철수 ↔ 김철순 67점동점입니다. 선을 어디에 그어도 둘이 같은 쪽에 남습니다. 그때 “이 점수는 자동 통과에 쓸 수
없다”고 적고 사람 검토로 보냈고, 결론을 “문자열 거리의 한계”라고 적었습니다.
실무 자료를 확인하니 제재 스크리닝은 세 층으로 합니다.
- 정확 일치: 이름과 별칭에 더해 생년월일, 국적, 여권·문서번호까지 맞댑니다.
- 퍼지 매칭: 편집거리, 음역, 발음으로 비슷한 것을 찾습니다.
- 맥락 판별: 2층이 올린 후보를 2차 식별자로 좁혀 사람이 볼 것을 줄입니다.
업계 자료에 따르면 경보의 90% 이상이 오탐이라 3층이 실무의 핵심인데, 제가 만든 것은
2층까지였습니다. 그때는 명단 항목에서 2차 식별자를 읽어내지 못해 좁힐 재료가 없다고
판단했습니다. 그 재료를 파서가 못 읽었던 것이지, 원래 없던 것이 아니었습니다.
파서를 고쳐 생년월일·국적을 읽게 된 것이 뒤 절(3절)이고, 3층은 그 뒤에야 세울 수 있었습니다.
거리 계산은 그대로 두고 볼 것만 늘렸습니다.
| 사례 | 이름만 | 생년월일·국적을 더한 뒤 |
|---|---|---|
| 같은 사람, 다른 로마자 | 67점 | 82점 |
| 다른 사람, 비슷한 이름 | 67점 | 12점 |
| 같은 사람, 띄어쓰기만 다름 | 83점 | 98점 |
흔한 이름의 남남(Lee Min Ho ↔ Lee Min Ho) | 100점 | 45점 |
임계 80 기준으로 오판이 2/4에서 0/4가 됐습니다. 마지막 줄이 이 작업의 값입니다.
철자가 완전히 같으니 이름만으로는 만점이고, 선을 어디에 그어도 걸립니다. 생년월일과
국적이 달라서 떨어집니다. 흔한 이름일수록 이름 매칭이 쓸모없어지는데, 정작 흔한 이름이
대부분입니다. 한국인의 절반이 성씨 다섯 개를 공유한다는 실무 자료(5절)가 그 근거입니다.
두 가지를 규칙으로 박았습니다.
모르는 것은 점수를 건드리지 않습니다. 생년월일을 우리가 모르거나 명단이 주지 않으면
이름 점수를 그대로 씁니다. 모르는 것을 “안 맞았다”로 읽으면 제재 대상이 조용히 통과합니다.
깎는 폭을 올리는 폭보다 크게 뒀습니다. 생년월일 불일치는 40점을 깎고 일치는 10점을
올립니다. 맞다는 증거보다 아니라는 증거가 셉니다. 생년월일이 다르면 그건 대체로 다른
사람이지만, 같다고 해서 같은 사람이라고 하기에는 같은 날 태어난 사람이 너무 많습니다.
2. 바닥: 부르는 곳이 없던 판정기
이름 매칭 점수를 내는 클래스와 판정 로직을 먼저 만들었습니다. 그런데 어디에도 붙어 있지
않았습니다. screen()을 부르는 곳이 테스트뿐이었고, 명단을 가져오는 구현체가 없어 조회
결과가 항상 비어 무엇을 넣어도 판정이 “확실하지 않음”으로 나왔습니다. 정산은 판매자의 심사
상태를 보지 않았고, 판매자 테이블은 마이그레이션으로 만들어 뒀는데 그것을 읽는 코드가
없었습니다.
테스트는 초록불이었습니다. 판정 로직 자체는 맞게 돌고 있었으니까요. “만들었다”와 “돌고
있다”는 다른 말인데, 테스트가 앞의 것만 확인하고 있었습니다.
네 자리를 이었습니다.
| 조치 | 대가 |
|---|---|
| 명단을 하루 한 번 받아 옵니다. 못 받으면 직전에 받아 둔 판을 그대로 씁니다 | 낡은 명단으로 보는 동안 새 지정자를 놓칩니다. 그런데 비우는 쪽을 고르면 모든 판매자가 “확실하지 않음”이 되어 지급이 통째로 멈춥니다. 명단을 못 받은 것과 명단에 있는 것은 전혀 다른 사건인데, 비워 두면 둘이 같아집니다. 가용성(낡은 명단으로 계속 본다)과 정확성 중 가용성을 택하고, 낡은 정도는 따로 셉니다 |
| 판정마다 한 행을 남기고 대조한 명단의 판을 함께 적습니다 | 저장 공간. 대신 나중에 문제가 되면 “그때는 통과였고, 대조한 명단은 이 판이었다”를 댈 수 있습니다. 지금 명단으로 다시 돌려서는 그때를 재현할 수 없습니다 |
| 정산은 판매자를 직접 읽지 않습니다. 지급 직전에 게이트에 예/아니오와 이유만 받습니다 | 게이트를 한 번 더 도는 비용. 정산이 판매자 테이블을 직접 읽으면 심사 규칙까지 정산 쪽으로 새어 나옵니다 |
| 집계는 하되 돈만 막습니다(보류 상태를 따로 둠) | 집계까지 건너뛰면 나중에 심사가 풀렸을 때 그 날짜의 매출이 영영 안 잡힙니다. 집계 키는 이 프로젝트에서 이미 한 번 조용히 틀려 지급이 통째로 빠진 자리라 조심해서 갔습니다 |
3. 가정대로 생겨 있던 시험 데이터
파서를 쓰고, 시험용 XML을 손으로 만들어 검사했습니다. 전부 통과했습니다. 실제 UN 명단을
받아 보니 세 군데가 틀려 있었습니다. 그런데 셋 다 제가 만든 XML이 제 가정대로 생겨서
안 보였습니다. 무엇이 어떻게 틀렸는지는 7절에 모았습니다.
그중 생년월일은 숫자가 헷갈리기 쉬워 따로 적습니다. 명단은 날짜의 정확도를 TYPE_OF_DATE로
표시하는데, EXACT(정확함)로 라벨된 요소가 751건이고 그중 YEAR 값이 채워진 것이
263건입니다. 그리고 그 263건은 전부 연도만 줍니다(연월일이 온전한 것은 0건).
저는 연월일이 다 있어야 비교하도록 짰으니 그 코드는 한 번도 실행되지 않았습니다. 겹치는
자리까지만 비교하도록 고쳐서 192건이 비교 대상으로 돌아왔습니다. 192는 그 연도 값을
가진 사람 수라, 날짜 요소로 센 263과 다릅니다(한 사람에 날짜 요소가 여러 개 붙습니다).
751·263·192의 포함 관계와, 거기서 어긋나는 1,011·1,014·488은 참고 섹션에 적어 뒀습니다.
그래서 실제 명단을 받아 도는 검사를 따로 두고, 파싱한 건수와 날짜·국적이 실제로 채워지는
비율을 확인하게 했습니다.
4. 명단에 한글이 한 건도 없음
여기까지 하고 실제 명단에서 한국 관련 항목을 세어 봤습니다.
명단 전체 1,011건한국 관련 79건한글로 적힌 것 0건79건이 전부 RI JE-SON, PAEK CHANG-HO, CHOE CHUN-SIK 같은 로마자입니다. 그것도
북한식 표기라, 같은 성을 남한에서는 Lee, Park, Choi로 씁니다.
우리 판매자는 사업자등록 정보로 들어오니 대표자 이름이 한글입니다. 한글과 로마자를 그대로
맞대면 점수가 0에 가깝게 나오고, 전원이 통과합니다. 앞에서 임계를 못 골라 막혔던 것도
사실 이 자리였습니다. 재던 대상이 애초에 맞댈 수 없는 두 문자였습니다.
한글 이름을 쓸 법한 로마자 표기로 펼쳐서 대조하기로 했습니다. 김을 KIM과 GIM으로,
철을 CHUL·CHEOL·CHOL로 펼치는 식입니다.
여기서 한 가지를 정했습니다. 점수를 올리는 데 쓰지 않고 정확히 맞을 때만 봅니다.
점수로 재 봤더니 김철수가 67점에서 100점이 되는 동시에 김철순도 92점이 됐습니다.
후보를 늘린 만큼 남에게도 잘 걸립니다. 그래서 후보 중 하나가 명단의 표기와 완전히 같을 때만
100점을 주고, 아니면 원래 점수를 그대로 씁니다. 앞 절의 “모르는 것은 점수를 건드리지
않는다”와 같은 규칙입니다.
명단에 실제로 있는 이름으로 재서 8건 중 8건이 걸렸습니다. 만드는 과정에서 틀린 셋(종성
표·후보 상한·검사 표본)은 7절에 있습니다.
윤호진 ↔ YUN HO-JIN 이제선 ↔ RI JE-SON백창호 ↔ PAEK CHANG-HO 한유로 ↔ HAN YU-RO김광일 ↔ KIM KWANG-IL 최준식 ↔ CHOE CHUN-SIK장범수 ↔ JANG BOM SU 현광일 ↔ HYON KWANG IL5. 같은 성의 여섯 가지 표기
후보를 펼쳐도 사람이 실제로 쓰는 표기를 다 담을 수는 없습니다. 한국 이름 스크리닝을 다룬
실무 자료가 어려운 자리를 그대로 적어 두고 있었습니다.
- 한국인 성씨의 74%가 네 글자 미만입니다. 퍼지 매칭이 보통 네 글자 이상에서 도는데,
성씨가 그 밑입니다. - 한국인의 절반이 성씨 다섯 개를 공유합니다. 성씨만으로 좁히면 오탐이 폭발합니다.
Park,Bak,Pak,Bahk,Pahk,Back은 여섯 다 맞는 표기입니다. 잘못 쓴 것이 하나도 없습니다.- 명단마다 성이 앞에 오기도 하고 뒤에 오기도 합니다.
업계는 하나로 안 되니 정확 일치와 음성학과 편집거리를 병렬로 돌립니다. OFAC 자신의
검색 도구도 Jaro-Winkler와 Soundex를 같이 씁니다. 제가 만든 것은 정확 일치까지였습니다.
그래서 소리를 접는 키를 만들었습니다. 여섯 표기가 하나로 모입니다.
Park Bak Pak Bahk Pahk Back → PAKSoundex를 그대로 쓰면 안 됐습니다. Soundex는 영어 이름용이라 첫 글자를 그대로
남기는데, 한국 이름이 갈리는 자리가 정확히 첫 글자입니다. Park과 Bak이 P620과
B200으로 아예 다른 키가 됩니다. 그래서 한국어 로마자에서 실제로 섞이는 짝(ㄱ↔ㅋ, ㅂ↔ㅍ,
ㅈ↔ㅊ, ㄹ↔ㄴ)만 접는 키를 따로 만들었습니다.
키를 만들며 틀린 둘(Park의 R, Yi의 Y)은 7절에 있습니다. 두 글자 성과 이름
순서도 같이 다뤘습니다. 두 글자 성을 모르면 남궁철수를 “남”과 “궁철수”로 자릅니다.
성이 뒤에 오는 표기도 후보로 만듭니다.
6. 소리 일치는 확정이 아님
소리 키가 맞으면 사람에게 보내는 임계까지만 올리고, 일치로 확정하지는 않습니다.
소리를 접을수록 남남도 같은 키를 받습니다. 한국인의 절반이 성씨 다섯 개를 공유하는데
그 다섯 개를 소리로 또 접으면, 같은 키를 받는 사람이 인구의 상당수가 됩니다.
이 키는 사람에게 보낼 이유로 쓰고, 일치의 근거로는 쓰지 않습니다.
정리하면 세 갈래입니다.
| 신호 | 무엇을 하나 |
|---|---|
| 로마자 후보가 정확히 맞음 | 100점. 우연으로 보기 어렵습니다 |
| 소리가 같음 | 사람에게 보내는 임계까지만 올립니다 |
| 편집거리만 가까움 | 원래 점수 그대로 둡니다 |
여기서 못 하는 것도 적어 둡니다. PEP(정치적 주요 인물) 명단은 넣지 않았습니다. 정부가
배포하는 공식 명단이 없고, 공개 데이터는 상업 이용에 별도 라이선스가 필요합니다. 붙일 자리만
열어 두고 비워 뒀습니다. 국내 금융위 고시도 기계가 읽을 수 있는 형태의 공개 배포를 찾지
못해 쓰지 않았습니다.
그리고 명단마다 파서를 새로 봐야 합니다. OFAC SDN 명단을 실제로 받아 우리 파서에 넣어
보니 항목이 0건이었습니다. 태그 구조가 달라(UN은 INDIVIDUAL·ENTITY, OFAC은
sdnEntry) 그대로는 한 건도 못 읽습니다. EU 명단도 같은 종류의 버그가 날 것으로
봅니다(예상). 실제 데이터를 받아 보기 전에는 제 가정이 맞는지 알 수 없었습니다.
7. 무엇을 틀렸나(8건)
앞 절들의 “또 틀렸다” 여덟 건을 세 묶음으로 접었습니다(파서 3절 · 한글 4절 · 소리 키 5절).
| 묶음 | 왜 안 보였나 | 고친 것 |
|---|---|---|
| 파서 셋 | 시험 XML이 가정대로 생겨 셋 다 안 보였다. 실제는 EXACT 751건 중 연도가 있는 263건이 연도만 주고, 국적이 KP ↔ Democratic Republic of the Congo로 한 번도 안 맞고, 나라 49건이 <VALUE>에 한 겹 더 싸여 있었다 | 나라 이름→코드 표로 634/634 인식, <VALUE> 자식으로 49건 회복, 겹치는 자리만 비교해 연도를 가진 192건 |
| 한글 셋 | 명단에 없는 이름(손으로 지은 김철수·박창호)으로 검사를 짜 1/4, “많이 만들수록 남에게도 걸린다”는 점수 시절 걱정이 상한 48로 남아 진짜 대상을 잘라냄, 종성 표가 밀려 박창호 ↔ PAK CHANG HO가 안 걸림 | 실제 명단에 있는 이름으로 8/8, 상한 512, 자모 인덱스로 확인 |
| 소리 키 둘 | Park·Bak이 다른 키(PANK), Yi·Lee가 갈림 | 모음 뒤 R·첫머리 Y를 접지 않음 |
참고
- UN 안보리 제재 통합 명단: Consolidated List
- OFAC 검색 도구가 쓰는 매칭 방식: Sanctions List Search 문서
- 이름 매칭에서 오탐이 차지하는 비중: Fuzzy Matching for Sanctions Screening
- 한국 이름 스크리닝의 어려움: Screening Korean Names (SQA Consulting)
- LLM으로 오탐을 줄인 실험과 그 속도 비용: Federal Reserve FEDS Notes (2025-09)
- 날짜 필드 산수:
EXACT751 ⊃ 연도 있음 263(전부 연도만) → 사람 192. 751+263=1,014는 전체 1,011을 넘지만 263이 751의 부분집합(나머지 488건은EXACT인데 연도조차 없음).
댓글
댓글 수정/삭제는 GitHub Discussions에서 가능합니다.