--- title: 우아한형제들 — DDD Aggregate / Hexagonal 도메인 분리 (검증된 부분 + 미검증 요약) source_type: company-tech-blog url: https://techblog.woowahan.com/12720/ archive_url: status: raw confidence: low tags: [domain, ddd, aggregate, woowahan, jpa, ca-skeleton, hexagonal] related_branches: [feature-domain-modeling-guardrails] related_projects: [ca-skeleton-operational-contract] created: 2026-05-22 last_reviewed: 2026-05-27 --- # 우아한형제들 — DDD Aggregate / Hexagonal 도메인 분리 > Layer: `raw/company-tech-blogs/` — 우아한형제들 기술블로그의 Hexagonal Architecture / 도메인 분리 사례. > **중요 — 원본 URL 검증 결과**: 이전 buffer 의 `https://techblog.woowahan.com/2711/` 는 "DDD Aggregate 도메인 객체와 JPA 매핑하기" 가 **아님** — 실제 글 제목은 "잊을만 하면 돌아오는 정산 신병들" (정산시스템 파일럿 후기). 잘못된 URL 인용 발견. 본 raw 는 실제 verified URL `/12720/` (Spring Boot Kotlin Multi Module Hexagonal Architecture, 2023-07-11) 로 교체. 기존 본문의 "DDD Aggregate / @OneToMany cascade / @BatchSize" 인용은 **출처 미확보** 상태로 분리 보존. ## Parent / 활용 branch (필수) | Branch | 이 자료가 정당화하는 결정 | |---|---| | [[raw/branch-notes/feature-domain-modeling-guardrails]] | Domain 객체와 JPA Entity 분리 결정의 한국 현장 사례 (Hexagonal 헥사곤별 자체 객체 보유 패턴) | | [[raw/project-notes/ca-skeleton-operational-contract]] | §19 Domain Application Readiness Contract 의 도메인 모델링 대안 reference | ## 출처 / Source - **검증된 URL**: https://techblog.woowahan.com/12720/ ("Spring Boot Kotlin Multi Module Hexagonal Architecture", 2023-07-11, WoowaTech) - **미검증 URL (수정 필요)**: ~~https://techblog.woowahan.com/2711/~~ — 본 URL 의 실제 내용은 정산시스템 파일럿 후기 (저자 김시영). DDD Aggregate 글이 아님. - 보조 (미검증): 우아한형제들 "이벤트 기반 분산 트랜잭션" — https://techblog.woowahan.com/7835/ (별도 확인 필요) - 보조 (미검증): 우아한테크코스 강의자료 "Aggregate 설계" (박재성, 2023) - 저자/조직: 우아한형제들 (Woowa Brothers) 기술블로그 - 발행일: 2023-07-11 (검증된 글) - 마지막 확인일: 2026-05-27 ## 왜 저장했는지 / Why archived ca-tmpl 의 "ORM 외부 매핑 / 도메인 분리" 결정에 대한 한국 현장 사례. 우아한형제들은 일찍부터 DDD / Hexagonal 을 도입한 한국 대표 사례이고, 같은 결정 (Domain 객체와 JPA Entity 를 어떻게 분리할 것인가) 을 다르게 푸는 방식을 보여줌. ca-tmpl 이 같은 노선 (별도 JpaEntity, ArchUnit 으로 javax.persistence import 금지) 을 채택한 trade-off 기록용. ## 핵심 인용 / Key quotes (verbatim) ### 검증된 인용 (techblog.woowahan.com/12720/, 2023-07-11) > [§헥사고날 아키텍처의 목적] "헥사고날 아키텍처는 비즈니스 요구사항을 빠르게 개발할 때 기술 선택에 대한 고민으로 소모되는 비용을 아낄 수 있습니다." > [§Domain Hexagon] "DDD(도메인 주도 개발)의 그 Domain Layer로 기술에 독립적인 POJO로 개발" > [§Domain Hexagon] "POJO로 구현하기 때문에 Spring의 Component, Service annotation 등 비사용" > [§Application Hexagon] "Domain의 구성요소를 사용하여 시스템이 가지는 기능/사례(usecase)를 정의한 집합" > [§Application Hexagon] "DB가 어떤 것인지, 외부에서 시스템을 가동하기 위한 기술은 무엇인지 아무것도 알 필요가 없다." > [§Object Mapping] "각 포트로의 데이터 교환에 있어서 헥사곤 영역에 맞는 클래스로 필드 매핑이 계속 발생합니다." > [§Separate Domain Objects] "각 헥사곤이 자신만의 객체를 보유하게 분리를 결정했지만 잘한 선택이었다고 생각합니다." ### 미검증 인용 (1차 출처 URL 미확정 — 분리 보존) > **경고**: 다음 인용들은 이전 buffer 에 기재되었으나, 명시된 URL (/2711/) 에서 verbatim 으로 확인되지 않음. 원문 출처 재확보 전까지 ingest 단계에서 사용 금지. > [미검증] "Aggregate는 데이터 변경의 단위입니다. Aggregate Root를 통해서만 내부 엔티티에 접근할 수 있어야 하고, 영속성 컨텍스트에 의해 그 일관성이 유지되어야 합니다." > [미검증] "JPA의 `@OneToMany` cascade를 활용하면 Aggregate 내부 엔티티의 lifecycle을 root와 묶을 수 있지만, 양방향 매핑에서 무한 루프와 N+1을 막기 위한 `@BatchSize` 설정이 필요합니다." > [미검증] "도메인 객체에 JPA 어노테이션을 직접 부착하는 방식은 단순하지만, 도메인이 ORM에 종속됩니다. 별도의 JpaEntity를 두고 도메인과 분리하는 hexagonal 변형도 사내에서 일부 사용 중입니다." > [미검증] "Aggregate 내부 mutator는 가급적 root method를 거치도록 설계하고, JPA가 reflection으로 객체 생성을 위해 필요한 기본 생성자는 `protected`로 두어 외부에서 직접 호출하지 못하게 합니다." ## Claims Extracted / 추출된 주장 | Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove | |---|---|---|---|---|---| | WOOWA-HEX-C1 | 헥사고날 아키텍처는 비즈니스 요구사항 개발 시 기술 선택 비용을 절감하는 데 도움이 됨 | [§목적, verified /12720/] "헥사고날 아키텍처는 비즈니스 요구사항을 빠르게 개발할 때 기술 선택에 대한 고민으로 소모되는 비용을 아낄 수 있습니다." | `company-case-study` | 빠른 비즈니스 개발이 우선인 팀 | 모든 프로젝트에 헥사고날이 적합하다는 일반화 금지. 우아한 단일 팀의 견해 | | WOOWA-HEX-C2 | Domain Hexagon 의 클래스는 기술 비종속 POJO 로 구현 — Spring `@Component` / `@Service` 등 annotation 미사용 | [§Domain Hexagon, verified] "DDD(도메인 주도 개발)의 그 Domain Layer로 기술에 독립적인 POJO로 개발" + "POJO로 구현하기 때문에 Spring의 Component, Service annotation 등 비사용" | `company-case-study` | Domain 순수성 강제가 목표인 팀 | POJO 가 Domain Layer 의 유일한 표현 방식이라는 뜻 아님 — 다른 DDD 변형은 framework annotation 허용 | | WOOWA-HEX-C3 | Application Hexagon 은 Domain 구성요소로 usecase 를 정의하며, DB / 외부 기술 무지 (DB 종류 등 모름) | [§Application Hexagon, verified] "Domain의 구성요소를 사용하여 시스템이 가지는 기능/사례(usecase)를 정의한 집합" + "DB가 어떤 것인지, 외부에서 시스템을 가동하기 위한 기술은 무엇인지 아무것도 알 필요가 없다." | `company-case-study` | usecase 중심 application layer 설계 | application layer 의 책임 범위는 팀별로 다르게 정의 가능 | | WOOWA-HEX-C4 | 각 포트 통신마다 헥사곤별 클래스로 **필드 매핑 코드가 지속적으로 발생** (오버헤드 존재) | [§Object Mapping, verified] "각 포트로의 데이터 교환에 있어서 헥사곤 영역에 맞는 클래스로 필드 매핑이 계속 발생합니다." | `company-case-study` | 헥사고날 도입 시의 trade-off 평가 | 매핑 비용이 자동화 도구 (MapStruct 등) 로 줄어들 수 있는지 본문에 명시 없음 | | WOOWA-HEX-C5 | 각 헥사곤이 **자신만의 객체를 보유** 하는 분리 결정 — 저자는 이 선택을 긍정 평가 | [§Separate Domain Objects, verified] "각 헥사곤이 자신만의 객체를 보유하게 분리를 결정했지만 잘한 선택이었다고 생각합니다." | `company-case-study` | Domain / Application / Adapter 객체 분리 결정 | "잘한 선택" 은 저자 1인의 주관 평가 — 정량 측정 없음 | | WOOWA-HEX-C6 | (미검증) DDD Aggregate Root 만으로 내부 엔티티 접근, JPA `@OneToMany` cascade + `@BatchSize` 패턴, protected no-arg constructor 패턴이 우아한형제들 글에 명시되어 있다는 주장 | [미검증, /2711/ 에 부재] | `needs-confirmation` | 원본 출처 재확보 전까지 사용 금지 | 인용된 patterns 가 일반 DDD/JPA practice 임은 사실이나, 우아한형제들의 **공식 입장** 으로 인용하려면 1차 출처 URL 재확보 필요 | ## Usage Boundaries / 적용 경계 - **이 자료가 직접 증명하는 것**: - `WOOWA-HEX-C1` ~ `C5`: 우아한형제들 /12720/ 글의 Hexagonal 아키텍처 채택 동기, Domain POJO 패턴, 헥사곤별 객체 분리 결정과 trade-off - **이 자료가 증명하지 않는 것**: - `WOOWA-HEX-C6`: DDD Aggregate / JPA cascade / BatchSize / protected constructor 패턴이 우아한형제들 글에 명시되어 있다는 점 (1차 출처 미확정) - 우아한형제들 전체 (모든 팀) 가 Hexagonal 을 채택했다는 사실 — 본 글은 한 팀 사례 - prod 운영 측정값 (성능, 인시던트, 매핑 오버헤드 정량값) - **내 프로젝트에 적용하려면 추가 확인이 필요한 것**: - ca-tmpl 의 ArchUnit 룰 (domain → javax.persistence import 금지) 이 /12720/ 의 "Domain Hexagon POJO" 룰과 일치하는지 검증 - `WOOWA-HEX-C6` 의 DDD Aggregate / cascade / BatchSize claim 의 1차 출처 URL 재확보 (있다면 verbatim 으로 본 raw 에 추가) ## 메모 / Notes - ca-tmpl 결정과의 비교 (verified /12720/ 기준): - **우아한형제들 /12720/ 팀**: 헥사곤별 객체 분리 + Domain POJO + 매핑 코드 비용 감수. ca-tmpl 의 "domain 순수성 + 별도 mapper" 노선과 같은 방향. - **ca-tmpl**: 후자 채택. ArchUnit 으로 domain → javax.persistence import 를 금지. - 트레이드오프 (verified): - 매핑 코드 비용 (`WOOWA-HEX-C4`) vs 도메인 순수성 (`WOOWA-HEX-C2`). - 본 글은 후자에 더 큰 가치를 부여 (`WOOWA-HEX-C5` "잘한 선택"). - 우아한 글에서 ca-tmpl 이 채택하지 않은 부분 (미검증 영역): - cascade ALL 은 ca-tmpl 에서 명시적으로 다루지 않음 (persistence branch 영역) — 단, 우아한 측 입장의 1차 출처도 미확정. - 양방향 매핑 / `@BatchSize` 권고는 본 raw 에서 인용 가능 출처 없음. - 출처 신뢰도: company-tech-blog / company-case-study. **공식 best practice 아님**. 한국 백엔드 현장에서 자주 참조되지만 ca-tmpl 적용 시 "Netflix 가 그러하니까" 식 일반화 금지. - **TODO**: `WOOWA-HEX-C6` (DDD Aggregate / JPA cascade / BatchSize 인용) 의 1차 출처 URL 재확보. ## Related / 관련 - 같은 주제 다른 raw: - [[raw/company-tech-blogs/modulith-kakaobank-techblog-2025]] - [[raw/company-tech-blogs/onion-allegro-tech-blog-2023]] - 인용하는 branch: - [[raw/branch-notes/feature-domain-modeling-guardrails]] - 인용하는 project: - [[raw/project-notes/ca-skeleton-operational-contract]] (§19 Domain Application Readiness Contract) - 대안 그룹: **Group G-J — Privacy / File / Domain Modeling** (domain modeling) - 인용한 wiki 요약: (미작성)