[Spring] Query&Command

황성현·2025년 10월 25일

Spring Boot

목록 보기
3/3

1. DDD의 기본 관점

  • 기존 구조: DB 테이블 기준으로 서비스가 나눠짐.
  • DDD: 도메인이 맡은 역할을 기준으로 서비스와 엔티티가 나눠져야 함.
    • 예: 커뮤니티 도메인 → 질문, 답변, 게시글 등으로 각각 역할/엔티티/서비스 분리.
    • 그 후 FACADE에서 이들을 조합.

2. 현재 문제 상황

  • CourseProgress(user-course 매핑 엔티티)를 같은 방식으로 분리 시도.
  • 그런데 CourseComplexReader 안에 있는 searchMyCourse()와 신규 기능 로직이 거의 동일.
  • 문제:
    • 한 클래스(CourseComplexReader)에 합치기는 애매하다.
    • 그렇다고 분리하려니 중복되는 로직을 어디에 둬야 할지 고민.

3. 구조적 의문

  • CourseCourseTag처럼 연관은 있지만, 도메인별로 엔티티와 서비스는 나눠야 한다는 게 기본 전제.
  • 그런데 지금 CourseComplexReader는 사실상 도메인 서비스라기보다는 QueryService에 가까움.
    • 즉, Course 관련 여러 부수적인 데이터(tags, 썸네일 파일 등)를 다 조합해서 조회하는 역할.
    • 그래서 “도메인 서비스는 순수해야 한다”는 원칙이 깨지고 있음.

4. 제안하는 대안

  • Reader/Writer(Service를 단순히 조회/저장으로 나누는 구조) 대신,
    • Manager: 순수 도메인 CRUD 관리

    • QueryService(공통 조회/DTO 전용 서비스)

      로 나누는 게 더 맞아 보임.

  • Manager는 구현부가 적어 보일 수 있지만, 원래 도메인 규칙은 간결해야 하며 추후 규칙 추가될 때 늘어난다.

Comment | Reader/Writer를 CQRS로 보면? (#124)


5. 현실적인 고민

  • 이 구조로 근본적 문제를 다 해결하려면 공수가 크다.
  • 그래서 차선책으로는:
    • 기존 구조 유지
    • 다만 CourseComplexReaderQueryService 성격으로 인정하고, 신규 기능도 여기에 구현해서 중복을 줄인다

Reader/Writer를 CQRS로 보면? (#124)

  • CQRS (Command Query Responsibility Segregation) “명령(Command)”과 “조회(Query)”를 분리하는 아키텍처 패턴
    • Command(명령): 데이터 변경 작업 (등록, 수정, 삭제)
      → 주로 @Transactional
    • Query(조회): 데이터 읽기 작업 (검색, 목록, 상세 조회)
      → 주로 @Transactional(readOnly = true)

성현님도 동일하게 CQRS를 생각하고 말씀 드렸겠지만 저는 CQRS 관점에서 아래처럼 생각하고 있긴 합니다.

Writer = CommandService (CUD) (=Manager)

Reader = QueryService (R)

ComplexReader = QureyDSL… DTO 전용 QueryService 어쩌구… Reader에 너무 많은 코드가 길어지는 것을 방지하기 위함으로 유추

혹시 제가 질문 자체를 잘못 이해했다면
어떤 부분이 좀 잘못된 설계라 생각되셨는지 코드나
아니면 변경되면 이렇게 된다라는 예시 코드 있을까요?

질문 자체를 잘못 이해했을 수도 있으니 문제 있다면 말씀주세요

0개의 댓글