본문으로 건너뛰기

ADR 0050: 다수 당사자 사건 모델

배경

사건 모델의 당사자는 client/opponent 단일 string (+ phone/address/ idNumber 부속 필드). 그러나 실무에서 다수 당사자는 예외가 아니라 기본인 도메인이 있다:

  • 상속 (Pack 4): 공동상속인 N 명이 원고/피고 — 현재 heirCount 숫자만
  • 공사대금·대여금 (Pack 1): 연대보증인, 공동채무자
  • 부동산 (Pack 3): 공동임차인, 전대차 관계

현재는 메모란에 우겨넣어 비정형 데이터로 유실 (한 줄 본질 누수) + 소장·위임장 당사자 표시가 1:1 만 자동.

client/opponent1,785+ 참조 — 전수 rename/restructure 는 RecoveryType→CaseDomainType 때와 같은 이유로 비채택.

결정 (Proposed)

1. additive 배열 — 기존 필드는 "대표 당사자" 로 유지

cases/{caseId}.parties?: Array<{
id: string; // 안정 식별자
side: "client" | "opponent"; // 진영
role: string; // "원고" | "피고" | "연대보증인" | "공동상속인" 등 자유 라벨
name: string;
phone?: string; address?: string; idNumber?: string;
isPrimary: boolean; // 진영당 정확히 1명 — client/opponent 필드와 동기화
}>
  • client/opponent (+ 부속 필드) 는 대표 당사자의 denormalized 사본 으로 영구 유지 — 기존 1,785+ 호출부·목록·검색·포털·이해충돌 검사 모두 무수정 동작.
  • parties 미존재 = 단일 당사자 사건 (기존 데이터 전부) — 마이그레이션 0.
  • 쓰기 경로는 mutation 1곳 (updateCaseParties) 으로 집중: 배열 갱신 시 isPrimary 항목을 client/opponent 필드에 자동 동기화 (split-brain 차단, formatAmount SSoT 와 같은 원칙).

2. 소비 지점 (구현 순서)

  1. updateCaseParties (business-logic) + 사건 상세 당사자 섹션 배열 편집 UI
  2. 서면 빌더 (소장 당사자 표시·위임장·정산서) — parties 있으면 전원 표기
  3. 이해충돌 검사 (P0-4) — 대조 소스에 parties 배열 포함
  4. 포털 — 대표 당사자 기준 유지 (변경 없음)

3. 비목표

  • client/opponent 필드 제거 (영구 denorm)
  • 당사자별 개별 포털 토큰 (대표 1인 유지)
  • 집단소송 규모 (Phase 4 별도 — 본 ADR 은 ~10명 수준)

근거

  • additive + denorm 동기화는 이 코드베이스에서 2회 검증된 전략 (CaseDomainType alias · checklist status map)
  • "메모란 우겨넣기" 는 서면 자동화·이해충돌 대조에서 보이지 않는 데이터

구현 상태

  • 2026-06-10: ADR 작성 (Proposed). 구현은 "너홀로프로만으로 모든 업무" 캠페인 P2-10 후속 세션 — 본 문서가 설계 SSoT.
  • 2026-06-10: §2 구현 순서 1~4 전부 ship (Accepted):
    • ① mutation (PR #2729)packages/business-logic/src/cases/update-parties.ts updateCaseParties single-writer (isPrimary → client/opponent denorm 동기화, 대표 주소 변경 시 AddressMeta 리셋). 순수 층 parties-pure.ts (deep entry @neohollo/business-logic/cases/parties) 의 CasePartiesArraySchema invariant (진영별 ≥1 · isPrimary 진영당 1 · id 유일 · ≤20) + effectivePartiesFromCase (denorm 합성 폴백) 가 소비 지점 공용 진입점.
    • ② 사건 상세 UI (PR #2732)CasePartiesDialog (유일 편집 UI) + updateCasePartiesAction wrapper + CaseInfoSection 공동 당사자 표시. generic 편집 경로 (updateCaseFieldsAction) 의 당사자 denorm 키 변경은 party-denorm-guard 가 거부 (split-brain defense-in-depth).
    • ③ 서면 빌더 (PR #2734) — 소장·지급명령 "원고 1/2…" 번호 전원 표기
      • 서명 "외 N명" (어댑터가 caseData.parties 자동 주입 — 호출부 수정 0), 위임계약서·소송위임장 공동 위임인 전원 서명란, 정산서 의뢰인 전원 나열.
    • ④ 이해충돌 검사 (PR #2736) — 진영별 [대표+공동] cross 대조, 기존 사건 parties[] 비대표 (연대보증인·공동상속인) 도 §31 대조 소스.
    • 포털 (§2-4) 은 대표 당사자 기준 유지 — 변경 없음.