새로운 프로젝트를 진행하며 CQRS 패턴을 사용하게 되었다.
Command Query Responsibility Segregation의 약어인데,
Command(변경) Query(조회) / Responsibility(역할) Segregation(분리)로 나눠서 보면 이해가 쉽다.
"변경 역할을 수행하는 구성요소와 조회 역할을 수행하는 구성요소를 분리하는 패턴"이라고 한다.
어떤 경우에 어떻게 사용하고, 어떤 효과가 있는지 알아보자.
왜 사용하는가?
일반적인 웹서비스의 기능은 CRUD(Create, Read, Update, Delete)이며, 도메인을 정의해놓고 변경, 조회 작업을 모두 수행한다. 간단한 기능에는 적합하지만, 서비스가 복잡해질수록 다양한 요구가 생기며, 변경 역할과 조회 역할은 다른 성격을 띄게 되어 분리의 필요성이 커진다.
ex) 홈페이지에 카테고리별 인기글을 노출시키고 싶다면?
-> 카테고리, 게시글이라는 도메인이 존재한다고 하면, 카테고리로 묶은 뒤 조회수로 정렬하여 가져와야 할 것이다. 이런 작업들이 여러 도메인에 걸쳐 전시 조회를 위해 존재한다!
즉, UX나 비즈니스 요구사항이 복잡해져 데이터를 관리하는 역할과 데이터를 조회하여 보여주는 역할이 구분되어야 할 때 CQRS 아키텍쳐를 고려해보면 좋을 것 같다. 조회 역할만 분리 시 조회 성능을 높일 수 있다.
어떻게 적용할까?
그렇다면 기존의 시스템에서 조회와 변경이라는 역할을 어떻게 분리해낼 수 있을까?
생각할 부분이 여러가지가 있지만, 우선 프로세스와 DB 관점에서 카테고리별 인기글이라는 기능에 대하여 조회와 변경 역할을 분리한다고 생각해보자.
프로세스와 DB
1. 같은 프로세스, 같은 DB
변경과 조회의 역할을 코드 수준에서만 분리하는 방법이다. 가장 간단하며, 구현하기 쉬우나 코드 상의 분리만 일어날 뿐 실제 변화는 거의 없다.
2. 같은 프로세스, 같은 DB(다른 테이블)
변경과 조회의 역할을 코드 수준에서 분리하고, 데이터 수준에서는 같은 DB 내의 테이블만 변경하는 방법이다. 명령 역할에서 데이터 변경 시 해당 변경을 [카테고리별 인기글] 테이블에도 반영해주며, 조회 역할은 카테고리별 인기글 테이블만 조회한다.
3. 같은 프로세스, 다른 DB : 레디스 사용
조회 역할을 위한 [카테고리별 인기글]을 별도 DB로 분리한다.(Redis를 사용하면 조회 기능을 향상시킬 수 있다.) 명령 역할에서 게시글이나 카테고리에 변경을 수행했을 때, 해당 변경 내용을 [카테고리별 인기글]을 가지고 있는 DB에 전파해주어야 한다. 변경 전파에 관한 내용은 더 아래에서 살펴보기로 하자.
4. 다른 프로세스, 다른 DB
마이크로서비스와 같이 코드, 데이터 단에서 별도의 서비스로 분리하는 방법이다.
도메인 변경 내용 전파
변경 역할을 하는 프로세스와 조회 역할을 하는 프로세스가 다른 DB를 사용하는 경우, 변경 역할 DB(게시글, 카테고리)의 변경 내용을 조회 역할 DB에 전파해야 한다. 유실되어도 되는 데이터인지, 기대 전송 속도가 얼마나 되는지에 따라 알맞게 사용하면 된다.
1. 직접 전파
2. 변경사항 발생 시 변경 내용을 DB에 저장하고, 전파기가 변경내역을 읽고 전파
3. CDC(Change Data Capture) 활용
데이터 구조
조회 역할을 하는 DB쪽의 도메인 설계는 어떻게 할까?
1. 변경 역할 DB의 도메인과 비슷하게 설계한다.
2. 조회가 들어오는 Query를 거의 그대로 저장한다.
이건 아직 어떻게 할지 모르겠다. 2번으로 해야할 것 같긴 한데 더 찾아봐야지. (좋은 자료 있으면 추천 부탁드립니다..)
참고 자료 :
https://www.youtube.com/watch?v=xf0kXMTFJm8&t=549s
https://www.youtube.com/watch?v=38cmd_fYwQk
https://www.youtube.com/watch?v=fg5xbs59Lro