1 개요
본 알고리즘은 노인 통합돌봄 사례(Case)에 대해 영업 중인 제공기관(Provider) 중
적합한 후보를 점수화하여 상위 N개를 추천합니다.
AI라는 표현을 사용하지만 규칙 기반 가중합(weighted sum) 알고리즘이며, 학습 데이터로부터 가중치를 도출하지 않습니다. 가중치는 명시적으로 정의되어 있고 누구나 본 문서에서 확인할 수 있습니다.
⚠ 책임 구조:
본 점수는 의사결정을 보조합니다. 최종 매칭 확정은 담당자의 판단으로 이루어지며,
모든 결정은
MatchSnapshot 테이블에 영구 기록되어 사후 감사가 가능합니다.
2 입력 / 출력
입력:
Case: 사례 (어르신, 거주 권역, 필요 서비스, 케어 트랙)limit: 반환할 상위 후보 수 (기본 10)
출력:
- 후보별
provider,total_score(0~100),breakdown(항목별 점수) - 분석 모드(
call_with_analysis)에서는 funnel 메트릭 + 단계별 제외 기관 추가
3 가중치와 근거
각 항목의 가중치는 다음과 같이 정의되어 있습니다. 본 표는 AiMatchScoreCalculator::WEIGHTS에서 자동 추출됩니다 — 코드와 영원히 동기화됩니다.
| 항목 | 가중치 | 근거 |
|---|---|---|
| 공단평가 | 50% | 국민건강보험공단의 공식 평가가 가장 신뢰할 수 있는 품질 지표이므로 최대 비중 |
| 지역근접 | 20% | 어르신/보호자의 이동 부담과 응급 대응 속도를 반영 |
| 서비스 | 15% | 사례에 명시된 필요 서비스를 실제 제공할 수 있어야 매칭이 의미 있음 |
| 입소여력 | 15% | 정원 여유는 즉시 수용 가능 여부 — 매칭 실현성 보장 |
⚠ 한계:
현재 가중치는 도메인 전문가의 합의로 설정된 휴리스틱이며,
실제 매칭 성공률 데이터를 통한 ML 학습 결과는 아닙니다.
충분한 매칭 결정 데이터가 축적되면 재조정 가능합니다.
4 점수 계산식
종합 점수는 4개 항목 점수의 가중합으로 계산됩니다:
total_score = Σ (item_score × item_weight)
= 공단평가(0~100) × 50% + 지역근접(0~100) × 20% + 서비스(0~100) × 15% + 입소여력(0~100) × 15%
= 공단평가(0~100) × 50% + 지역근접(0~100) × 20% + 서비스(0~100) × 15% + 입소여력(0~100) × 15%
각 항목 점수 산출 방식:
- 공단평가:
provider.nhis_total_score를 0~100으로 정규화. 미입력 시 기본값 60점. - 지역근접: 같은 권역 100점. 다른 권역은
100 - (거리km × 4), 최저 40점. 거리는 권역 중심점 간 Haversine 공식(지구 반지름 6371km). - 서비스: 사례 필요 서비스 중 기관이 제공 가능한 비율 × 100. 최저 30점.
- 입소여력:
정원 데이터 있으면
(1 - 현원/정원) × 200 + 50, clamp(20~100). 없으면 직원 1인당 활성사례 비율로 추정.
5 필터링 파이프라인
점수화 전에 다음 단계로 후보를 필터링합니다. 각 단계 통과 기관만 다음 단계로 진입합니다.
| 단계 | 조건 | 제외 사유 라벨 |
|---|---|---|
| 1. 운영 중 | status: operating | — |
| 2. 케어 트랙 일치 | care_track == case.care_track | "이 사례는 X 트랙인데 기관은 Y 트랙" |
| 3. 서비스 제공 가능 | can_provide_service?(provider) | "필요 서비스 → 기관 유형 매칭 불가" |
| 4. 정원 여유 | current_occupancy < capacity (정원 데이터 있을 때) | "정원 N명 모두 사용 중" |
| 5. 점수화 + 상위 N | limit으로 컷오프 | "점수 X (N위 — 상위 컷오프에 못 듦)" |
각 단계별 제외된 기관과 사유는 사례 분석 페이지에서 펼쳐서 확인 가능합니다.
6 데이터 출처
- 공단평가 점수: 국민건강보험공단 평가 데이터 (provider.nhis_total_score)
- 권역 좌표: 남양주시 5개 권역 중심점 (Region.latitude, longitude)
- 기관 정보: 기관 자체 등록 + 운영 담당자 갱신 (provider.updated_at으로 신선도 추적)
- 정원/현원: 기관 자체 입력 (provider.capacity, current_occupancy)
- 필요 서비스: 사례 접수 시 담당 매니저가 지정 (case.services)
각 데이터의 갱신 시점은 매칭 결과 화면의 "데이터 출처" 섹션에서 확인할 수 있으며, 7일 이상 미갱신 시 신선도 경고가 표시됩니다.
7 한계와 알려진 이슈
- 가중치(50/20/15/15)는 휴리스틱 — ML 학습 기반 아님
- 지역 거리는 권역 중심점 직선거리 — 실제 도로 거리/이동 시간 미반영
- 입소여력 점수화 상수(×200+50)는 실증 검증 없는 휴리스틱
- 공단평가 미입력 기관은 기본값 60점으로 동일하게 처리 — 실제 점수와 다를 수 있음
- 실시간 정원 변화 미반영 — 갱신 주기 의존
8 버전 이력
v1.0
현재
2026-03-03
초기 출시 — 규칙 기반 가중합 알고리즘
- 가중치: 공단평가 50% / 지역근접 20% / 서비스유형 15% / 입소여력 15%
- 지역 점수: 같은 권역 100점, 다른 권역은 Haversine 거리 기반 (최저 40점)
- 서비스 매칭: 트랙별 분기 (장기요양은 직접 매핑, 비장기요양은 카테고리 매핑)
- 필터링 파이프라인: 운영 중 → 케어 트랙 → 서비스 가능 → 정원 여유 → 점수화
- 공단 평가 누락 시 기본값 60점 (평균 이하 페널티)
- 입소여력: 정원 데이터 있으면 (정원-현원)/정원 비율, 없으면 직원 1인당 활성사례 추정