Files
llm-wiki/wiki/concepts/privacy-file-domain-modeling.md

14 KiB

title, source_type, status, confidence, tags, related_projects, last_reviewed
title source_type status confidence tags related_projects last_reviewed
Privacy / File / Domain Modeling (GDPR + ICAP + Vernon) llm-generated draft medium
privacy
gdpr
file-upload
ddd
domain-modeling
ca-skeleton
2026-05-22

Privacy / File / Domain Modeling (GDPR + ICAP + Vernon)

Layer: wiki/concepts/ — 일반 개념. Phase E Group G-J(3 branch / 10 raw) 통합. 내 프로젝트 사실 판정은 raw/project-notes/ca-skeleton-operational-contract §19, §29 G-J 와 각 branch-note에서 별도로 다룸.

Summary

서비스가 도메인을 얹기 전에도 (1) 개인정보·로그의 보존/삭제 계약, (2) 파일 업로드/다운로드의 안전성 계약, (3) 도메인 모델의 프레임워크 격리 계약 세 축이 사전에 정의되어야 한다. 본 문서는 이 세 축의 공식 기준과 그 한계를 묶어서 다룬다. 대표 결정값(예: 30/180/365일 retention, HMAC-SHA-256 + 90일 salt rotation, DSR SLA 30/14일, 3-layer file size limit, content-type allowlist 6종, VO private constructor, aggregate root mutator non-public)은 모두 개별 branch-note의 결정 사항을 따른다.

Standard (공식 정의)

Privacy / Retention

  • GDPR Art.25 — Data protection by design and by default: 처리 시작 시점부터 "최소한의 데이터, 가능한 짧은 보존, 가능한 적은 노출"이 기본값이어야 한다. Art.17(Right to erasure)은 controller가 합리적 조치로 backup·복제본을 포함해 삭제하도록 요구한다.
  • NIST SP 800-88 Rev.1 — Cryptographic Erase (CE): 키를 안전하게 폐기함으로써 데이터 자체를 sanitize한 것으로 인정하는 공식 방법. backup·offline media의 GDPR Art.17 대응 수단으로 사용 가능.
  • ENISA / IAPP — Pseudonymization techniques: HMAC-with-secret-key, tokenization, encryption 등을 pseudonymization 기법으로 분류. salt rotation, lookup table 분리 보관, brute-force input space 등을 비교 기준으로 제시.
  • DSR (Data Subject Request) 운영 패턴: intake → identity verification → scope classification(export/delete) → execution → audit evidence. GDPR Art.12는 응답을 "원칙적으로 1개월(연장 시 +2개월)" 내로 요구.

File / Resource Handling

  • ICAP / RFC 3507 — Internet Content Adaptation Protocol: HTTP proxy/gateway가 antivirus engine(예: ClamAV)에 payload를 위임 검사하는 표준 프로토콜. 업로드 단의 외부 콘텐츠 검사를 app 외부에서 수행하는 정석.
  • AWS S3 — Presigned URL upload: 서버가 서명된 PUT URL을 발급하면 클라이언트가 직접 S3에 업로드. app/gateway의 대역폭/CPU 부담 없이 large object 처리 가능.
  • tus.io — Resumable upload protocol (v1.0.0): HTTP PATCH 기반 resumable upload. 대용량/장시간 업로드를 chunk 단위 재개 가능하도록 표준화.
  • multipart/form-data + size limit: Spring spring.servlet.multipart.max-file-size 등 framework 단의 1차 enforcement는 envelope error 변환의 책임을 진다. gateway/WAF는 raw 차단 보조.

Domain Modeling

  • Vaughn Vernon — Effective Aggregate Design (IDDD): 4 rules — (1) protect true invariants in consistency boundary, (2) design small aggregates, (3) reference other aggregates by identity, (4) update other aggregates eventually. ORM-friendly constructor / package-private setter를 통해 ORM과 도메인 모델의 분리를 권장(이하 "Option A: ORM 외부 매핑").
  • Martin Fowler — Anemic Domain Model: 데이터만 있는 entity + 모든 로직이 service에 모이는 구조를 anti-pattern으로 정의. rich model(state + behavior + invariant 동소화)을 기본으로 제시.
  • Greg Young — CQRS / Event Sourcing: domain event는 transport-free fact, command와 query 모델 분리, event stream을 source of truth로 두는 패턴. event sourcing과 CQRS는 동일 개념이 아님(Young 본인이 구분).

