헬스케어 IT 분야에서 일해본 사람이라면 누구나 이 문제에 직면했을 것입니다.
환자 A는 병원 1에 "Jonathan Smith, DOB 03/15/1985"로 나타나고, 환자 B는 병원 2에 "Jon Smith, DOB 03/15/1985"로, 환자 C는 클리닉에 "John Smythe, DOB 03/15/1985"로 등록됩니다.
같은 사람일까요? 아마도요. 하지만 수백만 건의 기록, 수십 개의 소스 시스템, 그리고 "누군가 태어난 해를 잘못 입력한" 수준의 데이터 품질 속에서 이를 대규모로 어떻게 증명할 수 있을까요?
이것이 바로 **EMPI(전사적 마스터 환자 지수)**가 해결하는 문제입니다. 전통적으로 EMPI는 비싼 상용 제품, 경직된 규칙 엔진, 그리고 많은 수동 검토를 통해 해결되었습니다.
저희는 AI를 사용하여 Azure 상에서 오픈 소스 도구로 EMPI를 구축했으며, 그 결과는 정말 인상적입니다.
이 게시물은 EMPI가 어떻게 작동하는지, 아키텍처는 어떤 모습인지, 그리고 확정적 매칭, 확률적 알고리즘, AI 강화 점수 매칭의 조합이 단일 접근 방식보다 더 나은 결과를 내는 이유를 설명합니다.
1. EMPI가 여전히 중요한 이유 (그 어느 때보다)
헬스케어 기관들은 "환자 데이터 문제"를 겪고 있는 것이 아니라, "환자 신원 문제"를 겪고 있습니다.
모든 EHR, 실험실 시스템, 약국 플랫폼, 청구 처리기는 자체적인 환자 기록을 생성합니다. FHIR, HL7 또는 플랫 파일을 통해 이러한 시스템들이 데이터를 교환할 때, 미국에는 보편적인 환자 식별자가 없습니다. 의회는 1998년부터 이에 대한 자금 지원을 막아왔습니다.
그 결과:
- 중복 기록은 비용을 증가시키고 진료 기록을 단편화합니다.
- 누락된 매칭은 임상의가 환자의 전체 의료 기록을 볼 수 없다는 것을 의미합니다.
- **오탐(False positive)**은 두 명의 다른 환자를 하나의 기록으로 병합하여 환자 안전 위험을 초래할 수 있습니다.
전통적인 EMPI 솔루션은 확정적 매칭(정확한 필드 비교)과 때로는 확률적 점수 매칭(퍼지 문자열 매칭)을 사용합니다. 작동은 하지만, 상당한 회색 영역의 기록을 남겨 인간의 검토를 필요로 하며, 이 대기열은 팀이 처리할 수 있는 속도보다 더 빠르게 늘어납니다.
AI가 그 회색 영역을 줄일 수 있다면 어떨까요?
2. 아키텍처: 세 가지 매칭 계층
여기 핵심적인 통찰이 있습니다: 어떤 단일 매칭 기술도 충분하지 않습니다. 정확한 매칭은 오타를 놓치고, 퍼지 매칭은 오탐을 생성하며, AI 단독으로는 환각을 일으킵니다.
하지만 이들을 보정된 가중치로 함께 쌓아 올리면 놀랍도록 정확한 결과를 얻을 수 있습니다.
각 계층을 자세히 살펴보겠습니다.
3. 계층 1: 확정적 매칭 — 기반
확정적 매칭은 기본 중의 기본입니다. 두 기록이 엔터프라이즈 ID를 공유한다면, 그들은 같은 사람입니다. 그 이상도 이하도 아닙니다.
시스템은 각 식별자 유형에 신뢰 수준을 할당합니다:
| 식별자 | 가중치 | 이유 |
|---|---|---|
| 엔터프라이즈 ID | 1.0 | 권한 있는 기관에 의해 명시적으로 할당됨 |
| SSN | 0.9 | 존재하고 정확할 때 매우 신뢰할 수 있음 |
| MRN | 0.8 | 시스템 종속적 — 동일한 헬스케어 시스템 내에서만 유효 |
| 생년월일 | 0.35 | 흔하지만 고유하지 않음 — 인구의 0.3%가 같은 생일을 공유함 |
| 전화번호 | 0.3 | 유용한 신호지만 자주 변경됨 |
| 이메일 | 0.3 | 동일 — 보조적인 증거일 뿐, 증명은 아님 |
여기서 중요한 구현 세부 사항은 MRN 시스템 유효성 검사입니다. 병원 A의 MRN "12345"는 병원 B의 MRN "12345"와 완전히 관련이 없습니다. 시스템은 식별자의 소스 시스템 URI를 확인한 후에야 일치로 간주합니다. 이 과정 없이는 우연한 MRN 충돌로 인한 오탐의 홍수를 겪을 것입니다.
엔터프라이즈 ID 일치가 발견되면 시스템은 바로 단축 처리됩니다. 확률적 또는 AI 점수 매기기가 필요 없습니다. 확실한 일치이기 때문입니다.
4. 계층 2: 확률적 매칭 — 흥미로운 부분
이것이 시스템이 제 역할을 하는 부분입니다. 확률적 매칭은 헬스케어 데이터의 지저분한 현실, 즉 오타, 별명, 숫자 전치, 약어, 일관성 없는 형식 등을 처리합니다.
이름 유사성
시스템은 이름 매칭을 위해 다중 알고리즘 앙상블을 사용합니다:
- Jaro-Winkler(60% 가중치): 이름과 같은 짧은 문자열에 최적화되었습니다. 문자열이 공통 접두사를 공유할 때 추가 점수를 부여하므로 "Jonathan" 대 "Jon"은 예상보다 높은 점수를 얻습니다.
- Soundex / Metaphone(음성학적 부스트): "Smith" 대 "Smythe", "Jon" 대 "John" 등 문자열 거리만으로는 놓칠 수 있는 유사 발음 변형을 잡아냅니다.
- Levenshtein 거리(오타 감지): 단일 문자 오류("Johanson" 대 "Johansn")를 처리합니다.
이러한 점수들은 혼합되며, 이름과 성은 결합되기 전에 독립적으로 점수가 매겨집니다. 이는 일치하는 성이 크게 다른 이름을 보완하는 것을 방지합니다.
생년월일 — 생각보다 스마트합니다
생년월일 매칭은 정확한 비교를 넘어섭니다. 시스템은 헬스케어에서 가장 흔한 데이터 입력 오류 중 하나인 월/일 전치를 감지합니다:
| 시나리오 | 점수 |
|---|---|
| 정확한 매칭 | 1.0 |
| 월과 일이 바뀐 경우 (예: 03/15 대 15/03) | 0.8 |
| 1일 차이 | 0.9 |
| 2~30일 차이 | 0.5–0.8 (비율 조정) |
| 다른 연도 | 0.0 |
이것만으로도 순수 확정적 시스템이 완전히 놓치는 범주의 불일치를 잡아냅니다.
주소 유사성
주소 매칭은 하이브리드 접근 방식을 사용합니다:
- 정규화된 전체 주소에 대한 Jaro-Winkler(70% 가중치)
- 단어 재배열 처리를 위한 토큰 기반 Jaccard 유사성(30% 가중치)
- 우편번호, 도시, 주 일치에 대한 보너스 점수
- 약어 확장 — "St"는 "Street"으로, "Ave"는 "Avenue"로 확장
5. 계층 3: AI 강화 매칭 — 판도를 바꾸는 요소
이것은 아키텍처가 전통적인 EMPI 솔루션과 달라지는 부분입니다.
OpenAI 임베딩 (의미적 유사성)
시스템은 OpenAI의 text-embedding-3-small 모델을 사용하여 각 환자의 전체 인구통계학적 프로필에 대한 텍스트 임베딩을 생성합니다. 그런 다음 환자 쌍 간의 코사인 유사성을 계산합니다.
왜 이것이 작동할까요? 임베딩은 문자열 매칭으로는 포착할 수 없는 의미적 관계를 포착하기 때문입니다. "123 Main Street, Apt 4B, Springfield, IL"과 "123 Main St #4B, Springfield, Illinois"는 문자 단위로는 다르지만 의미적으로는 동일합니다.
임베딩 점수는 총 가중치의 10%만을 차지합니다. 이는 최종 판단이 아닌 신호입니다. 하지만 모호한 경우에는 이 신호가 균형을 깨뜨립니다.
GPT-5.2 LLM 분석 (지능적 추론)
인간 검토 영역(0.65–0.85)에 해당하는 매칭의 경우, 시스템은 선택적으로 GPT-5.2를 호출하여 환자 쌍을 분석하고 구조화된 추론을 제공합니다:
{ "match_score": 0.92, "confidence": "high", "reasoning": "Multiple strong signals: identical last name, DOB matches exactly, same city. First name 'Jon' is a common nickname for 'Jonathan'.", "name_analysis": "First name variation is a known nickname pattern.", "potential_issues": [], "recommendation": "merge" }
LLM은 단순히 숫자를 생성하는 것이 아니라, 두 기록이 일치한다고 생각하는 이유를 설명합니다. 이것은 모호한 사례에 대해 최종 결정을 내리는 인간 검토자에게 엄청나게 가치 있는 정보입니다. 두 기록을 보며 추측하는 대신, AI가 생성한 추론을 평가할 수 있습니다.
LLM 분석이 활성화되면 최종 점수는 전통적인 점수와 LLM 점수를 혼합합니다:
최종 점수 = (전통적인 점수 × 0.8) + (LLM 점수 × 0.2)
LLM의 온도는 일관성을 위해 0.1로 설정됩니다. 매칭 엔진에서 창의적인 출력이 아닌 확정적인 출력을 원하기 때문입니다.
6. 그래프 데이터베이스: 환자 관계 모델링
기록과 점수는 이야기의 절반에 불과합니다. 진정한 힘은 시스템이 관계를 저장하고 탐색하는 방식에서 나옵니다.
저희는 Gremlin API가 포함된 Azure Cosmos DB를 사용합니다. 이는 환자, 식별자, 주소, 임상 데이터를 유형화된 엣지로 연결된 정점으로 모델링하는 그래프 데이터베이스입니다.
(:Patient)──[:HAS_IDENTIFIER]──▶(:Identifier)
│ ├──[:HAS_ADDRESS]──▶(:Address)
│ ├──[:HAS_CONTACT]──▶(:ContactPoint)
│ ├──[:LINKED_TO]──▶(:EmpiRecord) ← 골든 레코드
│ ├──[:POTENTIAL_MATCH {score, confidence}]──▶(:Patient)
│ └──[:HAS_ENCOUNTER]──▶(:Encounter)
└──[:HAS_OBSERVATION]──▶(:Observation)
왜 그래프인가?
세 가지 이유가 있습니다:
- 후보 검색은 그래프 탐색 문제입니다. "환자 X와 식별자를 공유하는 모든 환자를 찾아라"는 자연스러운 그래프 쿼리입니다. 환자에서 식별자로 이동한 다음, 해당 식별자를 공유하는 다른 환자로 다시 이동합니다. Gremlin에서는 몇 줄이면 되지만, SQL에서는 데이터가 증가함에 따라 성능이 저하되는 다중 테이블 조인입니다.
- 관계는 일급 시민입니다.
POTENTIAL_MATCH엣지는 매칭 점수, 신뢰 수준, 자세한 분석을 관계에 직접 저장합니다. 조인 없이 "신뢰도 높은 매칭을 모두 보여줘"라고 쿼리할 수 있습니다. - EMPI 기록은 본질적으로 계층적입니다. 골든 레코드(EmpiRecord)는
LINKED_TO엣지를 통해 여러 소스 환자에 연결됩니다. 두 환자를 병합할 때, 관계형 테이블의 행을 다시 작성하는 것이 아니라 엣지를 추가하는 것입니다.
대규모 성능
Cosmos DB의 파티션 전략은 source_system을 파티션 키로 사용하여 헬스케어 시스템 간에 논리적 격리를 제공합니다. 시스템은 Azure의 429 속도 제한을 자동 재시도 및 지수 백오프로 처리하며, RU 소진을 방지하기 위해 대량 로드에 배치 작업을 사용합니다.
7. FHIR-Native 데이터 수집
시스템은 헬스케어 데이터 교환을 위한 새로운 상호운용성 표준인 HL7 FHIR R4 번들을 수집합니다.
각 FHIR 번들은 인구 통계, 진료 기록, 관찰, 상태, 절차, 예방 접종, 약물 요청 및 진단 보고서 등 완전한 환자 기록을 포함하는 JSON 파일입니다.
FHIR 로더는 다음을 수행합니다:
- FHIR 식별자 시스템을 내부 유형(SSN, MRN, Enterprise ID)에 매핑
- 세 가지 FHIR 날짜 형식(YYYY, YYYY-MM, YYYY-MM-DD) 모두 처리
- 포괄적인 환자 프로필을 위한 임상 데이터 추출
- 수천 명의 환자를 메모리 효율적으로 처리하기 위한 이터레이터 패턴 사용
- 감사 준수를 위한 소스 시스템 출처 추적
이는 이 서비스가 사용자 정의 통합 작업 없이 Epic, Cerner, MEDITECH 또는 Synthea에서 생성된 테스트 데이터 등 모든 FHIR 준수 EHR에서 직접 데이터를 수집할 수 있음을 의미합니다.
8. 대화형 에이전트: 자연어를 통한 매칭
이제 재미있는 부분입니다.
이 시스템에는 Azure AI Foundry Agent Service를 기반으로 구축된 대화형 AI 에이전트가 포함되어 있습니다. OpenAPI 도구를 통해 매칭 서비스의 REST API를 호출하는 GPT-5.2 기반 에이전트로 배포됩니다.
복잡한 UI를 탐색하여 매칭을 찾는 대신, 데이터 관리자는 간단히 질문할 수 있습니다:
"Aaron이라는 환자를 찾아주세요"
"환자 abc-123과 환자 xyz-456을 비교해주세요"
"검토 대기 중인 매칭은 무엇인가요?"
"환자 A와 환자 B 간의 매칭을 승인해주세요"
이 에이전트는 Streamlit 대시보드의 에이전트 채팅 탭에 직접 통합되어 사용자가 워크플로우를 벗어나지 않습니다. 내부적으로 에이전트가 도구("환자 검색" 등)를 호출하기로 결정하면 Azure AI Foundry는 로컬 함수 실행 없이 컨테이너 앱 API로 직접 HTTP 요청을 보냅니다.
사용 가능한 에이전트 도구
| 도구 | 기능 |
|---|---|
| searchPatients | 이름, DOB, 식별자로 환자 검색 |
| getPatientDetails | 상세한 환자 인구 통계 및 기록 확인 |
| findPatientMatches | 환자의 잠재적 중복 검색 |
| compareTwoPatients | 상세 점수와 함께 두 환자를 나란히 비교 |
| getPendingReviews | 인간의 결정이 필요한 매칭 목록 |
| submitReviewDecision | 매칭 승인 또는 거부 |
| getServiceStatistics | MPI 대시보드 지표 확인 |
이 동일한 도구 세트는 모델 컨텍스트 프로토콜(MCP) 서버를 통해서도 노출되어, AI 기반 IDE 및 코딩 도우미에서 매칭 엔진에 접근할 수 있도록 합니다.
9. 대시보드: 모든 것을 한데 모으기
환자 매칭 서비스에는 운영 관리를 위한 완전한 기능을 갖춘 Streamlit 대시보드가 포함되어 있습니다.
| 페이지 | 내용 |
|---|---|
| 대시보드 | 주요 지표, 점수 분포 차트, 최근 매칭 활동 |
| 매칭 결과 | 필터링 가능한 목록(점수 분석 포함) — 확정적, 확률적, AI, LLM 탭 |
| 환자 | 임상 데이터를 포함한 모든 로드된 환자 검색 및 탐색 |
| 환자 그래프 | streamlit-agraph를 사용한 환자 관계의 대화형 그래프 시각화 |
| 검토 대기열 | 승인/거부 작업이 있는 대기 중인 매칭 |
| 에이전트 채팅 | 자연어 쿼리를 위한 대화형 AI |
| 설정 | 매칭 가중치, 임계값, 표시 기본 설정 구성 |
매칭 상세 보기에는 검토자가 모든 점수 구성 요소를 살펴볼 수 있는 여섯 가지 탭이 있습니다: 요약, 확정적, 확률적, AI/임베딩, LLM 분석 및 원시 데이터. 검토자는 단순히 숫자를 보는 것이 아니라, 시스템이 왜 특정 방식으로 매칭 점수를 매겼는지 정확히 알 수 있습니다.
10. Azure 아키텍처
전체 솔루션은 Azure에서 실행됩니다:
| 서비스 | 역할 |
|---|---|
| Azure Cosmos DB (Gremlin + NoSQL) | 환자 그래프 저장 및 매칭 결과 영구화 |
| Azure OpenAI (GPT-5.2 + text-embedding-3-small) | LLM 분석 및 의미론적 임베딩 |
| Azure Container Apps | FastAPI REST API 호스팅 |
| Azure AI Foundry Agent Service | OpenAPI 도구를 갖춘 대화형 에이전트 |
| Azure Log Analytics | 중앙 집중식 로깅 및 모니터링 |
Cosmos DB의 Gremlin API(그래프 탐색)와 NoSQL API(매칭 결과 문서) 간의 분리는 의도적입니다. 그래프 쿼리는 관계 탐색에 탁월합니다("이 식별자에 연결된 모든 환자를 찾아라"). 문서 쿼리는 필터링 및 집계에 탁월합니다("지난 24시간 동안의 자동 병합 매칭을 모두 보여줘").
11. 우리가 배운 것
AI는 확정적 매칭을 대체하는 것이 아니라 보강합니다.
세 가지 계층 접근 방식이 작동하는 이유는 각 계층이 다른 계층의 약점을 보완하기 때문입니다:
- 확정적 방식은 쉬운 사례를 빠르고 확실하게 처리합니다.
- 확률적 방식은 정확한 매칭이 놓치는 오타, 별명, 형식 차이를 잡아냅니다.
- AI는 모호한 중간 영역에 대해 의미론적 이해와 사람이 읽을 수 있는 추론을 제공합니다.
LLM은 의사 결정자가 아니라 검토자의 조수로서 가장 가치 있습니다.
저희는 LLM 가중치를 최종 점수의 20%로 의도적으로 유지합니다. LLM의 진정한 가치는 생성하는 구조화된 추론, 즉 매칭 점수 뒤에 있는 "이유"에 있습니다. 인간 검토자는 AI가 생성한 분석을 통해 매칭 신호를 이해할 수 있을 때 사례를 더 빠르게 처리합니다.
그래프 데이터베이스는 환자 식별에 자연스럽게 적합합니다.
환자 매칭은 근본적으로 관계 문제입니다. "누가 누구와 식별자를 공유하는가?" "어떤 환자들이 이 골든 레코드에 연결되어 있는가?" "모두 같은 사람일 수 있는 기록의 클러스터를 보여줘." 이들은 그래프 탐색 쿼리입니다. 관계형 테이블에서 이것을 모델링하는 것은 가능하지만, 데이터 모델을 활용하는 대신 데이터 모델과 씨름하는 것입니다.
FHIR 상호운용성은 통합 마찰을 거의 0으로 줄여줍니다.
FHIR R4 번들을 입력 형식으로 받아들임으로써, 이 서비스는 사용자 정의 커넥터 없이 모든 최신 EHR에서 데이터를 수집할 수 있습니다. 이는 엄청난 실용적인 이점입니다. EMPI 프로젝트에서 가장 어려운 부분은 대개 데이터를 가져오는 것이지, 매칭하는 것이 아닙니다.
12. 직접 사용해 보기
환자 매칭 서비스는 전적으로 Azure 서비스와 오픈 소스 도구를 기반으로 구축되었습니다 https://github.com/dondinulos/patient-matching-service:
- FastAPI, Streamlit, Azure AI SDK를 사용하는 Python
- 그래프 저장을 위한 Azure Cosmos DB(Gremlin API)
- 임베딩 및 LLM 분석을 위한 Azure OpenAI
- 대화형 에이전트를 위한 Azure AI Foundry
- 배포를 위한 Azure Container Apps
- FHIR 테스트 데이터 생성을 위한 Synthea
매칭 알고리즘(Jaro-Winkler, Soundex, Metaphone, Levenshtein)은 순수 Python 구현을 사용합니다. 독점 매칭 엔진은 필요하지 않습니다.
새로운 EMPI를 처음부터 구축하든, 기존 EMPI에 AI 기능을 추가하든, 세 가지 계층 접근 방식은 확정적 매칭의 확실성, 확률적 점수 매기기의 유연성, AI 강화 분석의 지능 등 모든 면에서 최고의 이점을 제공합니다.
마지막 생각
AI를 사용하여 EMPI를 구현할 수 있을까요?
예. 그리고 그 답은 "모든 것을 LLM으로 대체하라"가 아닙니다. "AI가 가장 큰 가치를 더하는 곳, 즉 의미론적 이해, 자연어 추론, 인간 검토자 보강에 AI를 사용하고, 확정적 및 확률적 매칭을 기반으로 유지하라"입니다.
이러한 조합은 어떤 단일 접근 방식보다 더 정확합니다. 그래프 데이터베이스는 관계를 쿼리할 수 있게 만듭니다. 대화형 에이전트는 시스템에 접근성을 부여합니다. 그리고 이 모든 것이 FHIR-native 데이터 수집과 함께 Azure에서 실행됩니다.
환자 매칭은 해결된 문제가 아닙니다. 하지만 스택에 AI가 있다면, 훨씬 더 관리하기 쉬운 문제입니다.
태그: 헬스케어, Azure, AI, EMPI, FHIR, 환자 매칭, Azure Cosmos DB, 그래프 데이터베이스, 상호운용성