# DSN-02 · Layer 1 유지율 곡선 상세 (E1) — 디자인 명세

> 본 문서는 `design/02_layer1_retention.html`의 명세이다. 평가모델 Layer 1(유지율 곡선) 알고리즘(E1)의 시각화 핸드오프 문서. CLI 구현 시 데이터 매핑·차트 라이브러리 결정에 사용한다.

## 1. 목적

| 항목 | 값 |
|---|---|
| 화면 ID | DSN-02 / layer1-detail |
| 연계 알고리즘 | E1 — 회차별 conditional retention rate by 상품군×채널×연령×vintage |
| 1차 사용자 | Bobot 데이터 사이언티스트, 보험계리사 |
| 2차 사용자 | 인수팀 리드 (Dashboard에서 진입해 가정 점검) |
| 핵심 결정 | "이 GA의 유지율 곡선이 모델로 신뢰할 만한가? 백테스트 ±15% 합격선 안인가?" |
| 첫 0.5초 인지 목표 | 25회차 conditional + 백테스트 오차가 합격선 안인지 |

## 2. 화면 영역 구성

| 영역 | 컴포넌트 | 역할 |
|---|---|---|
| Sidebar | DSN-01과 동일 | "Layer 1 유지율 곡선" active |
| Topbar | breadcrumb + 액션 3개 | ← Dashboard / CSV 내보내기 / 백테스트 재실행 |
| Filter rail | 상품군/채널/연령대/Vintage + 갱신 버튼 | 코호트 4축 선택 |
| Cohort chips | 자주 쓰는 코호트 + 신규 저장 | 빠른 전환 |
| KPI 4-up | 25회차 conditional + 13회차 + 37회차 + 백테스트 오차 | 핵심 수치 |
| Chart card | SVG 회차별 유지율 곡선 | 메인 시각화 |
| Backtest panel | MAE/RMSE/테일 오차 + 합격선 띠 시각화 | 신뢰도 점검 |
| Heatmap panel | 상품군 × 연령대 25회차 % | 강점/약점 식별 |
| Assumptions table | 5행 모델 가정 + 민감도 | v0 잠정성 명시 |
| Doc note | 시안 안내 | brand-dna 확정 후 제거 |

## 3. 데이터 계약

```jsonc
// GET /api/v1/evaluation/:book_id/layer1
//      ?product=protection&channel=ga&age=30s&vintage=2022
{
  "book_id": "BK-2026-014",
  "model_version": "v0.4",
  "cohort": {
    "product": "protection",
    "channel": "ga",
    "age": "30s",
    "vintage": "2022",
    "n_contracts": 4820
  },
  "curve": {
    // x축: 회차 (개월). 1, 2, ..., 73 (또는 60)
    "months": [1, 2, 3, /*...*/ 60],
    "model_predicted": [0.99, 0.98, /*...*/ 0.55],
    "actuals": [0.99, 0.98, /*...*/ 0.81],   // null after current cutoff
    "industry_avg": [0.99, 0.97, /*...*/ 0.51],
    "ci_lower": [/* model - band */],
    "ci_upper": [/* model + band */]
  },
  "kpi": {
    "retention_25m": 0.812,
    "retention_25m_vs_industry_pp": 0.034,
    "retention_13m": 0.934,
    "retention_37m_estimated": 0.681
  },
  "backtest": {
    "mae_pp": 0.132,           // 13.2%
    "rmse_pp": 0.158,
    "tail_error_pp": 0.194,    // 49+ 회차
    "pass_threshold_pp": 0.15,
    "pass": true,              // mae_pp <= 0.15
    "tail_pass": false,        // tail_error_pp > 0.15 → 경고
    "history_window": "2021-2025"
  },
  "heatmap": {
    "axes": {"row": "product", "col": "age"},
    "rows": ["protection","health","saving","variable"],
    "cols": ["20s","30s","40s","50s","60+"],
    "values_pct": [
      [76.4, 81.2, 87.6, 84.1, 79.2],
      [74.8, 79.5, 82.7, 78.4, 71.6],
      [68.4, 72.1, 76.8, 75.3, 71.0],
      [66.2, 70.4, 71.8, 68.6, 64.5]
    ],
    "highlighted_cell": {"row": 0, "col": 1}    // 현재 코호트
  },
  "assumptions": [
    {"key":"hazard_distribution","value":"Weibull(k=1.4, λ=42)","source":"v0.3 추정 그대로","sensitivity":"k±0.2 → ±2.1%p"},
    {"key":"rule_1200_start","value":"2027.07 가정","source":"금융위 발표","sensitivity":"3개월 변동 → ±0.4%p"},
    {"key":"vintage_normalization","value":"2022 base=1.00","source":"금감원 5년치","sensitivity":"±0.05 → ±1.2%p"},
    {"key":"economic_cycle","value":"미반영 (v1)","source":"-","sensitivity":"잠재 ±3%p"},
    {"key":"low_data_segments","value":"변액 60+, 저축 20대","source":"합리적 가정 후 문서화","sensitivity":"가정 의존"}
  ]
}
```

