Files
llm-wiki/raw/interviews/clean-architecture-boundary-enforcement.md
T

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
feature-architecture-enforcement-rules
ca-skeleton
interview-prep
ca-skeleton
architecture
testing
archunit
clean-architecture
gradle
2026-05-28 collecting

interview-prep: clean-architecture-boundary-enforcement

Layer: raw/interviews/ — 면접 질문 원본 수집·연구 노트. 다듬어진 답변은 /interviewizewiki/interview/ 에 별도 작성.

Parent / 부모

질문 / 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.md D2): ca-tmpl 의 module 구조는 domain-core + application-core + adapter-{web,persistence,outbound} + shared-contract + sample-ticket + app-bootstrap 8개. module boundary 가 1차 강제선, module 내부 package 가 2차 책임 분류.
  • 사실 2 (근거: feature-architecture-enforcement-rules.md D1 + 외부 governance-archunit-official.md#AU-OFF-C1): boundary 강제는 두 층 — Gradle verifyCleanArchitectureDependencies task 가 declared module coverage + allowed project dependency 매트릭스를 검사하고, ArchUnit CleanArchitectureTest 가 bytecode/import 수준의 12 rule 을 검사.
  • 사실 3 (근거: feature-architecture-enforcement-rules.md D3, 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.md Claims to Verify 의 status 표): 위 8개 rule 모두 actually-implemented 또는 locally-verified. red/green 검증 (임시 위반 코드 → 실패 → 제거 → 통과) 까지 수행. cd src && ./gradlew :app-bootstrap:test verifyCleanArchitectureDependenciescd src && ./gradlew test 모두 통과.
  • 사실 5 (근거: feature-architecture-enforcement-rules.md D8 + feature-application-port-usecase-contract.md D3): application 의 @Transactional 금지는 Spring 공식 권고와 충돌 하는 의도적 소수파 결정. 다수파 (@Transactional 직접 부착, hexagonal-reflectoring) 가 reasonable 함을 인정하면서, template repository 의 격리 학습 비용 흡수가 이유.
  • 내가 직접 한 경험:
    • ca-tmpl src/build.gradleverifyCleanArchitectureDependenciessrc/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/architecture/CleanArchitectureTest.java 두 파일을 함께 보강.
    • 임시 위반 코드 4종 (shared.ticket package, controller domain return, mapper → application 의존, application @Transactional, app-bootstrap → sample-ticket Gradle 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. 코드 문제와 환경 문제를 구분 한 경험.
  • 트레이드오프:
    • 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 최소) vs TransactionPort 추상화 (소수파, 격리 우선, boilerplate 증가). ca-tmpl 은 template repository 라서 소수파를 의도적 선택. 단일 DB / 단일 transactionManager 의 작은 팀은 다수파가 reasonable.
    • Spring Modulith 도입 안 함: named interface 검증은 더 강력하지만 ca-tmpl 의 boundary drift 차단 비용 대비 효용이 이 시점에서는 낮다고 판단. 후속 검토 후보로 둠 (feature-architecture-enforcement-rules.md D5 Open Risk).
  • 한계 / "이건 안 해봤다":
    • runtime lookup / reflection 우회 (ApplicationContext#getBean 류) 가 현재 ArchUnit rule 을 false-pass 하는지 실험 미수행 (planned).
    • MapStruct generated mapper exemption 의 build path 가 빌드 도구 설정에 따라 어떻게 달라지는지 확인 미완 (needs-confirmation, D9 UNSUPPORTED_DECISION).
    • prod 운영 검증 없음 — ca-tmpl 은 template repository.

Sources / 근거

미해결 / Unknown

  • 모르는 것: ArchUnit 이 reflection 우회를 얼마나 못 잡는지 정량 측정 안 함. Spring ApplicationContext#getBean 류의 일반적 우회 패턴을 위반 코드로 넣어 실제 false-pass 확인 필요.
  • 모르는 것: MapStruct generated mapper exemption 의 표준 처리 방식. Maven vs Gradle / annotation processor 위치에 따라 달라지는 generated source path 의 일반적 표현.
  • 확인 방법: feature-architecture-enforcement-rules.md Claims to Verify 의 planned / needs-confirmation 항목을 후속 PoC branch 에서 실험.

답변 경계 / Answer boundary

  • 자신 있게 말할 수 있는 범위: ca-tmpl src/build.gradleverifyCleanArchitectureDependenciessrc/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) 에서의 선택 까지만.