본문은 [도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지]를 읽고 간단하게 정리한 글입니다. 필요에 따라 생략/수정된 부분이 있을 수 있으며, 내용이 추후 변경될 수 있습니다.
11.1 단일 모델의 단점
- 조회 기능을 구현하기 위해선 여러 애그리거트에서 데이터를 가져와야 하는데, 이때 조회 속도를 빠르게 만들기 위해서 여러 구현 방법을 고민해야 한다
- 예컨대 식별자를 이용해서 애그리거트를 참조하는 방식(3장)을 사용하면 즉시 로딩 등의 JPA의 쿼리 관련 최적화 기능을 사용할 수 없거나, 어떤 조회 기능을 사용하냐에 따라 같은 연관이더라도 즉시 로딩이나 지연 로딩으로 처리하는 게 다르기 떄문이다
- 이러한 고민은 시스템 상태를 변경할 때와 조회할 때 단일 도메인 모델을 사용하기 때문에 발생한다
- JPA와 같은 ORM 기법은 도메인 상태 변경 기능을 구현하는 데는 적합하지만, 조회 기능처럼 여러 애그리거트에서 데이터를 가져오는 기능을 만들 땐 고려할 게 많아서 구현을 복잡하게 만든다
- 상태 변경을 위한 모델과 조회를 위한 모델을 분리함으로써 구현 복잡도를 낮출 수 있다
11.2 CQRS
- 시스템이 제공하는 기능은 크게 상태를 변경하는 기능과 사용자 입장에서 상태 정보를 조회하는 기능 두 가지로 나눌 수 있다
- 도메인 모델 관점에서 상태 변경 기능은 주로 한 애그리거트의 상태를 변경하는 반면, 조회 기능에 필요한 데이터를 구하기 위해선 두 개 이상의 애그리거트가 필요할 때가 많다
- 상태 변경과 조회라는 두 종류의 작업을 단일 모델로 수행하면 앞서 언급한 것처럼 모델이 복잡해진다
- 단일 모델을 사용할 때 CQRS를 사용하면 이러한 복잡도를 해결할 수 있다
- CQRS는 Command Query Responsibility Segregation의 약자로 상태를 변경하는 명령(Command)을 위한 모델과 상태를 제공하는 조회(Query)를 위한 모델을 분리하는 패턴이다
- 도메인이 복잡할수록 명령 기능과 조회 기능이 다루는 데이터 범위에 차이가 나므로 CQRS는 복잡한 도메인에 적합하다
- CQRS를 사용하면 각 모델에 맞는 구현 기술을 선택할 수 있다
- 명령 모델은 객체 지향에 기반해서 도메인 모델을 구현하기에 좋은 JPA를 사용하고, 조회 모델은 SQL로 데이터를 조회할 때 좋은 MyBatis를 사용할 수 있다
- 단순히 데이터를 읽어와 조회하는 기능은 응용 로직이 복잡하지 않으므로 컨트롤러에서 바로 DAO를 호출해도 무방하다
- 데이터를 표현 영역에 전달하는 과정에서 몇 가지 로직이 필요하다면 응용 서비스를 두고 로직을 구현하면 된다
- 위 그림은 명령 모델과 조회 모델의 설계 예를 보여준다
- 명령 모델과 조회 모델 모두 주문과 관련되었지만 명령 모델은 상태를 변경하는 도메인 로직을 수행하는 데 초점을 맞춘 반면, 조회 모델은 화면에 보여줄 데이터를 조회하는 데 초점을 맞춰 설계했다
- 상태 변경을 위한 명령 모델은 객체를 기반으로, 조회 모델은 필요한 데이터를 담고 있는 데이터 타입을 이용한다
- 명령 모델과 조회 모델이 같은 기술을 사용할 수 있다 (5장 참고)
- 명령 모델과 조회 모델이 서로 다른 데이터 저장소를 사용할 수도 있다
- 명령 모델은 트랜잭션을 지원하는 RDBMS를, 조회 모델은 조회 성능이 좋은 메모리 기반 NoSQL을 사용할 수 있다
- 두 데이터 저장소 간 데이터 동기화는 이벤트를 활용해서 처리한다
- 명령 모델에서 상태를 변경하면 이에 해당하는 이벤트가 발생하고, 그 이벤트를 조회 모델에 전달해서 변경 내역을 반영한다
- 명령 모델과 조회 모델이 서로 다른 데이터 저장소를 사용할 경우 데이터 동기화 시점에 따라 구현 방식이 달라질 수 있다
- 변경 내역이 바로 조회 모델에 반영돼야 한다면 동기 이벤트와 글로벌 트랜잭션을 사용해서 실시간으로 동기화할 수 있다
- 특정 시간 안에만 조회 모델에 반영돼야 한다면 비동기로 데이터를 전송하면 된다
1) 웹과 CQRS
- 일반적인 웹 서비스는 상태를 변경하는 요청보다 상태를 조회하는 요청이 많다
- 쿼리 튜닝, 캐싱, 데이터 저장소 분리 등 조회 성능을 높이기 위한 다양한 기법을 사용하는 것은 결과적으로 CQRS를 적용하는 것과 같은 효과를 만든다
- 대규모 트래픽이 발생하는 웹 서비스는 알게 모르게 CQRS를 적용하게 되지만, 명시적으로 명령 모델과 조회 모델을 구분하지 않을 뿐이다
- 조회 속도를 높이기 위해 별도 처리를 하고 있다면 명시적으로 명령 모델과 조회 모델을 구분하는 게 좋다
- 조회 기능 때문에 명령 모델이 복잡해지는 것을 막을 수 있다
- 명령 모델에 관계없이 조회 기능에 특화된 구현 기법을 보다 쉽게 적용할 수 있다
2) CQRS 장단점
- CQRS 패턴을 적용할 때의 장점과 단점 몇가지가 있다
- 장점)
- 1) 명령 모델을 구현할 때 도메인 자체에 집중할 수 있다(=도메인 로직을 구현하는 데 집중할 수 있다)
- 2) 명령 모델에서 조회 관련 로직이 사라져 복잡도가 낮아진다
- 3) 조회 성능을 향상시키는 데 유리하다
- 4) 조회 전용 모델을 사용하므로 조회 성능을 높이기 위한 코드가 명령 모델에 영향을 주지 않는다
- 단점)
- 1) 구현해야 할 코드가 더 많다
- 단일 모델을 사용할 때 발생하는 복잡함 때문에 발생하는 구현 비용과 조회 전용 모델을 만들 때 발생하는 구현 비용 사이에서 trade-off를 잘 따져봐야 한다
- 2) 더 많은 구현 기술이 필요하다
- 1) 구현해야 할 코드가 더 많다
- 위의 장단점을 고려해서 CQRS 패턴을 도입할지 여부를 결정해야 한다
- 복잡하지 않은 도메인에 CQRS를 도입하면 두 모델을 유지하는 비용만 높아지고 얻을 수 있는 이점은 없다
- 반면 트래픽이 높은 서비스인데 단일 모델을 고집하면 유지 보수 비용이 오히려 높아지므로 CQRS 도입을 고려하자
3) CQRS 참고영상
'책 > 도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지' 카테고리의 다른 글
[도메인 주도 개발 시작하기] 10장: 이벤트 (0) | 2022.11.04 |
---|---|
[도메인 주도 개발 시작하기] 9장: 도메인 모델과 바운디드 컨텍스트 (1) | 2022.10.28 |
[도메인 주도 개발 시작하기] 8장: 애그리거트 트랜잭션 관리 (0) | 2022.10.24 |
[도메인 주도 개발 시작하기] 7장: 도메인 서비스 (0) | 2022.10.21 |
[도메인 주도 개발 시작하기] 6장: 응용 서비스와 표현 영역 (0) | 2022.10.14 |