## 4. 차트 구현 권고

### 회차별 유지율 곡선 (메인)
- **권장 라이브러리**: D3.js v7 (SVG, 정밀 컨트롤) 또는 Apache ECharts (한국어/내장 툴팁/PDF export 우수)
- **요소 5종**: 모델 예측 라인 / 실측 라인 (cutoff 이전만) / 업계 평균 (점선) / ±15% 신뢰구간 (band) / 25회차 강조선
- **인터랙션**:
  - hover → 회차/예측%/실측%/오차 툴팁
  - click 25회차 마커 → KPI 영역 강조
  - 우측 상단 토글로 신뢰구간 ON/OFF
- **Y축**: 50–100% (절단축). 50% 미만은 의미 없음
- **X축**: 1~60(또는 73)회차. 12회차 단위 그리드

### 백테스트 띠
- 단일 horizontal bar에 −25%~+25% 범위
- ±15% 영역에 accent-soft 하이라이트
- 빨간 vertical 임계선 2개(±15%)
- 모델 마커 위치 = MAE의 부호 + 절댓값

### 히트맵
- 4(상품군) × 5(연령대) = 20셀
- 색상 스케일: 60% → 65% → 70% → 75% → 80% → 85%+ (6 단계)
- 현재 선택 코호트 셀에 1px hero color 보더

## 5. 상호작용 명세

| 트리거 | 동작 |
|---|---|
| 필터 4종 변경 → 곡선 갱신 클릭 | URL `?product=&channel=&age=&vintage=` 갱신, 곡선/KPI/백테스트/히트맵 동시 fetch |
| 코호트 chip 클릭 | 필터값 일괄 설정 + 자동 곡선 갱신 |
| 신규 코호트 저장 | 모달 → 이름 입력 → 사용자 프로필에 저장 |
| CSV 내보내기 | 현재 코호트의 회차별 데이터 (월·예측·실측·CI) CSV |
| 백테스트 재실행 | 서버 측 백테스트 잡 트리거. 진행 시 KPI 영역 skeleton |
| 히트맵 셀 클릭 | 해당 셀 코호트로 필터 자동 변경 |
| 25회차 강조선 hover | 우측 annotation 박스 강조 |

## 6. 상태 처리

| 상황 | UX |
|---|---|
| 데이터 부족 세그먼트 (n < 100) | KPI 영역에 "n < 100, 가정 의존" 노란 배지 |
| 백테스트 합격 (mae ≤ 15%) | 백테스트 패널 상단 ✅ + ok-tone |
| 백테스트 실패 (mae > 15%) | 백테스트 패널 상단 🚫 + 빨간 배지 + Dashboard에서 진입 시 경고 |
| 테일 오차 > 15% | 노란 메타 태그 "37+ 회차 데이터 부족" |
| 현재 시점 cutoff 이후 | 실측 라인은 null 처리, 곡선 모델만 표시 |
| Vintage 미선택 (전체) | 곡선은 vintage별 mini multiples 4–5개 (v1 예정) |

## 7. 가독성·접근성

- ✅ 차트 색상은 hero/accent/회색 점선 — 색맹 대응(라인 두께·점선 패턴 차별)
- ✅ 모든 셀 색상 + 숫자 동시 표시 (히트맵)
- ✅ SVG에 `role="img"` + `aria-label`
- ✅ Y축 절단축임을 50% 라벨로 명시
- ✅ 키보드 사용자: 필터 → chip → 차트 → 백테스트 → 히트맵 → 가정표 순 탭

## 8. 디자인 토큰 — DSN-01과 100% 공유

CSS `:root` 토큰 동일. brand-dna.json 확정 후 한 번에 교체.
신규 토큰 없음. 추가된 시각 요소는:
- 히트맵 색상 스케일 6단계 (`.h-65 ~ .h-90`) — 향후 `--heat-N` 변수로 추출 가능

## 9. 핸드오프 체크리스트

- [ ] 차트 라이브러리 결정 (D3 vs ECharts) — 외부 자문 PDF 출력 품질로 판단
- [ ] 백테스트 잡 비동기 처리 (Sidekiq/Celery) — 시뮬 시간 ≥30s 가정
- [ ] CSV export는 Excel 호환 (UTF-8 BOM)
- [ ] §3 응답 스키마 OpenAPI 작성
- [ ] 곡선 SVG는 PDF 내보내기 시 vector 유지 (raster 변환 금지)

## 10. 다음 화면

| 화면 | ID | 진입 |
|---|---|---|
| Dashboard | DSN-01 | breadcrumb / "← Dashboard" |
| 시나리오 비교 | DSN-03 | (없음 — 별도 진입) |
| Layer 2 부당승환 상세 | (미정) | v1에 추가 |
