10 KiB
10 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-module-blueprint | interview-prep | raw |
|
|
|
2026-05-28 | collecting |
interview-prep: clean-architecture-module-blueprint
Layer:
raw/interviews/— 면접 질문 원본 수집·연구 노트. 다듬어진 답변은/interviewize후wiki/interview/에 별도 작성.
Parent / 부모
- raw/branch-notes/feature-skeleton-package-blueprint-contract — single-module feature-first 결정 (2026-05-22) 을 Gradle multi-module + Hexagonal (2026-05-27) 로 명시적으로 수정 한 결정 (D1~D8 + Default Module Blueprint tree + Module Dependency Rule 표).
- raw/project-notes/ca-skeleton-operational-contract — ca-tmpl skeleton-wide operational contract SSOT.
질문 / Question
- 질문 원문: Clean Architecture 템플릿에서 왜 단일 모듈 package 구조가 아니라 Gradle multi-module 구조를 선택했나요? 그리고 처음부터 그렇게 결정한 건가요?
- 출처: 예상 질문.
- 받은 날짜·맥락: 아직 실제 면접 질문으로 받은 것은 아님.
질문 의도 추론 / Why this question
- 핵심 평가 대상:
- Clean Architecture 원칙을 물리적 module boundary 로 옮긴 왜.
- package convention 과 build-graph enforcement 의 차이 인식.
- small project vs template repository 의 trade-off 인식.
- 첫 결정을 뒤집은 경험 (case study 검토 후 의사결정 reversion) — 정직함과 evidence-based 사고.
- 함정 / 흔히 빠지는 답변 패턴:
- "멀티모듈이 더 깔끔해서" — 비용 / 단점 / trade-off 언급 없음.
- "처음부터 멀티모듈이 답이라고 생각했다" — 의사결정의 과정 을 숨김.
- 우아한형제들 / 카카오뱅크 사례를 industry standard 처럼 인용 (실제로는 case study).
- 따라올 만한 후속 질문:
- small project 에서는 single-module 이 더 낫지 않나요? 어떤 기준으로 multi-module 을 선택해야 하나요?
- Gradle dependency rule 과 ArchUnit rule 은 각각 무엇을 보장 하나요? 한쪽만으로는 왜 안 되나요?
domain-core가shared-contract를 참조하는 건 Clean Architecture 위반 아닌가요?- Spring Modulith 가 multi-module 대체가 될 수 있나요?
- 새 사업 도메인이 추가되면 어느 module 에 어떻게 들어가나요?
adapter-messaging같은 새 adapter 가 필요해지면?
답변 재료 / Raw answer material
- 사실 1 (근거:
feature-skeleton-package-blueprint-contract.mdD1, §결정 사항 2026-05-22 / 2026-05-27): 초기 결정은 single-module feature-first package layout 이었다. 2026-05-27 에 우아한형제들 / 카카오뱅크 사례 검토 후 Gradle multi-module + Clean Architecture / Hexagonal 로 명시적으로 수정. 의사결정의 reversion 자체가 evidence. - 사실 2 (근거:
feature-skeleton-package-blueprint-contract.md§Default Module Blueprint + Module Dependency Rule 표): ca-tmpl 의 8 module —app-bootstrap,domain-core,application-core,adapter-web,adapter-persistence,adapter-outbound,shared-contract,sample-ticket. dependency direction 매트릭스로 허용/금지 가 매 module 별로 명시. - 사실 3 (근거:
feature-skeleton-package-blueprint-contract.mdD2, D3):domain-core는 framework-neutral POJO (Spring/JPA/HTTP 모름),application-core는domain-core+shared-contract에만 의존. adapter 구현체는 adapter module 밖으로 안 새어 나옴. - 사실 4 (근거:
feature-skeleton-package-blueprint-contract.mdD6):shared-contract는 response envelope / error code / header / MDC / metric / registry / annotation 같은 skeleton-wide operational contract 만. business / domain concept 는 금지. - 사실 5 (근거:
feature-skeleton-package-blueprint-contract.mdD7 +feature-architecture-enforcement-rules.mdD7):sample-ticket은 fixture/sample consumer 이며 production module 이 import / dependency 선언 시 Gradle + ArchUnit 양쪽 에서 실패. - 사실 6 (근거:
feature-skeleton-package-blueprint-contract.mdClosure §locally-verified):./gradlew verifyCleanArchitectureDependencies+./gradlew :app-bootstrap:test --tests '*CleanArchitectureTest'+./gradlew :adapter-web:test --tests '*SettingsTest'+./gradlew test모두 통과. 로컬 검증 완료. - 내가 직접 한 경험:
- 기존 reference code (blog domain) 를 production module 에서
sample-ticket/src/main/java/dev/caskeleton/sample/ticket/...로 격리. production module 은 anchor +package-info.java중심으로 정리. - production package root
dev.caskeleton으로 rename +BlogApplication→CaSkeletonApplication+blog.*설정 prefix →ca-skeleton.*. - 빈 anchor module 의 ArchUnit empty-should failure 를
allowEmptyShould(true)로 선별 해결 — raw/errors/archunit-empty-should-anchor-2026-05-27. - sample-ticket 격리 후
InvalidBearerTokenExceptioncompile error →spring-boot-starter-oauth2-resource-server명시 추가 — raw/errors/sample-ticket-oauth2-resource-server-dependency-2026-05-27.
- 기존 reference code (blog domain) 를 production module 에서
- 트레이드오프:
- single-module 의 장점: build 설정 단순, IDE 탐색 빠름, 처음 학습 비용 낮음. 작은 프로젝트 에는 합리적.
- multi-module 의 장점: module boundary 가 컴파일 단계 에서 위반을 차단. template 의 재사용성 (다음 프로젝트에서 import 해도 경계가 살아 있음).
- ca-tmpl 이 multi-module 을 택한 이유: template repository 라서 새 프로젝트 시작 시점에 경계가 흐트러지지 않도록 학습 비용을 미리 흡수 —
feature-skeleton-package-blueprint-contract.mdD8 Open Risk 와 일치. - case study 의 한계: 우아한형제들 / 카카오뱅크 사례는
company-case-study등급. 공식 표준이 아님. ca-tmpl 채택의 부분 정당화 까지만.
- 한계 / "이건 안 해봤다":
- Spring Modulith named interface 검증은 기본값으로 도입하지 않음 (
feature-skeleton-package-blueprint-contract.mdD5 Open Risk). - 실제 사업 도메인 (e.g., 결제 / 알림 / 인증) 이 들어왔을 때 module 분할 / 새 adapter 추가가 자연스러운지 검증 안 함.
- 운영 배포 검증 없음 —
feature-skeleton-package-blueprint-contract.mdClosure §prod-verified: 없음.
- Spring Modulith named interface 검증은 기본값으로 도입하지 않음 (
Sources / 근거
- raw/branch-notes/feature-skeleton-package-blueprint-contract — D1~D8, Default Module Blueprint, Module Dependency Rule.
- raw/branch-notes/feature-architecture-enforcement-rules — 자매 결정 (boundary 강제). 본 module 분리의 자동 검증 메커니즘.
- raw/branch-notes/feature-application-port-usecase-contract —
application-core내부 패키지 구조의 후속 (D1:*UseCase/*Portnaming). canonical 정제 시 통합. - 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 + Modulith 사례 (
KAKAOBANK-MOD-C4). - raw/official-docs/hexagonal-cockburn-wikipedia-summary — Ports & Adapters 원형 (
HEX-WIKI-C5). - raw/official-docs/arch-clean-architecture-uncle-bob — Dependency Rule 의 클래식 근거.
- raw/official-docs/layer-first-baeldung-clean-architecture-spring-boot — 대안 1: layer-first 입문형 사례.
- wiki/concepts/clean-architecture-package-layout — Clean Architecture package/module layout 개념.
- wiki/projects/ca-tmpl/clean-architecture-package-layout — ca-tmpl 적용 (canonical, 갱신 필요).
미해결 / Unknown
- 모르는 것: Spring Modulith 를 후속 도입했을 때 Gradle multi-module + ArchUnit 과의 중복/대체 관계.
- 모르는 것: 실제 사업 도메인 추가 시 module 분할 패턴 (e.g., 결제 추가 시
domain-core가 결제 / 사용자 / 주문 등 sub-package 로 비대해지는 시점은 어디인가). - 확인 방법:
feature-application-port-usecase-contract,feature-domain-event-outbox-contract,feature-business-rule-validation-contract후속 branch 적용 결과 관찰.
답변 경계 / Answer boundary
- 자신 있게 말할 수 있는 범위:
- ca-tmpl 에서 module rename / package anchor / Gradle dependency verifier / ArchUnit rule / full local test 까지 직접 수행 한 범위.
- 초기 single-module 결정을 multi-module 로 뒤집은 의사결정 과정 과 근거 (case study 검토).
domain-core/application-core/adapter-{web,persistence,outbound}/shared-contract/sample-ticket/app-bootstrap의 책임과 forbidden import.
- "이 부분은 공식 문서를 다시 보고 답변드리겠습니다" 라고 해야 하는 부분:
- Spring Modulith named interface 의 구체 configuration (도입한 적 없음).
- 회사별 shared kernel / common module 운영 표준 (ca-tmpl 의 결정은 이 맥락 까지만).
- module 수 (4 vs 8 vs 12) 의 최적값 (case study 가 사례별로 다름).
- 절대 과장하지 말 것:
- 운영 배포 경험인 것처럼 말하지 말 것. ca-tmpl 은 template repository 이고 검증 등급은
locally-verified. - 우아한형제들 / 카카오뱅크 사례를 업계 표준 처럼 표현 금지 — 둘 다 case study (
company-case-study등급). - "처음부터 multi-module 이 답이라고 알았다" 식의 표현 금지 — 결정의 reversion 사실을 숨기지 않음.
- 운영 배포 경험인 것처럼 말하지 말 것. ca-tmpl 은 template repository 이고 검증 등급은
Related / 관련
- 관련 면접 질문 (선행/후속): raw/interviews/shared-contract-and-sample-isolation (자매 — shared/sample 책임), raw/interviews/clean-architecture-boundary-enforcement (후속 — 자동 검증), raw/interviews/transaction-port-vs-spring-transactional (자매 — application 의 framework 격리).
- 영감을 받은 채용공고: (없음).
- 관련 블로그 글감: raw/blog-topics/clean-architecture-module-blueprint-2026-05-28 (같은 경험의 글감), raw/blog-topics/clean-architecture-boundary-enforcement-2026-05-28.
- 답변 derive 후 위치: 생성 전. 생성 시
wiki/interview/architecture/clean-architecture-module-blueprint.md후보.