11 KiB
11 KiB
title, source_type, status, related_branches, related_projects, tags, created, status_label
| title | source_type | status | related_branches | related_projects | tags | created | status_label | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| interview-prep / clean-architecture-boundary-enforcement | interview-prep | raw |
|
|
|
2026-05-28 | collecting |
interview-prep: clean-architecture-boundary-enforcement
Layer:
raw/interviews/— 면접 질문 원본 수집·연구 노트. 다듬어진 답변은/interviewize후wiki/interview/에 별도 작성.
Parent / 부모
- raw/branch-notes/feature-architecture-enforcement-rules — Clean Architecture 경계를 Gradle + ArchUnit fitness function 으로 강제한 결정 (D1~D10) + 검증 결과.
- raw/project-notes/ca-skeleton-operational-contract — ca-tmpl skeleton 의 module boundary / operational contract SSOT.
질문 / Question
- 질문 원문: Clean Architecture 템플릿에서 계층 경계가 시간이 지나도 깨지지 않도록 어떤 방식으로 자동 검증했나요?
- 출처: 예상 질문 (실제 면접에서 받은 것 아님).
- 받은 날짜·맥락: 아직 없음.
질문 의도 추론 / Why this question
- 핵심 평가 대상:
- 아키텍처 원칙을 문서가 아니라 자동 검증으로 연결한 경험.
- Gradle multi-module dependency 와 ArchUnit bytecode rule 의 역할 분리 인식 (각자 잡는 위반 종류가 다름).
- 정적 분석의 한계 인식 (runtime reflection, generated code, Spring Modulith 등 보완 도구의 자리).
- 단순 "Clean Architecture 적용했다" 선언이 아니라 실제 위반 코드를 넣어 red/green 검증 한 경험.
- 함정 / 흔히 빠지는 답변 패턴:
- "Clean Architecture 적용했다" 로 끝내고 controller/repository/JPA entity leak 을 구체적으로 어떻게 막았는지 설명 못함.
- Gradle 과 ArchUnit 의 역할 차이 를 묻지 않고 "둘 다 썼다" 로 뭉뚱그림.
- 한계 (reflection, MapStruct generated path, Spring Modulith 도입 안 함) 를 솔직히 말하지 않고 만능처럼 표현.
- 따라올 만한 후속 질문:
- Gradle dependency rule 과 ArchUnit rule 은 각각 어떤 위반 을 잡나요? 한쪽만으로는 왜 안 되나요?
- ArchUnit 이 잡지 못하는 위반은 무엇이고 어떻게 보완할 건가요?
- sample module 이 production code 로 역수입되는 걸 어떻게 막았나요?
- 빈 anchor module 은 ArchUnit 에서 어떻게 처리했나요?
- Spring Modulith 를 도입하지 않은 이유는 무엇이고, 추후 도입한다면 무엇이 중복 되고 무엇이 보완 인가요?
답변 재료 / Raw answer material
사실은 branch-note Decision ID 또는 외부 source claim ID 로 근거 같이 인용. 경험은 내가 직접 한 것 만.
- 사실 1 (근거:
feature-architecture-enforcement-rules.mdD2): ca-tmpl 의 module 구조는domain-core+application-core+adapter-{web,persistence,outbound}+shared-contract+sample-ticket+app-bootstrap8개. module boundary 가 1차 강제선, module 내부 package 가 2차 책임 분류. - 사실 2 (근거:
feature-architecture-enforcement-rules.mdD1 + 외부governance-archunit-official.md#AU-OFF-C1): boundary 강제는 두 층 — GradleverifyCleanArchitectureDependenciestask 가 declared module coverage + allowed project dependency 매트릭스를 검사하고, ArchUnitCleanArchitectureTest가 bytecode/import 수준의 12 rule 을 검사. - 사실 3 (근거:
feature-architecture-enforcement-rules.mdD3, D4, D5, D6, D7, D8): ArchUnit 이 잡는 위반 — domain purity (Spring/JPA/HTTP import 금지), application → adapter/bootstrap 의존 금지, adapter 간 직접 의존 금지, web DTO boundary, sample-ticket production 역수입 금지, application@Transactional직접 import 금지, controller direct domain response 금지, mapper boundary, shared-contract package allowlist. - 사실 4 (근거:
feature-architecture-enforcement-rules.mdClaims to Verify 의 status 표): 위 8개 rule 모두actually-implemented또는locally-verified. red/green 검증 (임시 위반 코드 → 실패 → 제거 → 통과) 까지 수행.cd src && ./gradlew :app-bootstrap:test verifyCleanArchitectureDependencies와cd src && ./gradlew test모두 통과. - 사실 5 (근거:
feature-architecture-enforcement-rules.mdD8 +feature-application-port-usecase-contract.mdD3): application 의@Transactional금지는 Spring 공식 권고와 충돌 하는 의도적 소수파 결정. 다수파 (@Transactional직접 부착, hexagonal-reflectoring) 가 reasonable 함을 인정하면서, template repository 의 격리 학습 비용 흡수가 이유. - 내가 직접 한 경험:
- ca-tmpl
src/build.gradle의verifyCleanArchitectureDependencies와src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/architecture/CleanArchitectureTest.java두 파일을 함께 보강. - 임시 위반 코드 4종 (
shared.ticketpackage, controller domain return, mapper → application 의존, application@Transactional,app-bootstrap → sample-ticketGradle dep) 추가 → 실패 확인 → 제거 → 통과. - 빈 skeleton anchor module 의 ArchUnit empty-should failure 를
allowEmptyShould(true)로 선별 해결 (모든 rule 에 일괄 적용 ≠ 빈 상태가 의도된 rule 에만 적용) — raw/errors/archunit-empty-should-anchor-2026-05-27. - Codex sandbox 의 read-only
~/.gradle권한 때문에 Gradle wrapper lock 실패 → 사용자 승인 escalation 으로 재실행 — raw/errors/gradle-wrapper-readonly-cache-2026-05-28. 코드 문제와 환경 문제를 구분 한 경험.
- ca-tmpl
- 트레이드오프:
- Gradle vs ArchUnit 분업: Gradle 은 module-level project dependency 를 컴파일 단계에서 확실히 차단하지만 method return type 이나 annotation import 같은 세부 규칙은 못 봄. ArchUnit 은 bytecode 수준의 import / class structure 를 잡지만 module 간 build-graph 사이클 은 깔끔하게 못 잡음. 둘이 역할이 다르고 둘 다 필요.
- 다수파 vs 소수파:
@Transactional직접 부착 (다수파, Spring 공식 권고, boilerplate 최소) vsTransactionPort추상화 (소수파, 격리 우선, boilerplate 증가). ca-tmpl 은 template repository 라서 소수파를 의도적 선택. 단일 DB / 단일 transactionManager 의 작은 팀은 다수파가 reasonable. - Spring Modulith 도입 안 함: named interface 검증은 더 강력하지만 ca-tmpl 의 boundary drift 차단 비용 대비 효용이 이 시점에서는 낮다고 판단. 후속 검토 후보로 둠 (
feature-architecture-enforcement-rules.mdD5 Open Risk).
- 한계 / "이건 안 해봤다":
- runtime lookup / reflection 우회 (
ApplicationContext#getBean류) 가 현재 ArchUnit rule 을 false-pass 하는지 실험 미수행 (planned). - MapStruct generated mapper exemption 의 build path 가 빌드 도구 설정에 따라 어떻게 달라지는지 확인 미완 (
needs-confirmation, D9UNSUPPORTED_DECISION). - prod 운영 검증 없음 — ca-tmpl 은 template repository.
- runtime lookup / reflection 우회 (
Sources / 근거
- raw/branch-notes/feature-architecture-enforcement-rules — 결정 D1~D10, Claims to Verify status 표, Closure 의
locally-verified5항목. - raw/branch-notes/feature-skeleton-package-blueprint-contract — 자매 결정 (D1~D8). module 분리 자체의 왜.
- raw/branch-notes/feature-application-port-usecase-contract —
@Transactional다수파 vs 소수파 trade-off 의 근거 (D3, D4 비교). - raw/official-docs/archunit-user-guide — ArchUnit rule DSL (
ARCHUNIT-UG-C5,ARCHUNIT-UG-C6). - raw/official-docs/governance-archunit-official — architecture test 거버넌스 (
AU-OFF-C1,AU-OFF-C2). - raw/official-docs/archunit-conditional-on-property-3-layer-pattern — predicate/condition 모델 (
AUCP-C1~AUCP-C5). - raw/company-tech-blogs/woowahan-hexagonal-multimodule — Domain / Application / Framework / Bootstrap 4-module 격리 (
WW-HEX-C1). - raw/company-tech-blogs/modulith-kakaobank-techblog-2025 — Gradle multi-module + Hexagonal + Spring Modulith (
KAKAOBANK-MOD-C4). - wiki/concepts/clean-architecture-package-layout — 정제된 layout 개념 (canonical).
- wiki/projects/ca-tmpl/clean-architecture-package-layout — ca-tmpl 적용 (canonical, 갱신 필요).
미해결 / Unknown
- 모르는 것: ArchUnit 이 reflection 우회를 얼마나 못 잡는지 정량 측정 안 함. Spring
ApplicationContext#getBean류의 일반적 우회 패턴을 위반 코드로 넣어 실제 false-pass 확인 필요. - 모르는 것: MapStruct generated mapper exemption 의 표준 처리 방식. Maven vs Gradle / annotation processor 위치에 따라 달라지는 generated source path 의 일반적 표현.
- 확인 방법:
feature-architecture-enforcement-rules.mdClaims to Verify 의planned/needs-confirmation항목을 후속 PoC branch 에서 실험.
답변 경계 / Answer boundary
- 자신 있게 말할 수 있는 범위: ca-tmpl
src/build.gradle의verifyCleanArchitectureDependencies와src/app-bootstrap/.../CleanArchitectureTest.java의 12 ArchUnit rule 을 직접 구현 + red/green 검증 한 범위../gradlew test+verifyCleanArchitectureDependencies로컬 통과까지. - "이 부분은 공식 문서를 다시 보고 답변드리겠습니다" 라고 해야 하는 부분:
- MapStruct generated code exemption 의 빌드 도구별 표준 처리.
- Spring Modulith named interface 의 구체 configuration (Modulith 를 도입한 적 없음).
- prod 환경에서 ArchUnit / Gradle dependency rule 이 CI 어떤 단계에서 실패시키는 게 안전한지 (운영 경험 없음).
- 절대 과장하지 말 것:
- prod 운영 검증인 것처럼 말하지 말 것. ca-tmpl 은 template repository 이고 검증 등급은
locally-verified. - 우아한형제들 / 카카오뱅크 사례를 industry standard 처럼 말하지 말 것. case study 다 (
Evidence Strength: company-case-study). @Transactional소수파 결정이 다수파보다 우월하다 는 식의 표현 금지. 이 맥락 (template repository) 에서의 선택 까지만.
- prod 운영 검증인 것처럼 말하지 말 것. ca-tmpl 은 template repository 이고 검증 등급은
Related / 관련
- 관련 면접 질문 (선행/후속): raw/interviews/clean-architecture-module-blueprint (선행 — module 분리 자체의 왜), raw/interviews/shared-contract-and-sample-isolation (자매 — shared/sample 책임), raw/interviews/transaction-port-vs-spring-transactional (자매 —
@Transactional다수파/소수파 trade-off), raw/interviews/post-implementation-knowledge-capture (워크플로우 자매). - 영감을 받은 채용공고: (없음).
- 관련 블로그 글감: raw/blog-topics/clean-architecture-boundary-enforcement-2026-05-28 (같은 경험의 글감), raw/blog-topics/clean-architecture-module-blueprint-2026-05-28 (자매 글감), raw/blog-topics/transaction-port-abstraction-over-spring-transactional-2026-05-28 (
@Transactionaltrade-off 글감). - 답변 derive 후 위치: 생성 전. 생성 시
wiki/interview/architecture/clean-architecture-boundary-enforcement.md후보.