CQRS에 대하여

김재연·2025년 9월 14일
post-thumbnail
  • Command 와 Query 를 분리하자는 것에서 나온 개념

우아한테크코스에서 많이 배우던 것이다. 수정과 조회가 동시에 일어나면 안된다는 것, 만일 이가 일어나게 된다면 소프트웨어의 3가지 원칙 중 복잡하지 않아야 한다는 KISS 가 지켜지지 않은 것이다.

이를 명시적으로 나오게 된 개념이 바로 위와 같은 개념이다.

다음과 같이, 두개의 어플리케이션이 있고, Service Interface가 이를 Query, Command로 나누어준다.

이가 왜 필요한지, 그림으로 나타내면 다음과 같다. 동일한 Domain Model 내부에 정답인지 판단하는 것과, 랭킹 뷰를 확인하는 것이 있다. 이는 통째로 큰 Domain Model 에서 보면 위에서 언급한 3원칙이 지켜지지 않는 것이다. 이렇기 때문에 CQRS 가 필요한 것이다.

그래서, 위와 같이 되면 어떠한 단점이 존재할까?

  • 복잡성
  • 성능
  • 확장성

이 떨어지게 된다.

지금부터 하나씩 잡아보자.

  1. 복잡성, 도메인이 비대해진다.

도메인이란 곧 비즈니스이고, 이는 독립적으로 지켜져야한다. 화면딴의 변화가 발생했다고해서, 즉 Query와 관련된 변경사항이 생겨서 도메인의 변경사항이 생겨서는 안된다. 도메인이 이러한 부분을 신경쓰기 시작하면 수정사항이 굉장히 잦아지게 될 것이고, 또한, 계속된 추가/수정으로 인해도메인 자체가 더욱 비대해지게 될 것이다.

  1. 성능

대부분의 write 연산에서 우리는 일관성에 대해 많은 신경을 쓴다. 그렇기 때문에 Lock 기법을 많이 사용하는데, 문제점이 Lock 으로 인해서 Read에도 영향이 간다는 것이다. 그렇기 때문에, 이를 분리하여 둘을 독립적으로 만들고 성능을 높일 수 있다.

  1. 확장성

쓰기 작업, 읽기 작업의 비율차는 엄청나다. 그렇기 때문에, 둘의 설계에는 분명한 차이가 존재한다. 그렇기 때문에 Command,Query를 서로 분리하게되면 각각의 영역에 대한 설계를 독립적으로 진행할 수 있고, 이는 추후 확장성에도 영향을 줄 수 있다는 것을 의미하게 된다.

그래서 위에서 나왔던 구조를 CQRS 형식으로 분리하게 되면 다음과 같은 구조가 된다.

이렇게 되면 어떠한 장점이 있을까 생각해볼 때, 가장 단순하게는 서로 다른 Persistence module을 사용할 수 있다. command에는 MyBatis, Read 에는 JPA를 쓸 수 있는 것이다.

그렇게 되면 다음과 같이 구조를 변경해볼 수 있는 것이다. 이전과 다르게 DB를 나누고 Stream으로 연결해준 것을 볼 수 있다. 그렇기 때문에 각각의 Command, Query 에 더 유리한 DB를 사용할 수 있게된다.

그래서 CQRS의 장점과 단점을 정리해보면 다음과 같을 것이다.

장점

  • 도메인 로직에만 집중 가능하다
    - Command 와 Query 를 분리했기 때문에 OCP(개방 페쇠 원칙) 를 준수하는 도메인 모델을 만들 수 있다 (확장성 좋다는 이야기)
    - 결국 도메인 로직에 비즈니스 로직을 집중시킬 수 있는 것 (복잡성이 줄어들기 때문에)
  • 데이터소스의 독립적인 크기 조정이 가능하다.
    - 보통 read 와 write 의 비율은 1000 : 1 이다.
    - 그러므로 write db 가 물리적으로 나뉘어져 있다면 해당 db 인스턴스는 작게 유지하고 read db 인스턴스에 더 높은 투자를 할 수 있다.
  • 단순한 쿼리
    - Query side 에서는 Materialized View 를 이용할 수 있는데, 이를 통해서 복잡한 조인 쿼리 없이 단순한 쿼리를 이용해서 원하는 정보를 얻어올 수 있다.

단점

  • 복잡성이 올라간다.
    - 당연히 헥사고날 아키텍처와 비슷하게 분리를 진행하니 패키지가 많아지고 복잡해질 수 밖에 없는 것이다.
  • 즉시적인 일관성이 보장되지 않는다.
    - command 에 따른 data 의 무결성이 잠시동안 깨질 수 있다.
    - 이 말은 데이터의 consistency 가 항상 동일하지 않다는 것을 의미한다.
    - 하지만 최종적으로는 데이터가 맞춰질 것이니 Eventual Consistency 라고 할 수 있다.

또한 데이터에 병렬로 접근하는 경우나 read 연산이 write 연산보다 많은 경우는 CQRS 를 사용하는 것이 효과적이다.

또한 마치면서 필자는 이렇게 이야기 한다. 사실 CQRS 는 의미와 같이 Command, Query 와 연관된 기술이라고, 그렇기 때문에 Data Source, Event Sourcing 과 연관된 것이 아니라, 실제로는 도메인 로직에 조금 더 집중하기 위한, 프로그래밍의 기본원칙을 준수한 구조라고 설명하고 있다.

profile
끊임없이 '성장'하는 개발자 김재연입니다.

0개의 댓글