Skip to content

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

OCR·VLM

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) 레포 문서

PII·마스킹

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회)으로 한다 채택 기획 단계 레포 문서

RAG·코퍼스

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 코퍼스 스테이징

DB·마이그레이션

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건

Clone this wiki locally