Files
llm-wiki/raw/company-tech-blogs/domain-woowahan-ddd-aggregate-techblog.md
T

119 lines
11 KiB
Markdown

---
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 요약: (미작성)