도메인이 성숙하기 전에 모듈부터 나누지 마세요
도메인 성숙도는 정책과 행동, 운영 현실을 얼마나 이해했는지에서 나옵니다. 추측을 일찍 굳히지 말고 운영에서 드러난 책임으로 모듈 경계를 정해야 합니다.
출처 및 AI 안내: 이 글은 제미니의 개발실무 유튜브를 기반으로 작성되었습니다.
gpt-5.6-sol모델을 사용해 생성·편집했습니다.
제가 도메인이 “성숙했다”고 말할 때 무엇을 뜻하느냐는 질문을 종종 받습니다. 체크리스트로 재는 공식 단계는 아닙니다. 정책과 스펙, 요구사항, 실제 동작을 우리가 얼마나 손안에 넣고 있는지에 가까운 표현입니다.
패키지 이름을 붙이고 경계를 그린 뒤 전달받은 요구사항을 전부 구현했다고 해서 도메인을 이해한 것은 아닙니다. 개발자가 비슷한 서비스를 운영해 봤다면 숨어 있는 규칙을 알아챌 가능성이 높습니다. 회사에 질문할 수 있는 도메인 전문가가 있다면 가능성은 더 높아집니다. 그렇다고 좋은 모델이 보장되지는 않습니다. 추측해야 할 부분이 줄어들 뿐입니다.
경험이 중요한 이유는 도메인이 명사보다 훨씬 크기 때문입니다. 리뷰 기능을 생각해 봅시다. 고객이 작성한 글의 권리는 누구에게 있을까요? 답글이 달린 뒤에도 수정할 수 있을까요? 답글은 몇 개까지 허용할까요? 답글에 다시 답글을 달 수 있을까요? 상품이 삭제되거나 주문이 환불되면 리뷰는 어떻게 될까요? Review라는 클래스 이름만으로는 이런 정책을 거의 설명할 수 없습니다.
도메인 성숙도는 이런 규칙을 이해하고, 코드로 구현하고, 실제 사용 속에서도 그 규칙이 어떻게 작동하는지 확인한 정도에서 나옵니다.
오픈은 끝이 아닙니다
개발자도 회사도 잘 모르는 도메인이라면 일단 만들면서 배웁니다. 개발을 시작할 때, 주요 흐름이 동작할 때, 첫 배포를 할 때마다 이해도는 올라갑니다. 그래도 그 어느 시점도 곧바로 성숙했다고 부르기는 어렵습니다.
운영을 시작하면 그림이 달라집니다. 사용자는 우리가 예상하지 않은 방식으로 서비스를 씁니다. 다이어그램에서는 A -> B -> C로 깔끔하게 끝나던 상태가 운영에서는 “C를 다시 A로 돌려주세요”라는 요청을 만납니다. 요구사항에는 그 역방향이 없었을 수 있습니다. 실제 고객에게 문제가 생기고 운영자가 수동으로 풀어야 할 때 비로소 드러납니다.
그 예외는 도메인 주변의 잡음이 아닙니다. 예외까지 도메인의 일부입니다.
저는 운영한 지 석 달 정도를 이해도가 처음 크게 올라가는 대략적인 지점으로 말하기도 합니다. 모든 서비스에 적용할 기준은 아닙니다. 고정된 기간이 아니라 실제 운영이 숨어 있던 정책을 드러냅니다. 개발 기간 자체보다 실제 사용, 장애, 수동 대응, 정책 변경을 관찰했는지가 더 강한 근거라는 뜻입니다.
기획자와 PO가 요구사항을 훌륭하게 정리해도 모든 조건을 미리 적을 수는 없습니다. 이미 현업을 아는 사람이 없다면 많은 규칙은 운영해야만 발견할 수 있습니다. 운영하면서 주의 깊게 볼수록 이 소프트웨어가 현실에서 무슨 역할을 하는지 더 정확하게 설명할 수 있습니다.
패키지 이름이 곧 모듈 경계는 아닙니다
이 차이는 코드베이스를 모듈로 분리할 때 중요합니다.
처음 요구사항에 Q&A와 리뷰가 있다고 해봅시다. 코드는 자연스럽게 qna, review 패키지로 시작합니다. 각 패키지가 제법 깔끔해지면 두 개를 도메인 모듈로 빼고 싶어집니다. 현재 디렉터리 구조만 보면 맞는 판단처럼 보입니다.
그런데 프로젝트의 목표를 나중에 제대로 알게 됐더니 커머스를 만드는 일이었습니다. Q&A와 리뷰는 상품, 고객, 구매, 재고, 운영 정책 주변에서 움직입니다. 시스템에 따라 둘은 독립된 생명주기를 가진 별도 도메인이 아니라 커머스라는 더 큰 도메인의 응집된 일부일 수 있습니다. 너무 일찍 분리하면 최초 요구사항에서 나온 단어를 단단한 의존성 경계로 굳혀버립니다.
Q&A와 리뷰를 절대 모듈로 나누면 안 된다는 뜻은 아닙니다. 제품 방향, 소유권, 변경 패턴, 재사용 필요, 운영 경험이 근거를 준다면 분리할 수 있습니다. 오늘 보이는 패키지 모양을 그 근거라고 착각하지 말자는 얘기입니다.
우리는 만들고 있는 것의 정체를 아직 모를 때가 많습니다. 회사가 처음에는 “Q&A와 리뷰만 있으면 됩니다”라고 말할 수 있습니다. 실제 제품이 커머스라면 나중에 상품, 사용자, 재고 관리, 주문 이력, 운영 기능이 붙습니다. 초기의 명사를 모두 모듈로 만들었다면 아키텍처는 비즈니스를 표현하기보다 불완전했던 요구사항의 흔적을 보존하게 됩니다.
책임이 보일 때 경계를 세웁니다
저는 바꾸기 쉬운 패키지 구조에서 시작하는 편을 선호합니다. 행동을 구현하고 책임을 읽을 수 있게 정리합니다. 어떤 개념이 함께 바뀌는지, 어떤 정책이 한 덩어리인지, 정말로 격리가 필요한 부분이 어디인지 지켜봅니다. 경계를 강제했을 때 추측을 둘러싼 어댑터만 늘어나는 것이 아니라 혼란이 줄어든다는 확신이 생기면 모듈로 옮깁니다.
모듈을 추출하기 전에 이런 질문에는 답할 수 있어야 합니다.
- 지금 보드에 올라온 기능 말고, 이 프로젝트가 만들려는 것은 무엇인가?
- 이 부분이 소유하는 정책은 무엇인가?
- 어떤 데이터와 행동이 함께 바뀌어야 하는가?
- 누가 운영하며 어떤 예외를 처리하는가?
- 독립된 생명주기가 있는가, 더 큰 기능과 함께 움직이는가?
- 물리적 경계로 어떤 의존성을 막으려는가?
답이 흐리다면 모듈보다 패키지가 저렴합니다. 아무 구조도 없다는 뜻이 아니라, 아직 배우는 동안 바꿀 여지를 남긴다는 뜻입니다.
이 글은 모듈 설계를 반대하는 이야기가 아닙니다. 경계에 걸맞은 근거를 먼저 만들자는 이야기입니다. 모듈은 제약을 걸기 때문에 유용합니다. 충분히 이해한 책임을 기준으로 건 제약은 설계를 지킵니다. 초기 추측에 건 제약은 나중에 얻은 이해를 반영하기 어렵게 만듭니다.
만들고, 배포하고, 운영하면서 관찰해야 합니다. 첫 폴더 이름이 무엇이었는지가 아니라 소프트웨어가 현실에서 어떤 역할을 하는지 물어야 합니다. 도메인 모델은 우리의 지식이 단단해지는 만큼 단단해지면 됩니다. 모델이 지식보다 먼저 완성될 필요는 없습니다.