Files
llm-wiki/vault/40-publish/topics-interview/clean-architecture.md
T

33 KiB

title, source_type, status, confidence, tags, related_projects, last_reviewed
title source_type status confidence tags related_projects last_reviewed
클린 아키텍처 — 개념·구조·장단점과 실무(대기업) 변형 비교 interview draft medium
clean-architecture
hexagonal
package-layout
backend
ca-skeleton
2026-07-04

클린 아키텍처 — 개념·구조·장단점과 실무(대기업) 변형 비교

이 문서의 성격 (먼저 읽어 주세요)

  • 목적: 면접·개인 이해용으로 클린 아키텍처(Clean Architecture)의 개념/구조/장단점과, 실무·대기업에서 만든 변형이 원전과 무엇이 다른지를 한 곳에 정리한 토픽 스터디 노트입니다.
  • 근거 등급 주의: 아래 사실은 대부분 개인 저술(engineering-blog) 또는 회사 기술블로그 사례(company-case-study) 에서 나온 것입니다. Uncle Bob·Cockburn 글조차 표준 기구 문서가 아니라 개인 블로그이며, 이 문서에서 유일한 공식 벤더 문서(official-vendor-doc)는 Microsoft의 ACL 패턴뿐입니다. 따라서 "공식 표준", "업계 best practice"라는 표현은 함부로 붙이지 않습니다. (CLAUDE.md §5)
  • 파이프라인 주의: 이 파일은 CLAUDE.md 표준 디렉토리(wiki/concepts/·wiki/interview/ 등)가 아닌 wiki/topics-interview/에 사용자 요청으로 만든 노트입니다. 정식 면접 산출물이 필요하면 §9 "다음 단계"의 canonical 경유 절차를 따르세요.

0. 30초 요약 (쉬운 설명 먼저)

  • 클린 아키텍처의 핵심은 딱 한 문장입니다. "의존성(import·참조)은 바깥에서 안쪽으로만 흐르고, 안쪽(비즈니스 규칙)은 바깥(DB·웹 프레임워크)의 존재를 몰라야 한다." 이걸 Dependency Rule(의존성 규칙)이라고 부릅니다.
  • 구조는 양파 같은 4개의 동심원입니다. 안쪽부터 Entities → Use Cases → Interface Adapters → Frameworks & Drivers. 안쪽일수록 순수한 비즈니스 규칙, 바깥일수록 기술 세부사항입니다.
  • 장점은 "도메인(핵심 업무 로직)을 DB·웹·프레임워크로부터 분리해서, 테스트하기 쉽고 기술 교체가 쉬워진다"는 것입니다.
  • 단점은 "코드가 늘고(모델 간 매핑, 포트 인터페이스 폭증), 초기 학습·설계 비용이 크다"는 것입니다. 다만 이 단점을 수치로 증명한 원전 자료는 거의 없습니다.
  • 대기업 변형(우아한형제들·Allegro 등)은 대부분 클린 아키텍처 그 자체가 아니라 사촌 격인 Hexagonal / Onion을 자기 방식으로 구현한 것입니다. 이 둘을 뭉뚱그려 "클린 아키텍처 대기업 사례"라고 말하면 과장입니다.

🖼 그림으로 보는 진화 — Layered → Hexagonal → Clean

