Repository navigation
Decision Log
donghoong2 edited this page Oct 28, 2026
·
1 revision
dev
a9974a0(2026-10-12) 기준
위키의 사례 기록과 구성 페이지에 흩어진 결정을 표 하나로 모은 색인이다. 결정을 뒤집었더라도 옛 결정은 지우지 않고 대체됨 → 새 결정 ID로 남긴다. 주제별로 나눴고, ID는 절 순서대로 붙였다. 형식은 Backend 위키의 결정 로그와 같다.
근거 열은 그 결정의 맥락·검토한 선택지·결과가 적힌 페이지를 가리킨다. 지금 코드가 근거인 결정은 레포 문서(모듈 README와 docs/)라고 적었다.
| 상태 | 뜻 |
|---|---|
| 채택 | 지금 유효한 결정이다. 괄호 안에 이 결정이 밀어낸 옛 방식을 적기도 한다 |
| 대체됨 → D-xxx | 한때 채택했으나 다른 결정으로 바뀌었다 |
| 폐기 | 검토하거나 시도했으나 채택하지 않았다 |
| 제안 | 방향은 정했으나 아직 적용하지 않았다 |
ID는 한 번 붙이면 바꾸지 않는다. 새 결정은 주제에 맞는 절에 넣고, 번호는 로그 전체에서 가장 큰 번호 다음을 쓴다.
| ID | 결정 | 상태 | 시점 | 근거 |
|---|---|---|---|---|
| D-001 | AI 엔진은 백엔드를 호출하지 않고 SQS 메시지와 공유 DB로만 연결한다 | 채택 | 기획 단계 | 프로젝트 개요 |
| D-002 | 문서 업로드·접수는 Spring Boot가 받고 AI 엔진은 큐만 소비한다 | 채택(FastAPI가 업로드를 받아 동기 OCR로 폼을 채우는 안을 대체) | 2026-06 | 프로젝트 개요 |
| D-003 | OCR·VLM·LLM·임베딩을 모두 자체 GPU 인스턴스의 Ollama·in-process로 서빙하고 외부 AI API를 쓰지 않는다 | 채택 | 기획 단계 | 프로젝트 개요 |
| D-004 | OCR 트리거 브로커로 Kafka(MSK)를 쓴다 | 대체됨 → D-005 | 2026-06 ~ 08 | Backend: Kafka→MSK→SQS |
| D-005 | 브로커를 SQS로 바꾸고 메시지 계약(OcrJob·ReportJob JSON)은 유지한다. 인증은 워커 IAM Role |
채택 | PR #53 (2026-08-10) | Backend: Kafka→MSK→SQS |
| D-006 | OCR·corpus 워커는 SSM으로, 리포트 워커·챗봇은 매니페스트 레포 image.tag 커밋 → Argo CD로 배포하고 CI는 실패만 알린다 |
채택(SSM → 백엔드 EC2 compose 경로를 대체) | PR #69·#70 (2026-10-12) | 프로젝트 개요 |
| D-007 | corpus 워커를 GPU 인스턴스에서 떼어 경량 인스턴스로 옮긴다 | 채택 | PR #44 (2026-08-05) | 코퍼스 스테이징 |
| D-008 | OCR 이미지에서 CUDA 베이스를 빼고 torch 번들 CUDA + 호스트 드라이버 주입을 쓴다 | 채택(nvidia/cuda 베이스를 대체) |
PR #47 (2026-08-08) | 레포 문서 |
| ID | 결정 | 상태 | 시점 | 근거 |
|---|---|---|---|---|
| D-009 | GPU를 오래 쓰는 OCR·리포트 생성은 큐 뒤의 워커로 분리하고 업로드는 즉시 202로 끝낸다 | 채택 | 기획 단계 | OCR 워커 구성 |
| D-010 | at-least-once를 전제로 진입부 멱등 조회·결정적 ID·업서트로 중복 전달을 흡수한다 | 채택 | PR #21 (2026-07-06) | OCR 워커 구성 |
| D-011 | 인프로세스 재시도를 두지 않고 재전달은 브로커에 맡긴다. 결정적 실패(NonRetryableError)는 즉시 종결하고, poison은 수신 횟수 상한으로 명시 스킵한다(DLQ 미도입) |
채택 | PR #53, #58 | 청구 fan-in |
| D-012 | 큐 메시지에는 식별자만 싣고 내용은 DB에서 읽는다 | 채택 | 기획 단계 | 리포트 워커 구성 |
| D-013 | OCR 문서 1건이 성공할 때마다 ReportJob을 발행한다 |
대체됨 → D-014 | ~ 2026-08-13 | 청구 fan-in |
| D-014 | 청구의 모든 문서가 종결된 뒤 청구당 ReportJob 1건을 발행한다. 종결 수는 job_id 집합에서 파생하고 저장과 같은 트랜잭션으로 센다 |
채택 | PR #58 (2026-08-13) | 청구 fan-in |
| D-015 | 리포트 워커는 claim_id로 청구의 전 문서를 읽어 문서 경계 헤더와 함께 병합한다 |
채택(대표 문서 1건 조회를 대체) | PR #62 (2026-08-14) | 청구 fan-in |
| D-016 | 필수 문서 미인식(blocked)은 기록만 하고 발행하지 않는다 |
대체됨 → D-017 | ~ 2026-08-16 | 청구 fan-in |
| D-017 | 필수 유형 없음(missing) ∪ 일부 문서 실패(incomplete)를 모두 ocr_quality='needs_reupload' 발행으로 수렴시킨다 |
채택 | PR #67 (2026-08-16) | 청구 fan-in |
| D-018 | 품질 미달은 리포트 워커가 reports.status='NEEDS_REUPLOAD'로 남긴다. 새 상태값은 백엔드가 먼저 배포한다 |
채택 | PR #65 (2026-08-16) | 청구 fan-in |
| D-019 | 워커는 다른 워커·팀 소유 테이블에 새 쓰기 경로를 만들지 않고 메시지로 기존 경로를 태운다 | 채택 | PR #67 (2026-08-16) | 청구 fan-in |
| ID | 결정 | 상태 | 시점 | 근거 |
|---|---|---|---|---|
| D-020 | OCR 엔진으로 PaddleOCR을 쓴다 | 대체됨 → D-021 | 기획 단계 | 프로젝트 개요 |
| D-021 | surya-ocr 0.17을 in-process로 고정하고 결과를 라인 구조(텍스트·bbox·신뢰도)로 보존해 세 트랙이 함께 쓴다 | 채택 | PR #21 | OCR 워커 구성 |
| D-022 | 표 보완 VLM으로 glm-ocr(0.9B)을 쓴다 | 폐기(의료 용어 오독·무한 반복) | 2026-08-02 | VLM 하이브리드 |
| D-023 | 표 문서 유형 또는 surya 평균 신뢰도 < 0.90인 페이지만 VLM으로 보완하고, groundedness(≥ 0.3)·재마스킹·잔류 검사를 통과한 페이지만 채택한다 | 채택 | PR #41 (2026-08-07) | VLM 하이브리드 |
| D-024 | VLM을 용도별로 나눈다: 표 전사 qwen3.6:35b-a3b, PII 좌표 qwen3-vl:8b-instruct | 채택(단일 모델 통일안을 대체) |
d1a0604 (2026-08-04) |
VLM 하이브리드 |
| D-025 | 재업로드 판정에 문서 전체 신뢰도 임계값이나 유형별 필수 필드 목록을 쓴다 | 폐기 | 2026-08-02 | VLM 하이브리드 |
| D-026 | 재업로드 판정은 신뢰도 < 0.90 그리고 (이름 스팬 없음 또는 도메인 엔티티 없음). 이름은 마스킹 전 원문으로 본다 | 채택 | PR #41 | VLM 하이브리드 |
| D-027 | 분류가 불확실하면 백엔드가 준 doc_type_hint를 채택한다(신뢰도는 낮게 기록) |
채택(OTHER 폴백을 대체) | PR #58 | 청구 fan-in |
| D-028 | 엔티티 스키마를 소비 필드(icd·admission_days·surgery) 중심으로 맞추고 나머지는 품질 판정 전용으로 명시한다 |
채택 |
ddf4b01 (2026-08-04) |
초록불 테스트 |
| D-029 | VLM 호출에 num_ctx=16384를 명시한다. 리포트 워커 LLM은 업로드 상한(5건) 안에서 실측상 여유가 있어 지정하지 않는다 |
채택 | PR #60 (2026-08-13) | num_ctx 잘림 |
| D-030 | 큰 판형 PDF는 압축폭탄 한도를 해제하지 않고 페이지별로 DPI를 낮춰 렌더한다 | 채택 | PR #40 (2026-08-01) | 레포 문서 |
| ID | 결정 | 상태 | 시점 | 근거 |
|---|---|---|---|---|
| D-031 | 텍스트 마스킹을 필수로, 이미지 검은블록 마스킹을 병행한다(손해사정사 열람용) | 채택 | 2026-06-30 | 원본 삭제 게이트 |
| D-032 | 정규식 ∪ NER 스팬으로 마스킹하고, 고민감 PII가 남으면 저장하지 않는다(fail-closed) | 채택 | 이슈 #18 | OCR 워커 구성 |
| D-033 | NER은 줄 단위 배치 추론 + 원문 오프셋 보정으로 돌리고, 모델 로드·추론을 lock으로 직렬화한다 | 채택(문서 통째 추론을 대체) |
6289afe, 180c815 (2026-07-01) |
NER 512토큰 |
| D-034 | 계좌번호 잔류는 하드 차단하지 않고 추적만 한다 | 채택 | 6289afe |
NER 512토큰 |
| D-035 | 이미지 마스킹의 라벨-값 분리를 bbox 근접 라인 클러스터링(과잉 마스킹)으로 푼다 | 폐기(제안 후 D-036으로 대체) | 2026-08-02 | 초록불 테스트 |
| D-036 | 라인 마스킹은 페이지 스팬을 라인 로컬 오프셋으로 잘라 재사용하고 재검출하지 않는다 | 채택 |
ffd9987 (2026-08-04) |
초록불 테스트 |
| D-037 | VLM은 좌표를 주지 않으므로 이미지 마스킹은 surya bbox로만 한다 | 대체됨 → D-038 | 2026-08-02 | VLM 하이브리드 |
| D-038 | 저신뢰도 문서에서만 VLM grounding 박스를 기존 박스에 추가한다(대체 아님) | 채택 |
3871217 (2026-08-04) |
VLM 하이브리드 |
| D-039 | 원본 삭제는 bbox 커버리지 ≥ 95%와 재OCR 잔류 검사를 모두 통과하고 저장이 성공한 뒤에만, 백그라운드로 한다. 실패는 outbox 스윕(15분, 최대 5회) 후 Lifecycle 백스톱 | 채택 |
bde698d (2026-08-05) |
원본 삭제 게이트 |
| D-040 | 이미지 마스킹 검증 실패는 예외가 아니라 원본 보존 + 경고로 끝낸다 | 채택 | bde698d |
원본 삭제 게이트 |
| D-041 | 비식별 사본은 SSE-KMS로 저장한다 | 채택 | bde698d |
원본 삭제 게이트 |
| D-042 | PII 복호화 실패와 컨텍스트 조립의 예상 밖 타입은 차단 경로로 보내고, details 파싱 실패는 폴백으로 둔다 |
채택 | PR #54·#56 (2026-08-12) | PII 복호화 |
| ID | 결정 | 상태 | 시점 | 근거 |
|---|---|---|---|---|
| D-043 | 후유장해는 항목 판단만 LLM이, 지급률 검증·합산은 코드가 한다 | 채택 |
8abf032 (2026-07-09) |
장해지급률 검증 |
| D-044 | 지급률 검증은 인용 구절이 원문에 실재하고 소수까지 보존한 지급률이 그 인용 안에 있을 때만 통과한다 | 채택(정수부 숫자의 원문 전체 검색을 대체) | PR #26 (2026-08-09) | 장해지급률 검증 |
| D-045 | 좌·우의 눈·귀·팔·다리·손가락·발가락은 다른 부위로 합산하고, 좌우 미상은 같은 부위로 본다 | 채택 | PR #26 | 장해지급률 검증 |
| D-046 | 약관에 장해분류표가 없으면 금감원 표준표를 가입일 기준 판본으로 쓰고 신뢰도를 낮춘다 | 채택 |
f46c9eb (2026-07-12) |
장해지급률 검증 |
| D-047 | 확정 장해 항목이 없으면 0%가 아니라 재평가 대상으로 안내한다 | 채택 |
39f8ef4 (2026-07-16) |
장해지급률 검증 |
| D-048 | 보험금은 범위로 제시한다. 하한은 조건이 명확한 정액 특약, 후유장해는 상한에만 | 채택(제시금액 × 배수 어림을 대체, 가입금액 미보유 시 폴백으로 유지) |
dc30c6f (2026-07-16) |
리포트 워커 구성 |
| D-049 | 분석 단계 실패는 부분 결과로 계속하고, 컨텍스트 구성·OCR 결과 유실·최종 저장 실패만 작업 실패로 올린다 | 채택 | 이슈 #11 | 리포트 워커 구성 |
| D-050 | 사용자 알림은 사용자가 할 수 있는 조치가 있을 때만, 차단 사유가 있으면 경고는 보내지 않고, 문구는 카탈로그 한 곳에서 관리한다 | 채택 | 이슈 #11 | 리포트 워커 구성 |
| D-051 | 입력·생성·출력 3단계 가드레일을 리포트·챗봇 공용 모듈로 둔다 | 채택 | PR #42 (2026-08-03) | 리포트 워커 구성 |
| D-052 | 챗봇은 WebSocket 직결·비스트리밍(완성 응답 1회)으로 한다 | 채택 | 기획 단계 | 레포 문서 |
| ID | 결정 | 상태 | 시점 | 근거 |
|---|---|---|---|---|
| D-053 | 벡터 저장소로 전용 벡터 DB 대신 PostgreSQL + pgvector를 쓴다 | 채택(Pinecone·Qdrant 검토 후) | 2026-06 | 검색 파이프라인 |
| D-054 | 벡터 인덱스는 HNSW, 타입은 halfvec(1024)
|
채택 | 2026-06 | 검색 파이프라인 |
| D-055 | 키워드 검색에 pg_search(BM25)를 쓴다 | 대체됨 → D-056 | 2026-06 | 검색 파이프라인 |
| D-056 | 키워드 검색은 Kiwi 형태소 토큰 + tsvector(GIN) + trigram 오타 보정으로 한다 |
채택 | PR #25·#28 (2026-07) | 검색 파이프라인 |
| D-057 | Elasticsearch를 별도로 운영한다 | 폐기 | 2026-06 | 검색 파이프라인 |
| D-058 | 키워드·벡터 결과를 RRF(k=60)로 합친다 |
채택 | PR #28 | 검색 파이프라인 |
| D-059 | 하이브리드 후보에 리랭커(bge-reranker-v2-m3)를 붙인다 | 제안(오프라인 평가에서 채택, src/rag 미반영) |
2026-09 | 검색 파이프라인 |
| D-060 | 약관 조항 분류는 정규식 → qwen3.6:35b-a3b → 키워드 규칙 순으로 한다 | 채택 | 2026-09 | 검색 파이프라인 |
| D-061 | corpus 워커는 큐 이벤트 대신 폴링 데몬으로, SKIP LOCKED claim과 지수 백오프로 돈다 |
채택(즉시 재큐를 대체) | PR #36 (2026-07-30) | 코퍼스 스테이징 |
| D-062 | 중복 방지는 S3 HeadObject(내용주소 키)에 맡기고 DB 문서 키는 비유니크로 둔다 |
채택(전역 UNIQUE를 대체) | PR #36 | 코퍼스 스테이징 |
| D-063 | 코퍼스 첨부의 모든 타입(HWP·zip·txt·md·json)을 정직하게 지원한다 | 대체됨 → D-064 | PR #57 (2026-08-12) | 코퍼스 스테이징 |
| D-064 | 코퍼스는 PDF만 받는다. 판정은 파일명 기반 filetype.detect() 한 곳에서, 판정 불가는 실패 |
채택 | PR #59 (2026-08-13) | 코퍼스 스테이징 |
| D-065 | 잘못 올라간 객체 정리는 DB(failed, s3_key=NULL) → S3 삭제 순서로, 기본 dry-run |
채택 | PR #59 | 코퍼스 스테이징 |
| ID | 결정 | 상태 | 시점 | 근거 |
|---|---|---|---|---|
| D-066 | DB를 core·ai·corpus 스키마로 나누고 role별로 소유한다 |
채택 | 2026-08 | 스키마 미지정 마이그레이션 |
| D-067 |
migrations/ 하나를 각 워커가 기동 시 통째로 실행한다 |
대체됨 → D-068 | ~ 2026-08-09 | 스키마 미지정 마이그레이션 |
| D-068 | 마이그레이션을 migrations/ai/·migrations/corpus/로 나누고 배포 경로 필터도 워커별로 나눈다 |
채택 | PR #51 (2026-08-09) | 스키마 미지정 마이그레이션 |
| D-069 | 크로스팀 GRANT는 수동 스크립트가 아니라 마이그레이션의 self-grant로 두고, 필요한 컬럼만 연다 | 채택 | PR #64·#65·#66 (2026-08-15 ~ 16) | 청구 fan-in |
| D-070 | 이미 존재하는 테이블의 정의 변경은 IF NOT EXISTS DDL 수정이 아니라 별도 ALTER 마이그레이션으로 한다 |
채택 |
4f92aab (2026-08-03) |
저장 0건 |
구성과 설계 근거
OCR 인식 · VLM 보완
개인정보 보호 · 마스킹
리포트 정확도
배포 · 데이터 파이프라인
레퍼런스