Article/도메인 주도 설계 이해하기

도메인 서비스 - DDD의 적용, JPA 엔티티와의 비교

조금씩 차근차근 2025. 4. 3. 23:34

도메인 서비스란?

  • 서로 다른 애그리거트간, 협력을 중재하는 객체이다.
  • 보통 싱글톤으로, Pure Fabrication 형태를 띄며 정의된다.
  • 도메인 서비스의 개념 자체는 매우 단순하다.
    • 우리가 쉽게 만들어 쓰는, 애플리케이션 서비스와 별 차이가 없어 보인다

도메인 서비스, 그럼 스프링 빈으로 사용해도 되나?

  • 가능하다.
  • 스프링의 빈(Bean) 관리 메커니즘을 활용하여 싱글톤 객체로 등록해두면 편리하게 재사용할 수 있다.
  • 다만 애플리케이션 레이어(서비스 레이어)와 명확히 구분할 필요가 있다.
  • 단순히 스프링 빈으로 등록했다고 해서 인프라 계층 로직을 무조건 포함해야 하는 것은 아니다.

그럼 도메인 서비스가 스프링 컨테이너에 의해 생성되는데, 인프라 로직에 종속된거 아닌가?

  • 실제 인프라 로직은, 선언한 빈을 통해 바이트 코드로 구현된다.
    • 실제 코드 영역엔 침투하지 않고, 외부에서 어노테이션 형태로 바이트코드를 생성하기 위해서만 사용된다.
    • 따라서, 도메인 서비스 코드의 본질(비즈니스 로직 실행)에 영향을 주지 않는다.
  • 비즈니스 로직, 애플리케이션 로직과 인프라 로직의 분리가 코드의 문법으로 분리되었다! 라고 볼 수 있다.

JPA 엔티티는 그럼 왜 논란이 생기는거지?

우리는 변경에 유연한 설계를 추구해야 한다.
DDD의 원래 목적은, “소프트웨어의 복잡성을 낮추는 것” 이다.
변경되는 이유가, 유일해야 한다는 것이다.

하지만, 엔티티의 설계에는 다양한 접근 방법이 있다.

  • 마이바티스 - SQL 주도 설계 선호
    • 개발자가 직접 SQL을 작성하고, 이를 바탕으로 객체를 매핑하기에 자유도가 높다.
  • JDBC - 단순한 객체 주도 설계
    • 좀 더 개발자의 자유도 높다.
    • 도메인 엔티티와 DAO용 엔티티의 분리가 용이해진다.
  • JPA - 도메인 객체 주도 설계
    • 자유도는 낮지만, 기본 구현된 기능 활용

우리는 도메인 로직을 변경한다면, 한가지 이유로만 변경하고 싶다.
그렇기에, JPA 엔티티와 도메인 엔티티를 분리하고 싶어 하는 것이다.

참고로 필자는, 어노테이션은 핵심 비즈니스 로직에 영향을 주는 코드가 아니라고 생각하기 때문에, 도메인 엔티티와 JPA 엔티티를 분리할 필요성을 못느끼고 있다.
DDD의 목적을 다시한번 생각해보자.
우리는 “소프트웨어의 복잡성을 다루기” 위해, DDD를 적용하고 따르는 것이다.
논리적으로 구분된 위치에서 동작한다면, 굳이 생산성 트레이드오프를 버려가면서 도메인 엔티티와 JPA 엔티티를 분리해야 할까?
그럴 바에는, Spring Data JDBC 라는 더욱 훌륭한 도구를 선택하는 것이 옳다고 생각한다.
JPA 를 두고 Assembler 와 Mapper 를 다시 구현하는 것은, JPA의 수많은 기능을 포기하는 아쉬운 선택이라고 생각한다.

따라서, 해당 부분은 프로젝트를 함께 진행하는 팀원과 함께, Ground Rule 로써 결정하는 것이 옳다고 생각한다.

  • 읽기 쉬운 코드
    • 비즈니스 로직과, 애플리케이션 로직, UI로직, 인프라 로직의 논리적 분리
    • 비즈니스 로직은 비즈니스 로직에 집중하도록

그럼 도메인 서비스는 어디에 두는게 좋은가? - DDD 패키지 구조

 

참고 1: https://github.com/citerus/dddsample-core

참고 2: https://github.com/jasontaylordev/CleanArchitecture