개념을 텍스트로 읽기 전에, 그림 3장으로 "왜 이런 게 나왔는가"의 흐름을 먼저 잡습니다. (렌더링용 SVG는 raw/diagrams/clean-architecture-topic/*.svg, 편집용 원본은 같은 폴더의 .drawio)

(1) 출발점 — 전통적 Layered, 그리고 그 문제

!architecture-layered-2026-07-04.svg

전통적 계층형 구조는 위에서 아래로만 의존합니다: Presentation → Business → Data Access → DB. 겉보기엔 깔끔하지만 의존성의 종착지가 DB라는 게 문제입니다.

  • 비즈니스 규칙(Business)이 아래의 기술(Data Access·DB)에 의존하므로, DB나 ORM을 바꾸면 도메인 로직까지 영향을 받습니다.
  • 도메인을 테스트하려면 DB가 필요해 테스트가 느리고 깨지기 쉽습니다.
  • controller/service/repository로 자르면(package-by-layer) 한 도메인 코드가 세 폴더로 흩어져 응집도가 떨어집니다. (근거: raw/company-tech-blogs/feature-first-sahibinden-package-by-layer-vs-feature)

(2) 해결 — Hexagonal (Ports & Adapters): 의존성을 뒤집는다

!architecture-hexagonal-2026-07-04.svg

Hexagonal은 이 문제를 의존성 역전(DIP) 으로 해결합니다. 도메인(Application Core)을 한가운데 두고, DB·web을 전부 바깥의 adapter로 밀어냅니다.

  • core는 port(interface)만 정의하고, 실제 구현(web/DB adapter)이 그 port에 의존합니다. 즉 그림에서 화살표가 전부 안쪽(core)을 향합니다.
  • 그래서 core는 web·DB의 존재를 모릅니다 → DB·web 교체가 자유롭고, 실제 장비 없이 격리 테스트가 가능합니다.

    "developed and tested in isolation from its eventual run-time devices and databases" — 출처: raw/official-docs/arch-hexagonal-cockburn

(3) Clean Architecture — 같은 규칙, 4개의 링으로

!architecture-clean-concentric-2026-07-04.svg

클린 아키텍처는 Hexagonal과 규칙이 같습니다(의존성은 안쪽으로만). 다만 안쪽을 4개의 동심원으로 더 세분화합니다: Entities → Use Cases → Interface Adapters → Frameworks & Drivers. 핵심은 여전히 The Dependency Rule 하나입니다.

"source code dependencies can only point inwards" — 출처: raw/official-docs/arch-clean-architecture-uncle-bob

(4) 그래서 새로 생기는 문제 (Clean / Hexagonal 공통)

문제를 해결하면 새 비용이 따라옵니다. 이게 §4에서 자세히 다룰 단점의 요지입니다.

  • 모델 매핑 비용 — 도메인 모델 ↔ JPA 모델을 분리하니 변환 코드가 늘어납니다.

    "...with the cost of having to do mapping between the models" — 출처: raw/company-tech-blogs/arhohuttunen-hexagonal-architecture-spring-boot

  • 인터페이스(port) 폭증 — 외부 연계를 전부 port로 두다 보면 outputPort가 대량 생성됩니다. (출처: raw/company-tech-blogs/hexagonal-woowahan-techblog-2023)
  • 보일러플레이트·학습 곡선 — 구조가 늘어 초기 진입이 어렵습니다. (단, 정량 수치는 조사된 자료에 없음)
  • 레이아웃만으로는 규칙이 안 지켜짐 — ArchUnit·빌드 그래프 검사 같은 강제 수단이 없으면 경계가 새어 나갑니다. (출처: wiki/concepts/clean-architecture-package-layout)
  • 트랜잭션 경계 모호 — 구조를 나눠도 @Transactional을 어디 둘지는 별도 결정이 필요합니다(§5.5).

1. 클린 아키텍처란 무엇인가 (개념)

1.1 한 줄 정의와 핵심 규칙

클린 아키텍처는 Robert C. Martin(Uncle Bob)이 2012년 블로그 글 "The Clean Architecture"에서 정리한 아키텍처 스타일입니다. 핵심은 Dependency Rule 하나입니다.

원문: "source code dependencies can only point inwards" — 소스 코드 의존성은 오직 안쪽으로만 향할 수 있다. 원문: "Nothing in an inner circle can know anything at all about something in an outer circle" — 안쪽 원의 어떤 것도 바깥쪽 원의 존재(이름·타입·함수)를 전혀 알아서는 안 된다.

출처: raw/official-docs/arch-clean-architecture-uncle-bob (engineering-blog)

즉 "무엇이 무엇을 참조해도 되는가"의 방향만 규정하는 원칙입니다. 어떤 레이어가 안쪽인지는 이 한 문장이 정해 주지 않습니다(원전 스스로 명시).

1.2 개념적 뿌리 — 사실상 같은 가족

클린 아키텍처는 홀로 나온 게 아니라 그 이전 아키텍처들의 재정리·통합에 가깝습니다. 면접에서 이 가족 관계를 아는지 자주 묻습니다.

  • Hexagonal Architecture (Ports & Adapters, Alistair Cockburn, 2005): "왼쪽/오른쪽"이 아니라 inside(애플리케이션 코어) / outside(모든 외부) 의 비대칭 하나로 시스템을 가른다는 발상. 클린 아키텍처의 직접적 뿌리입니다.
  • Onion Architecture (Jeffrey Palermo, 2008): 의존성이 외부(infra/UI)에서 내부(domain model)로만 향하는 동심원 모델. 규칙은 Hexagonal과 동등. 출처: wiki/concepts/clean-architecture-package-layout (canonical)
  • Screaming Architecture (Uncle Bob, 2011): "아키텍처는 framework가 아니라 시스템(도메인)을 외쳐야 한다"는 자매 원칙. 최상위 패키지가 controller/service/repository가 아니라 업무 영역이어야 한다는 주장.
  • Anti-Corruption Layer (ACL, Microsoft / DDD Eric Evans 기원): 서로 다른 의미체계(semantics)를 가진 두 시스템 사이의 번역 계층. 클린 아키텍처의 경계 개념이 시스템 간 통합으로 확장된 형태.
    • 원문: "Implement a façade or adapter layer between different subsystems that don't share the same semantics. ... This pattern was first described by Eric Evans in Domain-Driven Design." — 출처: raw/official-docs/arch-acl-microsoft-pattern (이 문서에서 유일한 공식 벤더 문서)

용어 한 줄 풀이

  • port: 애플리케이션 코어가 외부와 대화하는 "계약점"(인터페이스). OS의 포트 비유에서 따온 이름입니다.
  • adapter: 그 port를 실제 기술(DB·HTTP 등)에 연결하는 양방향 변환기.
  • POJO: Plain Old Java Object. 프레임워크 애노테이션 없는 순수 자바 객체.

2. 구조 (4개 동심원)

클린 아키텍처의 대표 그림은 4개의 동심원입니다. 안쪽부터:

원 (안→밖) 이름 무엇을 담나 원문 근거
1 (가장 안) Entities 엔터프라이즈 전역(most general) 비즈니스 규칙 "Entities encapsulate Enterprise wide business rules"
2 Use Cases 애플리케이션 특화 규칙 + 모든 유스케이스 구현 "application specific business rules. It encapsulates and implements all of the use cases"
3 Interface Adapters 유스케이스·엔티티에 편한 포맷 ↔ 외부(DB·웹) 포맷 변환 "set of adapters that convert data from the format most convenient for the use cases and entities"
4 (가장 밖) Frameworks & Drivers DB, 웹 프레임워크 등 기술 세부사항 "outermost layer is generally composed of frameworks and tools such as the Database, the Web Framework"

출처: raw/official-docs/arch-clean-architecture-uncle-bob

2.1 경계를 어떻게 넘는가 — 의존성 역전(DIP)

제어 흐름(호출 방향)은 바깥→안으로 들어가지만, 소스 코드 의존성은 그 반대여야 합니다. 이 모순을 인터페이스와 상속으로 뒤집는 것이 DIP(Dependency Inversion Principle, 의존성 역전 원칙) 입니다.

원문: "we would arrange interfaces and inheritance relationships such that the source code dependencies oppose the flow of control" — 출처: raw/official-docs/arch-clean-architecture-uncle-bob

주의: 원전은 "인터페이스로 방향을 뒤집는다"는 원칙만 말하고, 구체적으로 DI 컨테이너를 쓸지 factory를 쓸지 등 메커니즘은 지정하지 않습니다. 그건 프로젝트별 결정입니다.

2.2 경계를 넘는 데이터의 형태

원문: "isolated, simple, data structures are passed across the boundaries" — 경계를 넘을 때는 고립된, 단순한 데이터 구조를 전달한다. 출처: raw/official-docs/arch-clean-architecture-uncle-bob

여기서 "ORM 엔티티를 그대로 넘기면 안 된다"는 강한 규칙까지 원전이 못 박은 것은 아닙니다(원전 스스로 그 일반화의 한계를 인정). 실무에서 DTO(Data Transfer Object)로 넘기는 관행은 원칙의 해석입니다.

2.3 Hexagonal과의 구조 차이 (면접 포인트)

  • 클린 아키텍처: 4개 동심원으로 더 세분화.
  • Hexagonal: inside/outside 이분법 + ports 로 더 추상화. 육각형은 6이 중요해서가 아니라 "포트/어댑터를 그려 넣을 자리를 확보하려는 그림"일 뿐입니다.
    • 원문: "The hexagon is not a hexagon because the number six is important, but rather to allow the people doing the drawing to have room to insert ports and adapters as they need" — 출처: raw/official-docs/arch-hexagonal-cockburn
  • 이 둘의 정확한 1:1 매핑은 원전들이 서로 직접 비교한 게 아니라 후대의 종합입니다 (INFERENCE).

3. 클린 아키텍처의 장점

모두 원전이 직접 주장하거나(인용 있음) 널리 쓰이는 reference가 제시하는 이점입니다.

  1. 테스트 격리성 — 실제 DB·웹서버 없이 도메인/유스케이스를 격리해서 테스트할 수 있습니다. Cockburn이 가장 명시적으로 내세운 장점입니다.

    "Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases." — 출처: raw/official-docs/arch-hexagonal-cockburn

  2. 도메인의 기술 독립성 — 도메인 코드가 DB나 웹 관심사에 의존하지 않게 만듭니다.

    "Develop your domain code independent of database or web concerns." / "Free your domain layer of oppressive dependencies using dependency inversion." — 출처: raw/official-docs/hexagonal-thombergs-buckpal-github

  3. 환경 결정의 지연 — 프레임워크·DB·웹서버 선택을 초기에 확정하지 않아도 됩니다.

    "A good software architecture allows decisions about frameworks, databases, web-servers...to be deferred and delayed." — 출처: raw/official-docs/feature-first-uncle-bob-screaming-architecture-2011

  4. 낮은 결합도 — 경계 간 전달이 단순 데이터 구조로 제한되어 레이어 간 결합이 낮아집니다(§2.2).
  5. 도메인 가독성 — 최상위 구조만 봐도 "이 시스템이 무슨 업무를 하는지" 드러납니다(Screaming Architecture).

4. 클린 아키텍처의 단점 / 한계

정직한 경고: "장점"은 원전 근거가 풍부하지만, "단점"을 원전이 직접·정량적으로 인정한 근거는 매우 희박합니다. 아래 중 원문이 직접 인정한 비용은 ACL의 latency 하나뿐이고, 나머지는 실무 사례(blog)나 합리적 추론(INFERENCE)입니다. 면접에서 이 구분을 지키는 것 자체가 신뢰도를 높입니다.

  1. 모델 간 매핑 비용 — 도메인 모델과 영속성(JPA) 모델을 분리하면 그 사이를 변환하는 코드가 늘어납니다. (저자 직접 인정)

    "Here we have a clean separation of those concerns with the cost of having to do mapping between the models." — 출처: raw/company-tech-blogs/arhohuttunen-hexagonal-architecture-spring-boot

  2. 인터페이스(port) 폭증 — 외부 연계를 전부 인터페이스로 두다 보면 outputPort가 대량으로 생깁니다. (실무 사례가 자인)

    "수많은 outputPort 인터페이스들이 생겨나게 되었습니다." — 출처: raw/company-tech-blogs/hexagonal-woowahan-techblog-2023

  3. ACL의 지연(latency) — 번역 계층을 두면 두 시스템 간 호출에 지연이 더해질 수 있습니다. (이 문서에서 유일하게 공식 벤더 문서가 직접 인정한 단점)

    "The anti-corruption layer might add latency to calls made between the two systems." — 출처: raw/official-docs/arch-acl-microsoft-pattern

  4. 원칙 선언 ↔ 실행 가이드의 간극 — Screaming Architecture 같은 원전은 철학 선언 수준이라, 실제로 패키지를 어떻게 자를지의 구체적 가이드는 부족합니다. (INFERENCE — raw 문서 작성자 해석)
  5. 레이아웃만으로는 경계가 안 지켜짐 — 어떤 레이아웃을 골라도 규칙 위반은 자연히 새어 나갑니다. 별도의 강제 수단(빌드 그래프 검사, ArchUnit 같은 정적 분석 fitness function)이 있어야 build 시점에 막을 수 있습니다. 그마저도 runtime lookup·reflection 우회는 못 잡습니다. 출처: wiki/concepts/clean-architecture-package-layout (canonical §경계를 강제하는 방법)
  6. 정량 비용은 근거 부재 — 보일러플레이트 증가율, 개발 속도 저하 %, 팀 규모별 손익분기점 같은 수치는 조사된 어떤 자료에도 없습니다. "느려진다/코드가 는다"는 정성적으로만 말할 수 있습니다.

5. 실무·대기업 변형 — 원전과 무엇이 다른가

5.0 먼저 알아야 할 것 (혼용 주의)

조사한 11개 실무 문서 중 "Clean Architecture(CA)"를 직접 지칭한 것은 3개뿐입니다(UNIL TransactionPort, wakita CQRS-lite, Buckpal 책 제목). 나머지 8개(우아한형제들 2건, Allegro, Herberto Graça, Reflectoring, Arho Huttunen, Sahibinden, kamilmazurek)는 스스로를 Hexagonal / Onion / Layered 로 부릅니다.

→ 따라서 "이건 A사의 클린 아키텍처다"라고 뭉뚱그리는 것은 대부분 근거 없는 일반화입니다. 정확히는 "클린 아키텍처 계열(Hexagonal/Onion 포함)의 실무 변형"입니다.

5.1 우아한형제들 — 4-Hexagon 멀티모듈

  • 상황(context): 비즈니스 요구사항을 빠르게 개발해야 하면서, 기술 선택에 드는 고민 비용을 줄이고 팀 단위 제품 오너십을 강화하려던 상황. (근거: 아래 장점 인용)
  • 원전과 다른 점: 헥사곤을 4개(Domain / Application / Framework / Bootstrap)로 정의하고, 각각을 Gradle 물리 모듈로 강제합니다. 원문이 "핵사곤(Layer)"이라고 표기하듯, Cockburn의 단일 application core나 Uncle Bob의 4-circle과 명명·경계가 다릅니다. (구조 자체는 사실, 원전과의 대조는 INFERENCE)

    "총 4개의 핵사곤(Layer)으로 정의하였습니다. Domain Hexagon, Application Hexagon, Framework Hexagon, Bootstrap Hexagon"

  • 장점(주장): 기술 선택 고민 비용 절감, 팀 결속력/오너십 강화.

    "기술 선택에 대한 고민으로 소모되는 비용을 아낄 수 있는..."

  • 단점(자인): 앞서 §4에서 본 outputPort 인터페이스 폭증. 또한 이 글은 트랜잭션 경계 정책을 아예 다루지 않습니다(모듈 분리만으로 해결 안 됨).
  • 출처: raw/company-tech-blogs/hexagonal-woowahan-techblog-2023, raw/company-tech-blogs/woowahan-hexagonal-multimodule (company-case-study)

5.2 Allegro — Onion Architecture

  • 상황(context): Hexagonal을 쓰던 저자가 "코드 배치(layout)를 더 구조화된 방식으로 하고 싶다"는 문제의식에서 대안으로 선택한 상황. (근거: "more structured approach to the code layout")
  • 원전과 다른 점: 스스로를 Hexagonal의 "대안(alternative)" 으로 위치시키고, "더 구조화된 code layout"이라는 차이를 내세웁니다. 우열을 주장하지 않습니다(alternative ≠ superior). 참고로 이 글은 "Clean Architecture"라는 단어 자체를 쓰지 않습니다.

    "It can be successfully used as an alternative to a popular Hexagonal / Ports and Adapters architecture"

  • 장점(주장): 도메인 코드와 HTTP·DB 같은 기술 관심사의 강한 분리.
  • 단점: 원문에 명시된 단점 없음(확인 안 됨). "layer 안에서 feature를 어떻게 자를지 가이드가 없다"는 지적은 raw 작성자의 추정(INFERENCE)입니다.
  • 출처: raw/company-tech-blogs/onion-allegro-tech-blog-2023 (company-case-study, 저자 1인)

5.3 Herberto Graça — Explicit Architecture (DDD·Hexagonal·Onion·Clean·CQRS 통합)

  • 상황(context): DDD·Hexagonal·Onion·Clean·CQRS를 하나의 프로젝트에 통합하려는 상황(글 제목 자체가 "how I put it all together"). 특히 읽기 경로를 단순화하고 싶은 요구.
  • 원전과 다른 점: "모든 요청은 Use Case(Application Service)를 통과한다"는 암묵적 통념에 예외를 둡니다. CQRS의 읽기(Query) 경로는 Application Service를 우회해 바로 DTO를 반환할 수 있다고 봅니다.

    "The Query object will contain an optimized query that will simply return some raw data to be shown to the user."

  • 장점(주장): 읽기 경로 단순화, 도메인 엔티티를 노출하지 않고 DTO/ViewModel로 반환.
  • 단점: 이 패턴을 ArchUnit으로 정적 강제하는 구체적 방법은 원문 발췌 밖(확인 안 됨).
  • 출처: raw/company-tech-blogs/explicit-architecture-ddd-hexagonal-cqrs-hgraca (engineering-blog)
  • 용어 한 줄 풀이 — CQRS: Command Query Responsibility Segregation. 쓰기(command)와 읽기(query) 경로를 분리하는 패턴.

5.4 wakita — CQRS-lite Read-Path Bypass

  • 상황(context): 읽기(조회) 요청이 아무것도 바꾸지 않는데도 완전히 검증된 도메인 객체를 매번 만들었다가 곧바로 DTO로 풀어내는, 즉 읽기 경로의 오버헤드가 큰 상황.
  • 원전과 다른 점: 읽기 경로가 도메인 aggregate를 거치는 것을 "순수 오버헤드(pure overhead)" 라고 명시적으로 규정하고, 읽기 전용 repository를 application 계층 포트로 두어 도메인을 우회합니다. 물리적 store 분리 없이 논리적으로만 CQRS를 적용합니다.

    "Steps 4 and 5 are pure overhead. ... It just needs data — but it's constructing fully validated domain objects, only to immediately unwrap them into flat DTOs." "The split is logical, not physical."

  • 장점(주장): 읽기/쓰기 store를 물리적으로 나누지 않고도 CQRS의 이점(읽기 최적화) 확보.
  • 단점: 실제 성능 개선 수치 증거 없음. 또한 Kotlin+jOOQ 구현이라 Java+Spring Data JPA로 그대로 이식 가능하다고 말하면 안 됩니다.
  • 출처: raw/company-tech-blogs/cqrs-lite-clean-architecture-read-path-bypass-wakita (engineering-blog)

5.5 Spring @Transactional 배치 — 다수파 vs 소수파

트랜잭션 경계를 어디에 두느냐에서 실무가 갈립니다. 면접 단골 주제입니다.

  • 상황(context): Spring 환경에서 use case의 트랜잭션 경계를 정해야 하는데, "도메인·application은 framework-free" 원칙을 지킬 것이냐 vs 실용성(코드 간결)을 택할 것이냐의 갈림.

  • 다수파: use case에 @Transactional 직접 부착 — 코드가 가장 적고 진입 장벽이 낮습니다. Reflectoring 튜토리얼과 Buckpal(별 2,500+의 유명 예제)이 이 방식입니다.

    "@Component @Transactional public class SendMoneyService implements SendMoneyUseCase" — 출처: raw/company-tech-blogs/hexagonal-reflectoring-transactional-placement

    • 긴장점: application 계층이 org.springframework...Transactional을 import → "domain-application은 framework-free"라는 원칙과 어긋납니다(단, 이건 raw 작성자 해석이며 저자 본인의 정당화는 없음).
  • 소수파: 트랜잭션을 output port로 추상화 — UNIL은 프레임워크 중립 애노테이션을 선호하거나 runInTransaction(Runnable) 형태의 포트로 뽑아, presentation 실패가 트랜잭션 롤백을 유발하지 않게 경계를 분리합니다. 이 글은 "CA(Clean Architecture)"를 직접 언급합니다.

    "this isolates 'Use Cases' layer from dependency on a framework (design-time), which is prohibited by CA." "Present result of successful execution of the use case outside transactional boundary." — 출처: raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium

    • 단점: Runnable 시그니처는 nested transaction/propagation/isolation 표현력이 @Transactional 속성보다 빈약합니다(INFERENCE — raw 메모).
  • Arho Huttunen은 JPA 엔티티와 도메인을 분리하고 application 모듈을 Spring 무의존으로 두면서도, 현재 @Transactional 배치가 불충분하다고 스스로 비판합니다("we can do better"). 출처: raw/company-tech-blogs/arhohuttunen-hexagonal-architecture-spring-boot

5.6 Package-by-Feature vs Package-by-Layer

최상위 패키지를 무엇으로 자르느냐의 문제입니다.

  • 상황(context): 애플리케이션이 커지면서 계층별(layer) 패키지의 저응집·고결합이 드러나, 최상위 분할축을 기능(feature)으로 바꿀지 검토하는 상황.
  • Package-by-Feature(기능별): 한 기능에 필요한 클래스가 한 패키지에 모여 응집도↑, 패키지 이동 비용↓, package-private 가시성으로 캡슐화↑.

    "Package by Feature reduces the need to navigate between packages..." / "...set their access modifier package-private instead of public, so it increases encapsulation."

  • Package-by-Layer(계층별, controller/service/repository): 서로 관련 없는 클래스가 한 패키지에 모여 저응집·고결합, 도메인이 늘수록 패키지 클래스 수가 무한정 증가.

    "This method causes low cohesion within packages..." / "the number of classes in each package will increase without bound"

  • 주의: 이 자료는 Layer 방식의 단점만 열거하고 Feature 방식 자체의 단점은 말하지 않습니다. 면접에서 "Feature 방식의 단점은?"이라고 되물으면 이 자료만으로는 답할 수 없습니다(공통 kernel 위치·모델 중복 위험 등은 canonical 문서 참조: wiki/concepts/clean-architecture-package-layout).
  • 출처: raw/company-tech-blogs/feature-first-sahibinden-package-by-layer-vs-feature (company-case-study), raw/company-tech-blogs/layer-first-kamilmazurek-github-template (저자 self-attestation, 단점 미기재)

5.7 Buckpal — 반례(CONTRARY) 증거

  • 상황(context): 책 예제 프로젝트로서 개념 전달·실용성·간결성을 우선한 상황(getter/setter 보일러플레이트를 줄이려 Lombok 허용, 트랜잭션을 간단히 쓰려 @Transactional 직접 부착).
  • 왜 중요한가: Buckpal은 Tom Hombergs의 저서 Get Your Hands Dirty on Clean Architecture의 공식 예제(별 2,500+)입니다. 그런데 여기서는 도메인 순수성 ArchUnit 규칙이 Lombok을 명시적으로 허용(allowlist) 하고, application service에 @Transactional을 직접 부착합니다.

    ArchUnit rule: ...resideOutsideOfPackages("...application.domain.model..", "lombok..", "java..")

  • 면접 활용: "왜 당신의 프로젝트(ca-tmpl)는 Lombok 금지·@Transactional 금지처럼 업계 유명 예제보다 더 엄격한 규칙을 택했는가?"에 답할 때, "이게 업계 다수파 best practice가 아니라 의식적인 소수파 선택"임을 정직하게 설명하는 근거가 됩니다.
  • 이 파일 스스로 "@Transactional 직접 부착이 Hexagonal의 권장 패턴"이라는 주장은 UNSUPPORTED_DECISION(Spring 공식이나 Hexagonal 명세가 그렇게 권장한 적 없음)이라고 못 박습니다.
  • 출처: raw/company-tech-blogs/buckpal-archunit-lombok-allowlist-direct-transactional (frontmatter상 personal-blog)

6. 변형 비교 요약 표

변형 원전과의 핵심 차이 주장 장점 인정 단점 등급
우아한형제들 4-Hexagon 헥사곤=Layer, Gradle 물리 모듈 강제 기술선택 비용↓, 팀 결속력 outputPort 폭증, 트랜잭션 정책 부재 company-case-study
Allegro Onion Hexagonal의 "대안"으로 자기 위치(우열 주장 X) 도메인/기술 강한 분리 원문에 단점 없음(확인 안 됨) company-case-study
Graça Explicit Architecture CQRS Query가 Application Service 우회 읽기 경로 단순화, DTO 반환 ArchUnit 강제법 미제시 engineering-blog
wakita CQRS-lite 읽기 경로 = "pure overhead", 논리적 분리 물리 store 분리 없이 CQRS 성능 수치 없음, Kotlin/jOOQ 한정 engineering-blog
Reflectoring / Buckpal use case에 @Transactional 직접(다수파) 코드 최소, 진입장벽 낮음 명시적 정당화 없음, 원칙과 긴장 engineering / personal-blog
UNIL TransactionPort 트랜잭션을 output port로 추상화(소수파) presentation을 트랜잭션 밖 분리 Runnable 표현력 빈약(INFERENCE) company-case-study
Arho Huttunen JPA/도메인 분리, application Spring 무의존 clean separation 모델 간 매핑 비용(자인) engineering-blog
Sahibinden Feature vs Layer 최상위 분할축(feature vs layer) feature: 캡슐화/응집↑ Layer 단점만 기술(Feature 단점 없음) company-case-study
kamilmazurek Layer-first API/Service/Repository/Database 4-layer Simplicity/Maintainability(자기평가) 단점 원문 미기재 engineering-blog
Buckpal (반례) domain 규칙에 Lombok 허용 + @Transactional 직접 (장점 옹호 아님 — 반례 목적) "권장 패턴" 주장은 UNSUPPORTED personal-blog

7. 면접에서 조심할 것 (Overclaim 경고)

  • "클린 아키텍처는 공식 표준이다" → Uncle Bob·Cockburn 글은 개인 블로그입니다. 표준 기구 문서 아님.
  • "우아한형제들/Allegro의 클린 아키텍처" → 이들은 대부분 Hexagonal/Onion을 자칭하며 클린 아키텍처를 직접 지칭하지 않습니다.
  • "4-Hexagon이 헥사고날 표준" → vendor-specific 해석입니다.
  • "outputPort 폭증/팀 결속력 같은 회고를 성과 지표처럼" → 정량 근거 없음.
  • "Buckpal이 Hexagonal 공식 권장이니 @Transactional 직접이 정답" → 파일 자체가 UNSUPPORTED_DECISION으로 명시.
  • "장점(테스트 격리·도메인 독립)은 원전 근거가 있지만, 단점의 정량 근거는 희박하다" → 이 균형 감각이 오히려 신뢰를 줍니다.

8. 내가 설명할 수 있어야 하는 것 (셀프 체크)

  • Dependency Rule 한 문장으로 클린 아키텍처를 정의할 수 있는가?
  • 4개 동심원의 이름과 각 원이 담는 것을 말할 수 있는가?
  • 제어 흐름과 소스 의존성 방향이 반대인 이유(DIP)를 설명할 수 있는가?
  • 클린 아키텍처 / Hexagonal / Onion의 관계(사실상 같은 규칙, 다른 표현)를 설명할 수 있는가?
  • 장점은 원전 근거로, 단점은 "직접 근거가 희박함"을 함께 말할 수 있는가?
  • @Transactional 배치의 다수파/소수파와 그 트레이드오프를 말할 수 있는가?
  • "우리 프로젝트가 유명 예제(Buckpal)보다 엄격한 규칙을 택한 것은 의식적 소수파 선택"이라고 정직하게 설명할 수 있는가?

9. 다음 단계 (정식 파이프라인으로 승격하려면)

이 문서는 wiki/topics-interview/에 둔 비표준(off-pipeline) 스터디 노트입니다. 만약 이 내용을 정식 면접 산출물(wiki/interview/)이나 블로그로 쓰려면 CLAUDE.md §15 순서를 따라야 합니다.

  1. /ingest로 canonical 개념 문서를 먼저 정비/신설: 기존 wiki/concepts/clean-architecture-package-layout 보강 + (권고) wiki/concepts/hexagonal-architecture.md, wiki/concepts/anti-corruption-layer.md, wiki/concepts/clean-architecture-industry-variants.md 신설.
  2. 사람이 검토해 canonical status를 reviewed 이상으로 올림.
  3. 그 후 /interviewizewiki/interview/에 파생(원천 status가 reviewed|verified|published-ready 미만이면 중단됨).

Sources

Canonical (검증 보조)

공식/원전 (raw/official-docs — engineering-blog·official-reference·official-vendor-doc)

실무·대기업 사례 (raw/company-tech-blogs — company-case-study·engineering-blog·personal-blog)