이 글은 넥스트스텝의 DDD 세레나데 7기 교육을 5주간 참여하며 배운 경험과 느낀 점을 정리한 후기입니다.
Prologue
아래는 DDD 세레나데 7기 교육을 무사히 끝마친 후 받은 수료증입니다.
DDD 세레나데 7기에 참여하면서 도메인 주도 설계(DDD)의 기본 개념부터 실전 적용까지 다양한 내용을 배울 수 있었습니다.
미션을 수행하며 리뷰어 피드백을 반영하는 과정이 큰 도움이 되었습니다.
1주차에 대한 리뷰는 이미 작성한 글인 DDD 세레나데 7기 1주차 (feat. 이벤트 스토밍) 를 참고하시면 되므로, 이번 글에서는 2주차부터 정리하고자 합니다.
2주차 - 전략적 설계
2주차에서는 DDD의 핵심 개념인 전략적 설계(Strategic Design) 에 대해 배우며, 특히 유비쿼터스 언어
(Ubiquitous Language)와 바운디드 컨텍스트
(Bounded Context) 개념을 깊이 있게 다루었습니다.
2주차에 진행한 미션에 대한 결과는 아래와 같습니다.
이번 미션은 페어 프로그래밍(두 명이 함께 작업하는 방식)으로 진행되었지만, 일정 조율이 어려워 각자 미션을 수행하는 방식으로 합의하여 진행했습니다.
용어 사전 만들기
이번 미션을 수행하면서 용어 사전과 모델링을 작성한 경험이 있었지만, 예상보다 더 구체적으로 작성해야 한다는 점이 기억에 남습니다.
특히, 용어 사전은 단순한 리스트가 아니라 한글명, 영문명, 그리고 구체적인 설명이 포함되어야 하며, 개발자뿐만 아니라 비개발자도 이해할 수 있어야 한다는 점이 중요했습니다.
이에 따라 용어 사전을 아래와 같은 방식으로 정리했고, 리뷰어님께 해당 정의가 적절한지 피드백을 요청했습니다. 다행히도 제가 생각했던 방향과 동일하다는 답변을 받을 수 있었습니다.
용어 사전
이란 프로젝트(또는 서비스)에 참여하는 도메인 전문가, 개발자, 그리고 기획자·디자이너·데이터 분석가 등 다양한 직군 간의 의사소통을 명확하게 하기 위한 도구라고 생각한다.아래는 이전에 작성한
용어 사전
중 일부를 가져왔습니다.
모델링하기
모델링에 대해서는 처음에는 도메인 내 객체의 속성(상태)을 구성하고, 객체 간의 관계를 표현하는 과정이라고 생각했습니다.
그러나 미션을 진행하면서 다른 참여자들의 PR을 확인해본 결과, 단순히 객체의 속성을 정의하는 것만이 아니라, 속성(상태), 행위(기능), 정책(제약사항)으로 카테고리를 나누어 작성하는 방식이 더 적절하다는 점을 알게 되었습니다.
리뷰어님께서도 모델링은 어떻게 표현하느냐에 따라 다를 수 있으며, 대상에 따라 깊이와 디테일이 달라져야 한다는 피드백을 주셨습니다.
- 기획자, 상위직책자 분들에게 디테일 보다는 정확한 흐름과 팩트가 필요하다.
- 협업 부서, 동료 개발자에게는 보다 디테일한 내용이 추가되어야 한다.
이번 2단계에서 작성한 모델링은 협업 부서 및 동료 개발자에게 제공할 목적이었기 때문에, 속성(상태), 행위(기능), 정책(제약사항)으로 구분하여 더 구체적으로 작성했습니다.
요구사항을 기반으로 모델링을 도출하다 보면 자연스럽게 중복되는 부분이 생깁니다. 하지만 이는 도메인에 대한 이해를 더욱 명확하게 정리하는 과정으로 볼 수 있습니다.
아래는 이전에 작성한
모델링하기
중 일부를 가져왔습니다.
2주차 복습하기
2주차에서 배운 개념(용어)들을 필자의 개인적인 생각과 함께 정리했습니다.
도메인
이란 우리가 해결해야할 영역 → 보통은 비즈니스 도메인이라 부릅니다.- 예시. 커머스
하위 도메인
이란 도메인을 세부 도메인으로 나누는 것을 의미합니다.- 예시. 전시, 카탈로그, 상품, 주문, 결제, 정산
- 이런 하위 도메인은 자연스럽게 도출되는 개념이다. → 그만큼 하위 도메인은 제어할 수 없는 대상이 될 수 있습니다.
- 특정 하위 도메인의 비즈니스 가치가 크다면, 추가적으로 더 세부적인 하위 도메인을 정의할 수 있습니다.
하위 도메인
과바운디드 컨텍스트
의 차이점은 무엇인가요?- 하위 도메인은 자연스럽게 나뉘며, 바운디드 컨텍스트는 인위적으로 나뉩니다.(->의도적으로 구분하는 경계)
- 하위 도메인은 관심사이며, 바운디드 컨텍스트는 그 관심사를 구분짓는 경계로 간주됩니다.
- 언제
바운디드 컨텍스트
를 분할해야 하나요?- 서비스가 커짐에 따라 복잡성이 높아질 때입니다.
- 또는 모두가 동일하게 이해하고 개발하기 편하도록 경계가 필요할 때입니다.
- 요구 사항과
도메인 모델링
의 차이점은 무엇인가요?- 요구사항과 모델링은 만드는 사람(=주체)에 따라 달라진다고 생각됩니다.
- 요구사항은 클라이언트가 우리에게 문제를 해결해달라는 의미이고,
- 도메인 모델링은 그러한 문제를 해결하기 위한 아이디에이션(=아이디어 도출)입니다.
- 이러한 접근 방법을 표현하기 위하여 다이어그램, 글, 그림 등 다양한 도구를 활용합니다.
- 요구사항과 모델링은 만드는 사람(=주체)에 따라 달라진다고 생각됩니다.
도메인 엔티티
와 영속성 엔티티의 차이점은 무엇인가요?- 도메인 엔티티는 식별자를 갖는 무언가입니다. -> 비즈니스적으로 중요한 개념
- 영속성 엔티티는 테이블 관점에서 도출됩니다. -> 데이터베이스 저장을 위해 도출된 개념
- 이 두 개(Persistence, 도메인 주도 설계)는 높은 확률로 동일할 수도 있고, 다를 수도 있습니다.
- 어떤 엔티티가 애그리거트에서 루트 엔티티가 될 수 있나요?
- 외부에 노출되어 있는지 여부에 따라 결정됩니다.
- 즉, 외부에 노출되어도 되는 엔티티인 경우 루트 엔티티가 될 수 있습니다.
- 애그리거트와 리포지토리는 어떤 관련이 있나요?
- 애그리거트는 관련 객체들을 하나로 묶은 군집을 의미합니다.
- 이는 특정 객체의 타입이 아니라, 관련 객체들을 논리적으로 묶는 구조를 의미합니다.
레포지토리
는 애그리거트 단위로 도메인 객체를 저장하고 조회하는 기능을 정의합니다.- 애그리거트(루트) 단위로 존재하며 테이블 단위로 존재하지 않습니다.
- JPARepository, CrudRepository 등의 인터페이스를 활용하여 레포지토리를 구현할 수 있습니다.
- 다만, 이는 JPA 관점에서의 레포지토리이지, DDD에서의 레포지토리 개념과 동일하지 않을 수도 있습니다.
- 애그리거트는 관련 객체들을 하나로 묶은 군집을 의미합니다.
3주차 - 전술적 설계
3주차에서는 전술적 설계(Tactical Design) 를 기반으로 기존 코드를 도메인 중심으로 리팩터링하는 과정이 진행되었습니다. 이전 주차가 개념 학습과 문서화 중심이었다면, 이번 주차부터는 본격적으로 실제 코드에 DDD 개념을 적용하는 과정이 핵심이었습니다.
이번 미션에서는 상품, 메뉴, 매장 식사 주문과 관련된 도메인을 리팩터링하며, 도메인 중심으로 설계를 변경하고 비즈니스 로직을 보다 명확하게 분리하는 작업을 수행했습니다.
3주차에 진행한 미션에 대한 결과는 아래와 같습니다.
이전 2주차까지는 도메인 개념을 정리하고 모델링하는 과정이 중심이었다면, 3주차부터는 실제 코드에서 도메인 중심으로 설계를 변경하고, 불필요한 의존성을 줄이며, 유지보수하기 좋은 구조로 개선하는 과정을 진행했습니다.
리팩터링을 진행하면서 필자는 무의식적으로 DBA(Database Administrator) 관점에서 문제를 해결하려는 습관이 있다는 점을 깨달았습니다. 즉, 데이터베이스 모델을 먼저 고민하고, 데이터를 중심으로 구조를 잡으려는 방식이었습니다.
그러나 도메인 주도 설계에서는 이러한 접근 방식보다는 비즈니스 요구사항을 먼저 고려하고, 도메인 개념을 중심으로 코드 구조를 잡아야 한다는 것이 더 중요했습니다.
이러한 피드백을 기반으로 리팩터링 방향을 다음과 같이 정리했습니다.
- 비즈니스 요구사항을 기반으로 도메인 객체를 설계
- 데이터 중심이 아닌 도메인 중심의 접근 방식 적용
- 비즈니스 로직은 실행 흐름과 도메인 행위 중심으로 설계
결국, 코드에서 “데이터가 아니라 비즈니스 개념을 중심으로 사고하는 것”이 중요하다는 점을 다시 한번 깨닫게 되었습니다.
양방향 의존성 문제 해결
리팩터링 과정에서 가장 고민했던 부분 중 하나는 상품과 메뉴 간의 양방향 의존성 문제였습니다.
기존 코드에서는 상품
과 메뉴
가 서로 직접 참조하는 구조를 가지고 있었습니다.
즉, 상품
이 변경될 경우 메뉴
도 영향을 받고, 반대로 메뉴
에서도 상품
을 직접 조회해야 하는 경우가 많았습니다.
이러한 양방향 의존성은 코드의 복잡성을 높이고, 유지보수를 어렵게 만들 수 있는 문제였습니다.
이 문제를 해결하기 위해 도메인 이벤트(Domain Event) 패턴을 적용했습니다.
- 상품은 본인의 역할만 수행하도록 하고,
- 메뉴는 상품에서 발생한 이벤트를 수신하여 후속 작업을 수행하도록 변경했습니다.
도메인 이벤트를 적용함으로써 상품과 메뉴 간의 강한 결합도를 줄이고, 각 도메인이 독립적으로 역할을 수행할 수 있도록 분리했습니다.
DDD는 정답이 아니라, 하나의 방법론일 뿐
이번 리팩터링을 진행하며, DDD가 무조건 정답은 아니라는 점을 다시 한번 깨닫게 되었습니다.
많은 사람들이 DDD를 적용하는 것을 목표로 삼지만, 중요한 것은 “DDD 자체”가 아니라 비즈니스 요구사항을 효과적으로 해결할 수 있는 설계를 만드는 것이라는 점입니다.
“어떤 방법을 사용하든, 유지보수하기 쉬운 코드가 최종 목표”
결국, 비즈니스 상황을 가장 잘 이해하는 사람이 유지보수성을 고려한 최적의 설계를 해야 한다는 점이 핵심이라고 생각합니다
“본인이 겪고 있는 현재의 비즈니스 상황에 대해 충분히 잘 알고 있고, 본인의 결정이 유지보수성이 높다고 확신한다면 그 길로 가는 것이 맞다.”
“만약 확신이 없다면, DDD와 같은 방법론을 활용하는 것도 좋은 접근법이다.”
DDD를 적용하는 것은 목적이 아니라 수단이며, 실무에서는 상황에 따라 유연하게 접근하는 것이 중요하다는 점을 다시 한번 느꼈습니다.
4주차 - 도메인 주도 아키텍처
4주차에서는 도메인 주도 설계를 실무에서 활용할 수 있도록, DTO, 의존 역전 원칙(DIP), 안티코러션 레이어(Anti-Corruption Layer) 등의 기술적인 내용을 다루었습니다.
이번 주차는 미션 없이 개념을 학습하는 형태로 진행되었습니다.
4주차에 배운 점들 중 기억에 남는 부분을 정리해봤습니다.
- 인터페이스는 어느 시점에 생성하는 것이 적절한가?
- 반드시 필요한 것은 아니며, 변경 가능성과 통제 가능성을 고려하여 결정해야 한다.
- 자주 변경될수록, 통제 불가능할수록 인터페이스를 만드는 것이 유용하다.
- DTO 가 등장하게 된 이유는?
- 애플리케이션에서 화면이 없었다면, DTO라는 개념도 존재하지 않았을 것이다.
- 즉, DTO는
외부 요구 사항
에 의해 등장하게 되었다.
- 순수한 도메인 모델(Pure Domain Model)
- 클라이언트와 도메인 모델을 분리하여 내부 요구사항과 외부 요구사항을 명확히 구분
- 애플리케이션의 내부 요구 사항은 주로 비즈니스와 관련된 도메인
- 애플리케이션의 외부 요구사항은 클라이언트가 서버 개발자에게 요청하는 부분이거나 클라이언트와 같은 외부에서 발생하는 요구사항을 수용하는 부분이다.
- 반드시 DTO를 만드는 것은 실용적이지 않다.
- DTO는 보통 애플리케이션 레이어에서 관리하는 것이 가장 적절하다.
- 클라이언트와 도메인 모델을 분리하여 내부 요구사항과 외부 요구사항을 명확히 구분
- 도메인 주도 설계는 사실 아키텍처가 아니다. => 도메인 주도 설계 != 아키텍처
- 최근에 나오고 있는 다양한 도메인 주도 설계는
클린 아키텍처
라고 설명한다. - 헥사고날 아키텍처 또는 클린 아키텍처가 도메인 주도 설계 구현하는데 있어서 도움을 준다.
- 2003년 에릭 에반스 도메인 주도 설계를 레이어드 아키텍처라고 소개한다.
- 2008년은 헥사고날 아키텍처라 부르고, 최근에 나오고 있는 책들은 클린 아키텍처라고 한다.
- 이러한 아키텍처들은 도메인을 보호하는데 용이한 아키텍처라고 말하고 싶었던 것이다.
- 꼭 아키텍처가 있어야 도메인 주도 설계를 한다는 것이 아니고, 헥사고날 아키텍처, 클린 아키텍처를 적용해야 하는것도 아니다.
- 이러한 아키텍처들은 도메인 주도 설계에 도움을 줄 뿐, 꼭 이 방법으로 안해도 된다.
- 최근에 나오고 있는 다양한 도메인 주도 설계는
5주차 - 도메인 이벤트와 CQRS
마지막 5주차에서는 도메인 이벤트(Domain Event), 이벤트 소싱(Event Sourcing), CQRS 개념을 학습했습니다. 강의 진행자인 제이슨님께서 Spring에서 이벤트를 처리하는 방식을 실시간 라이브 코딩을 통해 시연해 주셨습니다.
해당 주차도 이전 4주차와 마찬가지로 실습이 따로 진행되지는 않았지만, 개인적으로 궁금한 주제인 ‘이벤트기반 아키텍처 구축하기’가 궁금해서 관련 내용을 나중에 따로 찾아보려고 합니다.
해당 주차와 관련된 링크를 추가로 첨부했습니다.
-
회원시스템 이벤트기반 아키텍처 구축하기 (동영상)
Review
DDD 세레나데 7기를 돌아보며
해당 강의를 진행해주신 제이슨님의 말씀에 따르면 도메인 주도 설계에서 중요하면서도 어려운 개념 세개가 있다고 합니다.
- 바운디드 컨텍스트(Bounded Context)
- 애그리게이트(Aggregate)
- 도메인 서비스(Domain Service)
이 세 가지 개념을 제대로 이해하고 실무에 적용할 수 있다면, 이번 강의를 충분히 잘 소화했다고 볼 수 있지 않을까 생각합니다.
강의를 수강하면서 느낀 점
회사를 다니면서 매주 강의와 미션을 수행하는 것이 생각보다 쉽지 않았습니다. 특히, 야근이 잦은 환경에서는 시간을 쪼개어 학습해야 하는 상황이 많았고, 필자 역시 그런 과정을 거치며 강의를 수강했습니다.
1~2주차 미션은 상대적으로 부담이 적었고, 체감상 8시간 이내면 수행이 가능했습니다. 그러나 3주차 이후 미션부터는 최소 8시간 이상 소요될 정도로 기술적인 고민뿐만 아니라, 비즈니스 로직을 어떻게 풀어갈지에 대한 고민이 필요했습니다.
현재까지 전체 미션의 90% 이상을 완료했지만, 마지막 단계인 “매장 식사 주문” 리팩터링 미션은 강의 기간 내에 마무리하지 못했습니다. 이 부분은 3월 내로 수행하여 늦더라도 제출할 예정입니다. (비싼 강의비만큼, 리뷰어님의 피드백을 받아야 아깝지 않다고 생각합니다. 😂)
(추가 - 2025.03.24) 마지막 단계인 “매장 식사 주문”을 하면서 애그리거트 루트에 대한 개념과 도메인간 의존성 관리에 대해 깊이 고민하면서 미션을 수행하는 과정을 거쳤습니다.
강의비가 비싼만큼 그만한 가치가 있었을까?
강의비는 약 100만원으로 비싼 편이었습니다. 하지만 그만큼 얻어가는 것이 많았고, 본인이 얼마나 적극적으로 참여했느냐에 따라 강의의 가치가 달라진다고 생각합니다.
필자가 생각하는 강의비가 아깝지 않다고 느끼는 기준은 다음과 같습니다.
-
강의에서 나온 개념(용어 및 기술적 이해도)을 최소 80% 이상 이해해야 한다. 만약 그 이하라면 반복해서 듣고, 모르는 부분은 직접 찾아보며 정리해야 한다.
-
매주 미션을 단순히 제출하는 것이 아니라, 리뷰어님의 피드백을 적극적으로 반영하고 개선해야 한다. 특히, 본인이 고민했던 흔적을 남기고, 리뷰어와 소통하는 과정에서 더 깊은 학습이 이루어진다.
-
강의 외에도 강사가 추천하는 영상, 블로그를 최소한 한 번씩은 읽고 학습해야 한다. 단순히 읽는 것에서 끝나는 것이 아니라, 해당 내용을 미션에 적용하면서 본인의 것으로 만들어야 한다.
마무리하며
이번 DDD 세레나데 7기 강의를 통해 단순히 도메인 주도 설계의 개념을 학습하는 것이 아니라, 실제 비즈니스 로직을 설계하고 리팩터링하는 경험을 할 수 있었습니다.
특히, 비즈니스 요구사항을 코드로 어떻게 풀어낼지, 어떻게 유지보수하기 좋은 설계를 할지 고민하는 과정이 인상 깊었습니다.
강의 기간 동안 배운 내용을 앞으로도 실무에서 꾸준히 적용해보고, 부족한 부분은 보완해 나가야겠다고 다짐하게 되었습니다.
DDD는 단순히 이론으로 끝나는 것이 아니라, 실무에서 적용해가며 계속 다듬어야 하는 과정이라는 점을 다시 한번 느낀 강의였습니다.
DDD를 실무에 적용하는 방식에 대한 고민
DDD 개념을 실무에서 어떻게 자연스럽게 녹여낼 수 있을지에 대한 고민도 생겼습니다. 단순히 “DDD를 도입해보자!” 라고 하는 것이 아니라,
- “우리 용어 사전과 모델링을 작성해볼까요?”
- “도메인이 파편화되어 있으니, 이번에 이벤트 스토밍을 적용해볼까요?”
이처럼 DDD 개념을 구체적인 작업으로 제안하는 방식이 더 효과적이라는 생각이 들었습니다. 특히, DDD에 익숙하지 않은 팀원들도 자연스럽게 접근하고 이해할 수 있도록 적절히 활용하는 것이 중요하다고 느꼈습니다.
리뷰어로 참여할 기회가 온다면?
다음 DDD 세레나데 8기
가 열리고, 만약 리뷰어로 참여할 기회가 생긴다면,
참여자의 입장이 아닌 리뷰어의 시각에서 배우는 점도 많을 것이라고 생각합니다.
강의를 듣고 미션을 수행하는 과정도 의미 있었지만, 다른 사람의 코드와 설계를 리뷰하고 피드백하는 과정에서도 깊은 인사이트를 얻을 수 있을 것 같습니다. 리뷰어로 참여하게 된다면, 실제 적용 사례를 다양한 시각에서 분석하며 더 깊이 있는 사고를 할 수 있는 기회가 될 것 같아 기대됩니다.