한계 / 주의점

Privacy

  • HMAC + salt rotation을 anonymization으로 단정 금지: ENISA·IAPP 기준으로도 HMAC은 pseudonymization이지 anonymization이 아니다. brute-force 가능한 input space(예: 한국 휴대폰 11자리, 주민번호 일부 자리)에서는 attacker가 가능한 모든 입력을 미리 HMAC 계산할 수 있으므로 tokenization(랜덤 토큰 + 별도 lookup table)이 우위인 구간이 존재한다. 또한 HMAC + salt rotation은 forward security만 제공한다 — 새로 기록되는 식별자에 한해 rotation 이전 hash가 무효화될 뿐, 이미 작성된 backup 안의 hash는 그대로 잔존한다. 따라서 HMAC을 backup erasure 수단으로 오해하면 안 된다.
  • salt rotation interval (예: 90일) 자체로 안전성이 증명되지 않음. 회전 주기 동안의 collision/lookup 정책, 옛 salt 보관 기간(예: 90일 retain), 키 저장소의 안전성이 별도로 요구된다.
  • GDPR Art.17 + backup → envelope key 필요: backup·snapshot에서의 erasure는 단건 삭제가 어렵다. NIST SP 800-88 Rev.1 § 2.5 Cryptographic Erase (CE)는 인정되는 방법이나, per-principal envelope key 구조(주체별 DEK를 master CMK로 wrap, 삭제 요청 시 해당 principal의 DEK 폐기 → 모든 backup ciphertext가 동시에 unreadable)가 사전에 설계되어 있어야 한다. HMAC + salt rotation은 이 단건 erasure를 제공하지 못한다. 비용 trade-off에 따라 (a) per-principal CMK / (b) per-principal DEK + master CMK envelope (AWS KMS·GCP KMS 권장) / (c) tenant-level CMK (Stripe·Twilio·Shopify 류 SaaS 일반 패턴) 중 선택이 필요하다. 일반적 대량 KEK 폐기로는 Art.17 단건 요청을 만족하기 어렵다.
  • PII detection SaaS(AWS Macie / OneTrust / TrustArc) 채택은 vendor 종속을 만든다. skeleton 단계의 기본값으로 두는 것은 부적절.

File / Resource

  • ICAP gateway가 모든 위협을 막는다고 단정 금지: HTTPS end-to-end TLS 환경에서는 gateway가 payload를 평문으로 보지 못해 ICAP 검사가 어려운 구간이 있다. 그 경우 post-upload async scan(예: quarantine bucket + worker)이 대안.
  • Direct S3 presigned URL: 앱이 payload를 보지 못하므로 in-app validation(예: content-type 재검증, watermark, business rule)이 부재한다. content-type/size 검증은 S3 측 정책 + 후행 worker로 분산되어야 한다.
  • tus resumable upload: session 식별자와 orphan temp file이 충돌한다. ca-tmpl 류의 "temp file > 1h not closed = orphan, sweeper가 삭제" 정책은 tus의 정상 long session을 잘못 삭제할 수 있어 threshold 분리가 필요하다.
  • in-app ClamAV daemon: 앱 인스턴스마다 daemon dependency가 늘고, scaling/CPU 비용이 함께 증가한다. skeleton 단계의 기본값으로는 부적절.
  • content-type "sniffing 금지" vs "allowlist": client-supplied Content-Type 신뢰는 위험하나, 동시에 서버측 sniffing(magic byte 추론)도 우회 가능. allowlist + endpoint별 검증이 현실적 절충.
  • size limit 3-layer (예: app 10MB / global 12MB / gateway 20MB): 의도된 defense-in-depth지만, gateway 단의 raw 413은 envelope을 우회한다는 점이 trade-off다. 어느 layer에서 어떤 응답 형태를 보장할지 사전에 정해야 한다.

