열거형의 주인은 누구인가: 도메인 모듈 의존성 설계
비즈니스 열거형은 도메인이 소유하고 스토리지는 안쪽을 의존하게 하며, 경계가 익는 동안에만 작은 공유 열거형 모듈을 두는 방법입니다.
출처 및 AI 안내: 이 글은 제미니의 개발실무 유튜브를 기반으로 작성되었습니다.
gpt-5.6-sol모델을 사용해 생성·편집했습니다.
열거형이 핵심 비즈니스 구분을 표현한다면 데이터베이스 모듈이 소유해서는 안 된다. API 요청과 영속성 엔티티가 함께 쓰는 리뷰 타입도 여전히 리뷰 개념이다. 도메인에 정의하고 주변 모듈이 그 타입을 의존하게 하면 된다.
이렇게 하면 순환 의존성이 생긴다고 걱정할 수 있다. 의존 방향을 제대로 잡았다면 순환은 생기지 않는다.
타입을 복제하기 전에 의존 그래프를 그린다
세 모듈이 있다고 해보자.
- 비즈니스 객체와 저장소 인터페이스를 가진 도메인 모듈
- JPA 엔티티와 저장소 구현체를 가진 스토리지 모듈
- 컨트롤러와 애플리케이션 조립을 맡은 실행 API 모듈
도메인은 스토리지와 API를 모두 모른다. 스토리지는 도메인 인터페이스를 구현하고 저장 데이터를 도메인 객체로 바꾸므로 도메인을 의존한다. API는 도메인을 의존하고, 애플리케이션 실행 시 구현체가 들어오도록 스토리지를 런타임 의존성으로 포함한다.
이 방향이라면 스토리지의 JPA 엔티티와 API의 요청 모델이 모두 도메인의 ReviewType을 임포트할 수 있다. 도메인에서 바깥 모듈로 돌아가는 경로가 없으므로 순환 참조가 아니다.
스토리지가 도메인을 전혀 모르게 만들려고 하면 오히려 구조가 어색해질 수 있다. 스토리지 전용 결과 객체와 열거형 표현을 만들고, 애플리케이션이 이를 소비하면서 그 타입들이 안쪽으로 침투한다. 구현체에서 도메인을 감추려다 의존 방향을 뒤집는 셈이다.
의미가 사는 곳이 열거형을 소유한다
결론은 ‘모든 열거형을 한 모듈에 둔다’가 아니다. 의미의 주인이 타입도 소유한다는 것이다. ReviewType이 리뷰의 행위를 결정한다면 리뷰 도메인에 둔다. 영속성 계층은 이름으로 저장할 수 있고, API는 외부 계약에 따라 타입을 직접 받거나 문자열을 파싱할 수 있다. 이는 표현 방식의 선택이지 소유권을 옮기는 일이 아니다.
요청 객체와 도메인 객체의 필드가 같을 필요는 없다. 다만 모든 도메인 타입의 공유를 피하려고 변환 코드를 늘리는 것도 실질적인 경계를 만들지 못할 수 있다. 외부 스펙이 별도 표현을 요구할 때 요청 타입을 나누고, 단지 컨트롤러를 지난다는 이유만으로 분리하지 않는다.
도메인 모듈이 아직 이르면 임시 선택을 한다
초기에는 더 까다로운 구조가 있을 수 있다. API 모듈 안에 컨트롤러와 초기 비즈니스 코드가 함께 있고, 스토리지만 분리된 상태다. 아직 도메인을 독립 모듈로 뺄 만큼 모델이 성숙하지 않았다. 열거형 하나를 쓰기 위해 스토리지가 API 전체를 의존하면 필요 이상으로 많은 것을 알게 된다. 그렇다고 미성숙한 도메인을 서둘러 모듈로 만들면 잘못된 경계를 굳힐 수 있다.
이때는 작은 공유 열거형 모듈을 징검다리로 둘 수 있다. API와 스토리지가 모두 이 모듈만 의존한다. 관련 열거형이 잠시 흩어진다는 비용은 있지만, 이미 도메인 경계를 다 안다는 척하는 것보다 나을 수 있다.
비즈니스 지식이 쌓이면 열거형도 다른 개념과 함께 도메인 모듈로 옮긴다. 답은 현재 모듈 구조, 모델의 성숙도, 분리 목적에 따라 달라진다.
유행하는 모듈 개수보다 깨끗한 의존 방향이 중요하다. 도메인 경계가 있다면 비즈니스 열거형을 그 안에 둔다. 아직 없다면 꼭 필요한 공유 타입만 격리하고, 도메인이 자연스럽게 드러날 여지를 남긴다.