init: 클린 기반 auth 서버 설계

This commit is contained in:
DongHyeonka
2026-07-24 14:30:18 +09:00
parent 471db0203d
commit 8a1ac1e769
3642 changed files with 275893 additions and 1 deletions
@@ -0,0 +1,102 @@
# 2026-05-04 jqwik 속성 기반 테스트 도입
## 한 줄 결론
보안 핵심(LogSanitizer)에 속성 기반 테스트를 추가하여 **application 모듈 분기 커버리지를 14.5% → 78.9%로 +64.4%p 끌어올렸으며**, 매퍼/JSON Pointer 변환에 대한 회귀 안전망(presentation 라인 3.4% → 24.8%)을 동시에 확보했다. 같은 측정 조건(exclusion 없음, 같은 명령어, 같은 도구 버전)에서 사과-사과 비교한 결과다.
## 변경 범위
- 신규 jqwik 의존성 도입 (1.9.3) — JUnit Platform에 `includeEngines` 추가
- 신규 속성 테스트 4개 클래스, 총 30개 속성
- `LogSanitizerPropertyTest` (11 속성, application 모듈)
- `ApiErrorHttpStatusMapperPropertyTest` (5 속성, presentation 모듈)
- `JsonPointerConversionPropertyTest` (8 속성, presentation 모듈)
- `RequestBoundApiResultFactoryPropertyTest` (6 속성, bootstrap 모듈)
- JaCoCo + PIT 플러그인 도입, Tier 기반 임계치 정책 수립
- 영향 범위: application / presentation / bootstrap 모듈
## Before / After 수치 (사과-사과 측정)
### 라인 커버리지
| 모듈 | BEFORE | AFTER | 변화 |
|---|---|---|---|
| `application` | 42.3% | **70.9%** | **+28.6%p** |
| `presentation` | 3.4% | **24.8%** | **+21.4%p** |
| `infrastructure` | 81.5% | 81.5% | — |
| `bootstrap` | 80.7% | 80.3% | -0.4%p (오차) |
### 분기 커버리지
| 모듈 | BEFORE | AFTER | 변화 |
|---|---|---|---|
| `application` | 14.5% | **78.9%** | **+64.4%p** |
| `presentation` | 3.3% | **42.3%** | **+39.0%p** |
| `infrastructure` | (브랜치 없음) | (브랜치 없음) | — |
| `bootstrap` | 59.7% | 56.6% | -3.1%p |
### 메서드 / 클래스
| 모듈 | METHOD before → after | CLASS before → after |
|---|---|---|
| `application` | 41.8% → 63.6% | 75.0% → 81.2% |
| `presentation` | 5.9% → 25.0% | 18.2% → 40.0% |
| `infrastructure` | 79.2% → 79.2% | 100% → 100% |
| `bootstrap` | 82.9% → 83.8% | 85.7% → 85.2% |
### PIT (단언 강도 측정)
| 모듈 | Mutations | Killed | Test Strength |
|---|---|---|---|
| `application` | 64 | **46 (72%)** | 82% |
| `presentation` | 75 | 24 (32%) | **92%** (커버된 영역에서) |
> **PIT는 BEFORE에 측정되지 않았다.** PIT 플러그인 자체가 이 사건에서 처음 도입되었기 때문에 비교값은 없으며, AFTER의 절대 수치만 의미를 갖는다.
## 자동 검출 가능해진 회귀 시나리오
이전에는 단위 테스트가 0개였던 영역에 임의 입력 fuzz가 추가되어, 다음 회귀가 PR 단계에서 즉시 잡힌다:
1. **`LogSanitizer.clientIp` 마스킹 누락** — 임의의 0~255 옥텟 IPv4 주소 1만건에 대해 마지막 옥텟이 0으로 마스킹되지 않으면 즉시 실패.
2. **매퍼의 `AUTHENTICATION_REQUIRED → 401` 변경** — 정확값 단언 + PIT가 잡음.
3. **신규 `ClientFacingErrorCode` 추가 후 매퍼 분기 누락** — 매핑 테이블 가드 + classpath 가드 + 속성 테스트의 3중 안전망.
4. **JSON Pointer `~`/`/` 이스케이프 누락 (RFC 6901 위반)** — 임의 입력 fuzz로 즉시 실패.
5. **TraceIdFilter 누락 시 traceId가 JSON `null`로 직렬화되는 회귀** — sentinel `"-"` 강제.
## 측정 조건 (재현용)
| 항목 | 값 |
|---|---|
| BEFORE 커밋 | `c9bfdf2` (2026-05-03) |
| AFTER 커밋 | `6f62490` (2026-05-04) — measurement run에서 build.gradle의 `**/config/**` exclusion 임시 제거 |
| 측정 명령어 | `./gradlew clean test jacocoTestReport` |
| PIT 측정 명령어 | `./gradlew :application:pitest :presentation:pitest` |
| JaCoCo 버전 | 0.8.13 |
| PIT 버전 | 1.19.1 (junit5-plugin 1.2.2) |
| jqwik 버전 | 1.9.3 |
> **운영 빌드 차이점**: 운영 `build.gradle`에는 `**/config/**` exclusion이 적용되어 있어 일반 `./gradlew jacocoTestReport`는 bootstrap을 0%로 보고한다. 본 비교는 사과-사과를 위해 그 exclusion을 임시 제거한 측정값이다. exclusion 정밀화는 별도 follow-up.
## 한계 / 미해결
1. **presentation의 PIT mutation kill이 32%로 보이는 이유**는 통합 테스트가 bootstrap 모듈에 있어 PIT 측정에서 빠지기 때문이다. *커버된 영역에서의 단언 강도는 92%로 매우 높다*. 다음 사건: 멀티모듈 aggregate 리포트 도입.
2. **bootstrap의 운영 빌드 0%**는 측정 누락이지 코드 미커버가 아니다. 다음 사건: `**/config/**` exclusion을 핸들러를 포함하지 않도록 정밀화.
3. **Tier 1 임계치(95%+)에는 미도달.** 현재는 baseline 모드(게이트 비활성)이며, 점진적 상향 일정은 `docs/testing-coverage-policy.md`에 정의됨.
## 첨부 (원본 리포트)
- BEFORE 스냅샷: `coverage-history/v0.0.1-SNAPSHOT/2026-05-04-jqwik-before/`
- AFTER 스냅샷: `coverage-history/v0.0.1-SNAPSHOT/2026-05-04-jqwik-after/`
각 스냅샷의 모듈별 진입점:
```
{snapshot}/application/jacoco/html/index.html # JaCoCo 라인/분기 표
{snapshot}/application/pitest/index.html # PIT (AFTER 스냅샷에만 존재)
{snapshot}/presentation/jacoco/html/index.html
{snapshot}/presentation/pitest/index.html
{snapshot}/bootstrap/jacoco/html/index.html
{snapshot}/infrastructure/jacoco/html/index.html
```
> `coverage-history/`는 git ignore 되어 로컬 전용. 같은 측정을 재현하려면
> SUMMARY.md의 "측정 조건 (재현용)" 섹션 참고.