CQRS 구현
구현1: 같은 프로세스, 같은 DB
코드 수준에서만 명령과 쿼리가 분리가 된다.
데이터 수준에서는 분리하지 않는다.
가장 단순하고 명령/쿼리 동일 데이터 보장된다. (트랜잭션 처리 쉬움)
구현2: 같은 프로세스, 같은 DB, 다른 테이블
명령과 쿼리가 코드, 데이터 수준에서 분리된다.
별도의 테이블을 가지고 구현하기 때문에 같은 DB를 사용한다.
- 쿼리 전용 테이블 사용
- 예) 최근 조회수 많은 글 목록
- 명령이 쿼리 전용 데이터 변경 유발
구현3: 같은 프로세스, 다른 DB
상품 목록을 Redis와 같은 저장소에 캐싱하고 쿼리 모델은 Redis를 사용한다.
명령이 데이터를 변경하면 변경 내역을 쿼리 쪽 DB에 전달하게 된다.
구현4: 다른 프로세스, 다른 DB
명령이 데이터를 변경하면 변경 내역을 쿼리 쪽 DB에 전달
다른 DB로 변경 전파
왼쪽부터 방법 1, 2, 3에 해당하는 그림이다.
방법1) 명령이 직접 쿼리 디비를 수정하는 방식
-
구현이 단순한게 장점이다.
-
카프카와 같은 메시징 수단을 이용해서 전달하는 변형도 있다.
-
데이터 유실 가능성이 있다. 쿼리 디비나 메시징이 일시적으로 문제가 발생하게 되면 쿼리 디비를 반영해야 할 데이터가 유실될 수 있다.
방법2) 변경 내역을 기록하고 별도의 전파기를 이용해 변경 내용 전달
-
별도 테이블에 변경 내역 저장 → 한 트랜잭션으로 처리되기 때문에 변경 내역이 유실되지 않음
-
전파기를 따로 구현해야 한다는 부담이 생긴다.
-
이 방법도 중간에 메시징을 두는 변형이 있다.
방법3) 디비가 제공하는 CDC 사용
디비에 바이너리 로그를 읽어서 변경 데이터를 확인하고
변경된 데이터를 쿼리에 전달하는 방식
두번째 방법과 비슷한데 명령쪽 코드에서 변경 내용을 저장하지 않아도 되기 때문에
명령 코드가 단순해진다는 장점이 있다.
메시징을 중간에 두는 변형이 존재한다.
다른 DB 사용시 주의 사항
- 데이터 유실
- 유실 허용 여부에 따라 DB 트랜잭션 범위 중요
-
허용 가능 지연 시간
- 중복 전달