--- title: ca-tmpl - Privacy / File / Domain Modeling 결정 source_type: project status: verified confidence: high tags: [ca-tmpl, privacy, gdpr, file-upload, ddd, actually-implemented, locally-verified, documented-only] related_projects: [ca-tmpl] last_reviewed: 2026-07-02 --- # ca-tmpl - Privacy / File / Domain Modeling 결정 > Layer: `wiki/projects/` — 내 프로젝트 사실. 일반 개념 / 공식 기준 / 트레이드오프는 [[wiki/concepts/privacy-file-domain-modeling]] 참조. ## 프로젝트 컨텍스트 **ca-tmpl skeleton** — 도메인 로직을 얹기 전 단계의 운영/보안/도메인 계약을 사전에 고정하기 위한 Spring Boot 기반 Clean Architecture 템플릿 프로젝트. 2026-07-02 기준 일부 privacy/domain guardrail은 코드화됐고, file handling/DSR/backup erasure는 여전히 계획 또는 문서 단계다. 본 문서는 Phase E Group G-J에서 결정된 3축 — **(1) Privacy / Retention**, **(2) File / Resource Handling**, **(3) Domain Modeling Guardrails** — 의 ca-tmpl 적용 결정사항을 정리한다. 핵심 결정값 요약: - **Privacy**: 30/180/365일 3-tier log retention, HMAC-SHA-256 + 90일 salt rotation pseudonymization, DSR SLA 30일/14일(intake → execution), `is_sample` 컬럼 기반 sample 데이터 분리. - **File**: app 10MB / global 12MB / gateway 20MB 3-layer size limit, content-type allowlist 6종(image/jpeg, image/png, image/gif, application/pdf, text/plain, application/zip 등), temp orphan 1h cleanup sweeper, ICAP antivirus gateway 기본값. - **Domain Modeling**: VO private constructor + factory method, aggregate root mutator non-public(package-private/protected), domain layer logger ban(ArchUnit forbidden import), safe reason enum, invariant in constructor, Vernon Option A(ORM 외부 매핑) 채택. ## 실제 구현 내용 (`actually-implemented`) - `adapter-identifier`의 `HmacUserPrincipalPseudonymizer`와 `app-bootstrap`의 `PseudonymizationConfig`, `PrivacySettings`가 user principal pseudonymization 기반을 제공한다. - `RequestLoggingFilter`가 raw principal이 아니라 pseudonymized principal을 MDC에 넣는 흐름을 갖는다. - `docs/registries/env-keys.yaml`, `secrets-classification.yaml`, `mdc-keys.yaml`, `capabilities.yaml`, `error-codes.yaml`에 privacy/file/domain 관련 registry row가 존재한다. - domain purity, logger ban, forbidden imports, aggregate boundary guard는 `CleanArchitectureTest` 계열과 domain/sample tests에서 일부 검증된다. - file upload handler, DSR workflow, backup cryptographic erasure, ICAP integration은 아직 구현되지 않았다. ## 로컬/dev 검증 (`locally-verified`) - `./gradlew check` 통과(2026-07-02, `BUILD SUCCESSFUL`, 114 tasks). - `HmacUserPrincipalPseudonymizerTest`, `PseudonymizationConfigTest`, `PrivacySettingsTest`, `RequestLoggingFilterTest`가 pseudonymization/logging path를 검증한다. - `CleanArchitectureTest`와 domain/sample tests가 domain forbidden import와 invariant 일부를 검증한다. - file upload, DSR, backup erasure는 로컬 검증되지 않았다. ## 운영 검증 (`prod-verified`) **없음.** ca-tmpl skeleton 자체가 운영 환경에 배포된 적 없음. ## 문서/계획만 존재 (`documented-only` / `planned`) 다음 항목은 구현된 privacy/domain guardrail과 아직 문서/계획으로 남은 file/DSR/backup 영역을 분리한다. ### Privacy (canonical §19) - log retention 30/180/365일 3-tier 분류 (info / warn-business / audit-security) - HMAC-SHA-256 + 90일 salt rotation pseudonymization (PII column 대상) - DSR SLA: intake → identity verification → execution 30일, internal execution 14일 - `is_sample` boolean column으로 sample / production 데이터 분리, retention job exemption - backup retention: cryptographic erase 방식 채택 의도(per-principal envelope key는 **미결정**, 후속 보강 후보) - per-principal envelope key 패턴 선택 (2026-05-22) — **needs-confirmation**, Phase C2 결정 보류. (a) per-principal CMK / (b) per-principal DEK + master CMK envelope / (c) tenant-level CMK 3종 후보. 근거: [[raw/official-docs/gdpr-cryptographic-erasure-envelope-key-pattern]]. HMAC + 90d salt rotation은 forward security만 제공하므로 backup의 Art.17 단건 erasure에는 별도 envelope key 구조가 필요함. ### File (canonical §29 H, branch-notes) - size limit 3-layer: Spring multipart 10MB (app envelope error) / reverse proxy 12MB / gateway WAF 20MB raw 413 - content-type allowlist 6종 + endpoint별 재검증 - temp file > 1h not closed → orphan 판정, sweeper가 삭제 (tus resumable session과 별도 threshold 필요성은 문서화만) - ICAP gateway antivirus(ClamAV 등) 기본값, in-app daemon 채택 X - direct S3 presigned URL은 **검토만 완료**, 채택 미정 ### Domain Modeling (canonical §29 I-J, branch-notes) - Value Object: private constructor + static factory method, invariant in constructor 강제 - Aggregate root: mutator를 public 금지(package-private/protected만 허용) - Domain layer logger ban: `org.slf4j.Logger`, `java.util.logging.*`, HTTP type, `@Entity`, `@Service` 등 forbidden import — ArchUnit 테스트로 강제할 계획 - safe reason enum (도메인 거부 사유 noun 형태 enum) - Vernon Option A(ORM 매핑을 domain 외부 mapper/persistence layer에서 수행) 채택, Option B(JPA direct annotation in domain) 거절 - CQRS / event sourcing **미채택**, "domain event = transport-free fact" 정의만 차용 ### 검토했으나 채택하지 않은 대안 (concept 참조) 3 sub-topic 각각 5종 이상의 대안을 검토 — 자세한 trade-off는 [[wiki/concepts/privacy-file-domain-modeling]] §"한계 / 주의점". - Privacy: PII detection SaaS(AWS Macie / OneTrust / TrustArc) — vendor 종속으로 skeleton 기본값 부적절. - File: in-app ClamAV daemon, direct S3 presigned URL only, tus resumable 표준 채택, magic-byte sniffing only — 각각 trade-off로 인해 채택 보류. - Domain: Anemic model, Pure DDD aggregates(over-engineering), Event sourcing, JPA direct annotation(Option B), Functional domain modeling(Scala/F#) — 모두 검토 후 거절. ## 면접에서 말할 수 있는 범위 ### 자신 있게 답할 수 있는 질문 - GDPR Art.17 backup erasure 처리 방식과 cryptographic erase의 의미 - HMAC + salt rotation의 의미와 anonymization이 아닌 이유 (brute-force 가능 input space에서 tokenization 우위) - file size 3-layer(app / proxy / gateway)의 defense-in-depth 의미와 trade-off - ICAP gateway의 한계 (HTTPS E2E TLS 환경에서 평문 검사 불가) - VO private constructor + factory method 이유 (invariant 보장, 잘못된 인스턴스 생성 차단) - ORM 외부 매핑(Vernon Option A) vs JPA direct annotation(Option B) trade-off ### 적당히 답할 수 있는 질문 - Vernon Option A vs B의 코드량 / 학습 비용 trade-off 비교 - NIST SP 800-88 cryptographic erase의 backup 적용 메커니즘 (per-principal envelope key 구조 필요성 정도까지) - DSR 운영 패턴 일반론 (intake → verification → scope → execution → audit) ### 답하면 안 되는 질문 (모른다고 해야 함) - "GDPR DSR 요청을 실제로 처리해본 경험이 있는가?" → **없음.** ca-tmpl은 skeleton 단계, 운영 데이터 없음. - "ICAP scan을 운영 환경에서 운영해본 경험은?" → **없음.** 설계 / 문서 단계. - "domain event sourcing을 도입한 경험은?" → **없음.** ca-tmpl은 event sourcing **미채택**, transport-free fact 정의만 차용. - "per-principal envelope key를 적용한 경험은?" → **없음.** 후속 보강 후보로 문서화만 됨. ## 과장 금지 지점 외부 설명(면접 / 이력서 / README / 블로그)에서 사실보다 부풀려지기 쉬운 표현들. - **"HMAC + salt rotation으로 anonymization을 적용했다"** → **부정확 (가장 흔한 과장)**. ENISA / IAPP 기준 명확히 **pseudonymization**이지 anonymization이 아니다. brute-force 가능 input(휴대폰 11자리 등)에서는 tokenization이 우위인 구간이 존재하며, 무엇보다 HMAC + salt rotation은 **forward security만** 제공한다 — rotation 이전에 기록된 backup 안의 hash는 그대로 잔존하므로 GDPR Art.17 backup erasure 수단으로 사용할 수 없다. backup 단건 erasure는 별도의 per-principal envelope key 구조(NIST SP 800-88 § 2.5 CE)가 필요하며 ca-tmpl은 **미결정** 상태이다. - **"ICAP antivirus gateway로 모든 위협을 막는다"** → 부정확. HTTPS end-to-end TLS 환경에서 gateway가 payload를 평문으로 보지 못하는 한계가 있음. post-upload async scan 보완 필요. - **"ca-tmpl은 pure DDD 기반이다"** → 부정확. Vernon Option A(ORM 외부 매핑)만 차용했으며, CQRS / event sourcing은 미채택. "transport-free domain event 정의만 차용"이 정확한 표현. - **"per-principal envelope key 구조를 적용해 GDPR Art.17 backup erasure를 완전 처리한다"** → 부정확. 후속 보강 후보로 **미결정** 상태. 현재는 cryptographic erase 의도만 문서화됨. - **"DSR SLA 30일은 GDPR 요구치다"** → 부정확. GDPR Art.12는 "원칙적으로 1개월(연장 시 +2개월)"이며 30/14일은 ca-tmpl 내부 운영 결정값. - **"retention job / file upload handler / DSR workflow를 구현했다"** → 거짓. pseudonymization/logging guard와 domain guardrail 일부는 구현됐지만, 이 운영 기능들은 문서/계획 단계다. ## 관련 개념 - [[wiki/concepts/privacy-file-domain-modeling]] ## Sources - [[raw/project-notes/ca-skeleton-operational-contract]] §19 Domain Application Readiness Contract, §29 G-J 외부 근거 / 대안 조사 - [[raw/branch-notes/feature-data-retention-privacy-contract]] — log retention by profile, HMAC pseudonymization, DSR SLA, backup retention 결정 - [[raw/branch-notes/feature-file-resource-handling-contract]] — upload size 3-layer, content-type allowlist, temp file cleanup, antivirus position 결정 - [[raw/branch-notes/feature-domain-modeling-guardrails]] — VO private constructor, aggregate mutator non-public, domain forbidden import 결정 ## Cluster / 묶음 - [[wiki/blog/ca-tmpl-privacy-file-domain-modeling-2026-07-02]]