Files
llm-wiki/raw/interviews/clean-architecture-identifier-generation.md
T

54 lines
4.0 KiB
Markdown

---
title: interview-prep / clean-architecture-identifier-generation
source_type: interview-prep
status: raw
related_branches: [feature-resource-identifier-contract]
related_projects: [ca-skeleton]
tags: [interview-prep, ca-skeleton, identifier, ulid, ddd, clean-architecture, hexagonal]
created: 2026-06-01
status_label: collecting
---
# interview-prep: clean-architecture-identifier-generation
> Layer: `raw/interviews/` — 면접 질문 원본 수집·연구 노트. 다듬어진 답변은 `/interviewize` 후 `wiki/interview/` 에 별도 작성.
## Parent / 부모
- [[raw/branch-notes/feature-resource-identifier-contract]] — D5(도메인 port + application orchestration), D1(ULID), D10(PostgreSQL uuid native) 실 구현.
- [[raw/project-notes/ca-skeleton-operational-contract]] — ca-tmpl skeleton-wide operational contract.
## 질문 / Question
- 질문 원문: 도메인 엔티티의 식별자(ULID)를 인프라(랜덤/시계 소스)에 도메인을 결합시키지 않으면서 server-assigned로 생성하려면 Clean Architecture에서 어느 계층이 책임지나요?
- 출처: 예상 질문 (실 면접 아님).
- 받은 날짜·맥락: 아직 없음. DDD factory / hexagonal port 이해 검증용.
## 질문 의도 추론 / Why this question
- 핵심 평가 대상:
- "도메인이 식별성을 소유"한다는 DDD 명제와 "도메인은 SecureRandom/시계/라이브러리에 결합되면 안 된다"는 순수성 명제를 *동시에* 만족시키는 설계를 아는지.
- factory가 entity가 아니라 도메인 *service/port*라는 Evans DDD의 디테일 인지.
- "도메인 생성 vs application 생성 vs 인프라 생성(Hibernate @GeneratedValue)"의 trade-off를 맥락 의존으로 보는지.
- 함정 / 흔히 빠지는 답변:
- "도메인 entity의 static factory가 `UUID.randomUUID()`를 직접 호출" → 도메인이 JDK 난수에 결합 + 테스트 시 generator 교체 불가 + ULID 같은 라이브러리면 도메인이 인프라 의존.
- "Hibernate `@GeneratedValue`로 DB가 생성" → 도메인이 영속화 메커니즘에 결합, ULID time-ordered/monotonic 보장 불가, PostgreSQL `uuid` native 결정과 충돌.
- "application이 ULID 라이브러리를 직접 호출" → use case가 인프라(UlidCreator)에 결합, ArchUnit `no_uuid_random_in_controller` 위반.
- 따라올 만한 후속 질문:
- 그럼 도메인 port는 누가 호출하나요? (use case) 그건 "application이 생성"하는 것 아닌가요? (생성 *책임*은 도메인 port, *호출 시점*은 orchestration — 구분)
- ULID 26자(Crockford base32)를 DB에는 어떻게 저장하나요? (PostgreSQL `uuid` native 16-byte로 `Ulid.toUuid()` 변환 — external은 ULID, internal은 uuid)
- sealed로 모든 식별자 타입을 닫고 싶은데 모듈 경계 때문에 `permits`가 안 되면? (`no_long_id_pk` ArchUnit rule이 빌드타임 대체)
- resource id / trace id / idempotency-key는 왜 다른 branch가 책임지나요?
## 답변 재료 / Raw answer material
- 구현: 도메인에 `WorkLogIdFactory`(port) 정의 → 인프라 `UlidWorkLogIdFactory`(`@Component`, `UlidCreator.getMonotonicUlid()`, SecureRandom) 구현 → `CreateWorkLogUseCase`가 port를 주입받아 `factory.newId()` 호출 후 `WorkLog.create(id, ...)`로 조립.
- 도메인 `WorkLog``WorkLogId`(26자 regex 검증만 하는 record)만 알고, ULID 라이브러리/난수/시계에 결합 없음.
- "Application layer 생성 거부"라는 단순 표현은 오해를 부른다 — 실제 거부 대상은 *application이 ULID 라이브러리를 직접 호출*하는 것이지, use case가 도메인 port를 orchestrate하는 것은 정합.
- 검증: `WorkLogUseCasesTest`가 fake `WorkLogIdFactory`(테스트는 generator 교체 자유) 주입으로 단위테스트. ArchUnit `no_uuid_random_in_controller`/`no_math_random_for_id`/`no_long_id_pk`가 빌드타임 enforce.
## Related / 관련
- 관련 branch note: [[raw/branch-notes/feature-resource-identifier-contract]]
- 관련 개념: [[raw/blog-topics/identifier-governance-rule-scoping-by-id-kind-2026-06-01]]