inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

CQRS와 조회 전용 저장소, 그리고 카테고리-상품 관계 고민기

최범수
1

도메인 주도 설계를 배우면서 겪은 고민

최근 도메인 주도 개발(DDD)에 관한 책을 읽으면서 여러 가지 설계에 대한 깊은 고민을 하게 되었다.
특히 관심을 끈 부분은 CQRS(Command Query Responsibility Segregation) 개념이었다. 이 글에서는 공부한 CQRS 개념과 함께, 카테고리와 상품 사이의 관계를 어떻게 효율적으로 설계할 수 있는지 정리해 보려고 한다.

 


쓰기 모델과 조회 모델을 분리한 이유

일반적인 웹 애플리케이션은 데이터베이스 하나에서 읽기 쓰기를 모두 처리한다. 이렇게 구현해도 초반에는 큰 문제없이 잘 동작하지만, 서비스가 성장하면서 읽기(조회) 트래픽이 급증하면 다음과 같은 문제가 발생할 수 있다.

이를 해결하기 위한 방법 중 하나가 CQRS 이다.

 

CQRS의 핵심 개념

CQRS 흐름

  1. 쓰기 발생: 데이터를 RDB에 저장

  2. 이벤트 또는 동기화: Kafka 등을 통해 조회 전용 저장소(ElasticSearch)에 데이터 동기화

  3. 조회 요청 처리: 조회 전용 저장소에서 빠르게 검색/조회

    이를 통해 조회 성능 향상과 시스템 부하 분산을 얻을 수 있다. 하지만 이벤트 동기화 과정에서 구현 복잡도가 늘어나고, 실시간성이 필요한 경우 동기화 지연이 단점으로 작용할 수 있다.

    간단 예시: CQRS 적용 시나리오

     

    • 상품 생성 시:

    1. 상품 정보를 RDB에 저장

    2. 이벤트를 발생 (예: "상품 생성됨")

    3. 이벤트 소비자가 ElasticSearch에 해당 상품 정보를 인덱싱

    • 사용자 조회 시:

    1. ElasticSearch에서 상품 목록 검색 -> 빠른 검색 결과 반환


카테고리와 상품 관계 설계

카테고리와 상품 간의 설계는 애플리케이션 성능, 특히 페이징 처리와 깊은 관련이 있다.
데이터 조회와 성능에 큰 영향을 미치는 두 가지 대표적인 설계 방식을 자세히 살펴보자.

 

N-1 관계 (상품 -> 카테고리 참조)

N-1 관계는 상품(Product)이 특정 카테고리(Category)를 직접 참조하는 방식이다. 일반적으로 상품이 반드시 하나의 카테고리에만 속할 때 이 방식을 사용한다.

@Entity
public class Product {
    @Id
    private Long id;

    @ManyToOne
    @JoinColumn(name = "category_id")
    private Category category;
}

 

M-N 관계 (상품 <-> 카테고리 ID로 연결)

M-N 방식은 하나의 상품이 여러 개의 카테고리에 속할 때 사용하는 구조로, 중간 테이블을 사용하여 다대다 관계를 처리한다. 특히 ID기반으로 연관관계를 표현하여 직접적인 엔티티 참조를 피하는 방식이다.

@Entity
public class Product {
    @Id
    private Long id;

    @ElementCollection
    @CollectionTable(name = "product_category", joinColumns = @JoinColumn(name = "product_id"))
    @Column(name = "category_id")
    private Set<Long> categoryIds;
}

어떤 방식을 선택해야 할까?

관계를 설계할 때는 애플리케이션의 사용 패턴과 비즈니스 요구사항을 깊게 고민해야 한다. 각각의 관계 방식은 다음과 같은 상황에 효과적이다.


 

글을 마무리하며

이 글을 작성하면서 설계 방식 하나를 선택하는 일이 얼마나 중요한 고민인지 새삼 느끼게 되었다.
이론적으로는 두 방식 모두 장단점이 있기 때문에 어느 하나가 더 우월하다 말할 수는 없겠지만, 결국 실제 서비스에서 어떤 방식이 더 효율적일지는 요구사항을 고려하여 더 효율적인 선택을 하는건 개발자의 몫인 것 같다.
앞으로도 단순히 이론에 그치지 않고 실무에서 끊임없이 고민하며 상황에 맞는 좋은 설계 방식을 찾아가야겠다는 생각이 들었으며 끝으로 이 글의 내용과 비슷한 고민을 하고 있는 사람들에게 조금이나마 도움이 되었기를 바란다.

백엔드 CQRS ManyToOne ManyToMany 조회전용저장소

답변 0