--- title: 2026-06-14 일일 노트 source_type: daily-note status: raw tags: [daily, ca-tmpl, ca-skeleton, clean-architecture, logging, observability] date: 2026-06-14 branches: [ feature-log-management-contract ] --- # 2026-06-14 > Layer: `raw/daily-notes/` — 그날의 혼합 일일 기록. 그 자체는 wiki로 옮기지 않으며, `/ingest`가 promotable 항목만 추출. ## 활성 브랜치 - `feature-log-management-contract` (implemented) — [[raw/branch-notes/feature-log-management-contract]] ## 한 일 feature-log-management-contract Phase C2 전면 구현 — 문서화돼 있던 DRIFT-1~6 + sampling 전부 코드로 해소. - 사용자 결정 2건 확정: **Q1**=dependency 실패 레벨 어댑터종류 분리(optional fail-open WARN / core HTTP ERROR), **Q2**=full HMAC pseudonymization. - DRIFT-2 Layer 1 masking: `LogMaskingPatterns`(정규식 SSOT) → `SecretMaskingJsonGeneratorDecorator`(JSON) + `SecretMaskingMessageConverter`(`%maskedMsg`). - DRIFT-1/D10: `logback-spring.xml` `` 분기(local/dev pattern vs prod JSON). - DRIFT-3: `RequestLoggingFilter` uri_template. - DRIFT-4: `OutboundDependencyLogger` snake_case + dependency_type + WARN + 5 callers. - DRIFT-5: `MetricsAsyncAppender` → `log.appender.dropped.total`. - DRIFT-6: `UserPrincipalPseudonymizer`(port) + `HmacUserPrincipalPseudonymizer`(adapter-identifier) + `PseudonymizationConfig`/`PrivacySettings`(app-bootstrap) + filter 배선. - sampling: `SamplingTurboFilter`. - 오케스트레이션: Task 1~4 는 `ca-implementer` 디스패치, Task 5(logback XML/custom appender/turbofilter/masking)는 API 검증(MaskingJsonGeneratorDecorator, AsyncAppenderBase, springProfile) 후 메인 에이전트 직접 구현. 리뷰 체인 3단계 ALL PASS. ## 배운 점 - `LogstashEncoder`(JSON)는 PatternLayout 을 우회 → `%replace` 마스킹 무력. JSON 은 `MaskingJsonGeneratorDecorator` 필요. → [[raw/blog-topics/logback-layer1-secret-masking-json-vs-pattern-2026-06-14]] - `AsyncAppender` 드롭 결정론 테스트: `discardingThreshold > queueSize` 트릭. → [[raw/interviews/deterministic-logback-asyncappender-drop-metric-test-2026-06-14]] ## 트러블슈팅 - `@Component` 필터에 생성자 의존성 추가 → `@WebMvcTest` 슬라이스(`OperationalContractRuntimeTest`) 컨텍스트 로드 실패. `@Import(PseudonymizationConfig.class)` 로 해소. → [[raw/errors/webmvctest-component-filter-constructor-dep-breaks-slice-2026-06-14]] - `ca-implementer` Task 4 디스패치가 중간 truncate(5 callers 중 2개만 수정) → 메인 에이전트가 잔여 3 callers + 4 test 단언을 직접 마무리. - local profile 실행 시 logback status 경고 3종 발견. (1)`` deprecated → `class` 로 교체(내 변경, 수정 완료 + `SecretMaskingMessageConverterTest` 로 `class` 등록 + 마스킹 검증). (2)``-in-`` + (3)`` 속성 deprecated **해소(2026-06-14, 사용자 재요청)**: Janino `` 6곳 → logback 1.5.20+ 내장 `KV` (조회 경로 `OptionHelper.propertyLookup(local,context)` 가 Janino 와 동일 → `` 값 그대로 읽어 동작 무변경). `` 내 `` 3개는 logback 권고대로 `` 를 top-level `+` 로 감싸 un-nest(ASYNC×FILE 2×2, 한 번에 하나만 활성). **janino 의존성(build.gradle) 제거** — dead dep(소스 `condition=` 0건) + Janino 동적 코드 컴파일 보안취약(2027 제거예정) 해소. 검증: logback-core 1.5.34(`dependencyInsight`) + `bootRun`(local) `|-WARN/|-ERROR` 0건 + 정상 기동(Tomcat:8080) + local PatternLayout 분기 정상. **owner 정정**: 토글 구조는 base-template 커밋 f9ad280("ca 구조 변경") 유래, 파일 owner 는 [[raw/branch-notes/feature-log-management-contract]] (D4 logging 바인딩, 최신 touch d10a751) — 직전 `migration-startup-contract D8` 귀속은 conflation(D8 은 build.gradle 인접 `logstash-logback-encoder` 줄을 govern). 기록: owner § Audit & Findings DRIFT-7. local=human-readable PatternLayout 분기(D10)는 의도대로 동작. ## 면접·포트폴리오로 옮길 만한 것 - [[raw/interviews/deterministic-logback-asyncappender-drop-metric-test-2026-06-14]] - [[raw/blog-topics/logback-layer1-secret-masking-json-vs-pattern-2026-06-14]] ## 내일로 넘긴 것 - D9 전용 audit appender(생산자 부재 + retention은 data-retention 소유 → 보류). - ~~pre-existing ArchUnit 실패(`OutboundHttpSettings` B7 false-positive, commit d702572)~~ **해결(사용자 요청)**: `CleanArchitectureTest` B7 규칙 `outbound_adapter_method_returns_only_domain_or_primitives` 에 `@ConfigurationProperties` 제외 추가(기존 `@Configuration` 제외와 동일 패턴). 세팅 홀더는 외부 응답 매핑 surface 가 아니라 config 바인딩 타입 → ACL 누출 대상 아님. 규칙의 실제 보호(외부 응답 타입 누출 차단)는 그대로 — 순수 filter narrowing. `:app-bootstrap:test` 0 실패. - ~~logback ``-in-`` / `condition` 속성 deprecation 정리(사용자 재요청)~~ **해결(2026-06-14)**: 트러블슈팅 §(2)/(3) — Janino→내장 `PropertyEqualityCondition` + `` un-nest + janino dep 제거, `bootRun` 검증 완료. - 사용자 커밋 대기.