Domain Modeling

  • Functional domain modeling (Scala / F#): 패러다임은 매력적이나 JVM Java 중심 팀의 학습 비용이 크다. skeleton 기본 채택은 부적절.
  • Anemic model: 로직이 service로 흩어져 invariant 위치가 불명확해진다. Fowler가 anti-pattern으로 명시.
  • Pure DDD aggregates: 작은 도메인에 과한 학습 비용 / 코드량을 강제할 수 있다. Vernon 본인도 "small aggregate"를 강조.
  • Event sourcing: event store, snapshot, projection 등 운영 비용이 크다. 도메인 event = transport-free fact라는 정의만 차용하고 event sourcing은 채택하지 않는 절충이 일반적.
  • JPA direct annotation in domain (Vernon Option B / 우아한형제들 초기 글 스타일): @Entity / @Column 등을 domain class에 직접 두는 방식. 도메인이 persistence를 "안다"는 점에서 framework 격리 규칙과 충돌. forbidden import 규칙을 둔 코드베이스에서는 채택 불가.
  • @Entity / @Service / Logger / HTTP type을 도메인이 import: 도메인의 framework neutrality가 깨진다. ArchUnit 등의 forbidden-import 테스트로 강제할 수 있다.

Project Application

Interview Questions

  • GDPR Art.17 erasure 요청이 들어왔을 때, backup·snapshot까지 어떻게 처리하는가? Cryptographic erase와 per-principal envelope key 구조가 왜 필요한가?
  • HMAC + salt rotation을 pseudonymization으로 채택할 때 salt rotation 주기(예: 90일)는 어떤 의미를 갖는가? brute-force 가능한 input space에서는 왜 tokenization이 더 안전할 수 있는가?
  • 파일 업로드 size limit을 app(예: 10MB) / global(예: 12MB) / gateway(예: 20MB) 3-layer로 두는 이유는? 각 layer가 어떤 실패 모드를 책임지는가?
  • ICAP / RFC 3507 기반 gateway antivirus의 한계는? HTTPS end-to-end TLS 환경과 in-app ClamAV daemon은 각각 어떤 trade-off를 만드는가?
  • Value Object의 생성자를 private/factory only로 두는 이유는? aggregate root의 mutator를 package-private/protected로 강제하는 이유는?
  • ORM 매핑을 도메인 외부에서 수행(Vernon Option A)하는 방식과, JPA annotation을 도메인에 직접 다는 방식(Option B / 우아한형제들 초기 글 스타일)의 trade-off는?

Do Not Overclaim

  • "HMAC + salt = anonymization"으로 단정 금지. ENISA·IAPP 기준 pseudonymization. brute-force 가능 input(휴대폰·주민번호 일부 등)에서는 tokenization이 우위인 구간이 존재.
  • "backup도 GDPR Art.17로 완전 삭제했다"고 단정 금지. cryptographic erase + per-principal envelope key 구조가 실제로 설계되어 있어야 가능한 진술이다. 단순 backup 보존만으로는 단건 삭제 불가.
  • "DSR SLA 30/14일은 GDPR 요구치"라고 단정 금지. GDPR Art.12는 "원칙적으로 1개월(연장 시 +2개월)"이며, 30/14일은 내부 운영 결정값이다.
  • "ICAP gateway antivirus가 모든 위협을 막는다"고 단정 금지. HTTPS E2E TLS 환경 한계와 post-upload async scan 필요성이 있다.
  • "Direct S3 presigned URL이 가장 안전하다"고 단정 금지. in-app validation 부재 → quarantine bucket + 후행 worker 분리가 추가로 필요.
  • "우리는 pure DDD 기반"이라고 단정 금지. Vernon Option A(ORM 외부 매핑) 차용이며, CQRS / event sourcing은 채택하지 않은 절충이다. "transport-free domain event 정의만 차용했다"가 더 정확한 표현.
  • "Vernon Option B(JPA direct annotation)도 DDD이니 동일하다"고 단정 금지. domain의 framework 격리 규칙을 두는 코드베이스에서는 양립 불가.
  • "functional domain modeling(Scala/F#) 도입했다"고 단정 금지(JVM Java 기준 코드베이스에서). 패러다임 학습 비용과 팀 적합성이 별도로 필요.

Sources

Privacy

File / Resource

Domain Modeling

Canonical