SW/마이크로서비스

마이크로 서비스 : 명령 조회 책임 분리 아키텍처 : 개념, 정의, 개요

얇은생각 2020. 5. 9. 19:30
반응형

CQRS(Command Query Responsibility Segregation : 명령 조회 책임 분리

서비스의 성능향상을 위해 서비스 Instance를 Scale Out하여 여러 개로 실행한 경우에 데이터 읽기/업데이트 작업으로 인한 리소스 교착 상태가 발생할 수가 있습니다. CQRS 패턴이라고 합니다. Command Query Responsibility Segregation, 명령 조회 책임 분리 패턴입니다.

CQRS는 기존의 일반적인 개념이었던 동일한 저장소에 데이터를 넣고, 입력/수정/삭제/조회하는 방식에 도전하는 흥미로운 패러다임을 도입하고 있습니다. 일반적으로 사용자의 비즈니스 요청은 시스템 상태를 변경하는 명령과 시스템의 상태를 가져오는 조회의 두 부분으로 크게 나눌 수 있습니다.

사실 이러한 두 가지 요청 중 비즈니스에서 많이 쓰이는 부분은 상태를 조회하는 부분입니다. 즉 입력, 수정, 삭제가 조회보다 적게 쓰이고, 조회의 요청이 훨씬 많이 사용됩니다. 그런데 이렇게 서비스 내에 모든 기능을 넣어 두면, 조회 요청 빈도가 증가함에 따라 모든 기능을 같이 확장해야 합니다. 이런 방식은 효율적이지 않습니다.

따라서 이렇게 하나의 저장소에 쓰기 모델과 읽기 모델을 분리하는 방식으로 변화시키면서, 쓰기 서비스와 조회서비스를 분리할 수 있습니다. 더 나아가서 아예 물리적으로 쓰기 트랜잭션용 저장소와 쿼리용 조회 저장소를 따로 준비할 수 있습니다. 이렇게 쓰기와 조회의 전략을 각각 분리하면 쓰기 시스템의 부하를 줄입니다. 또, 대기 시간을 줄이는 등 이점을 가져올 수 있습니다.

 

마이크로 서비스 : 명령 조회 책임 분리 아키텍처 : 개념, 정의, 개요

 

마이크로서비스를 명령 측면과 쿼리 측면의 두 부분으로 나눕니다. 명령 측면 마이크로서비스는 CreateOrderDelete 처리를 수행합니다. 저장소로 쓰기에 최적화된 관계형 데이터베이스를 사용합니다. 프로그램언어도 로직을 구현하기 좋은 Java 언어를 사용합니다.

반면에 쿼리 측면의 마이크로서비스는 조회성능이 높은 몽고디비나 일레스틱서치와 같은 No-sql DB를 사용합니다. 그리고 프로그램언어도 조회를 간단하게 구현할수 있는 Node.js등을 사용합니다. 그리고 조회서비스는 사용량이 많기 때문에 Scale Out하여 Instance를 증가시켜 놓을 수 있습니다.

이런 구조에서는 쓰기 서비스가 사용되는 시점에 조회서비스의 데이터와 일관성이 깨지게 됩니다. 따라서 이때 데이터 일관성 유지를 위한 이벤트 주도 아키텍처가 등장합니다. 쓰기 서비스는 저장소에 데이터를 쓰면서 저장한 내역이 담긴 이벤트를 발생시켜서 메시지브로커에 전달합니다.

조회 서비스는 이러한 메시지 브로커의 이벤트를 보고 있다가 이벤트데이터를 가져와 자신의 저장소를 최신상태로 동기화 시켜줍니다. 물론 쓰기 서비스에 데이터가 들어간 즉시 읽기 서비스의 데이터가 일치할 수 없습니다. 시간적 텀이 있을 수 있지만 어느 시점이 되면 결과적으로 일치하게 됩니다. 이런 과정을 결과적 일관성, Eventual Consistency라고 말합니다.

이벤트 주도 아키텍처는 이벤트를 사용하여 정보를 전달하고, 마이크로서비스 간의 결합도를 낮게 하여 그로 인해 유연성과 확장성을 높일 수 있습니다. 그리고 CQRS의 데이터 일관성을 위해서도 사용되었습니다. 다음과 같이 이벤트 자체를 정보를 전달하는 데만 사용하지 않고 상태를 저장하는 방식으로 사용할 수가 있습니다.

이벤트 소싱이라고 하는 기법입니다. 보통 쓰기 서비스에서 객체모델을 관계형 모델로 변경하기 위해서는 쿼리라는 질의어로 변환시키는 과정이 필요합니다. 이벤트 소싱에서는 관계형 모델로 변환하지 않고 이벤트 자체를 순차적으로 그 상태를 포함하여 저장합니다. 훨씬 쓰기 속도가 빠르게 됩니다.

이벤트 아이디가 있고, 어떠한 상태인지, 어떠한 엔티티의 이벤트인지 그리고 그 데이터의 내용이 Json 형태로 그대로 들어갑니다. 이렇게 저장되고 그대로 또 메시지 형태로 메시지 브로커에 발행됩니다. 그럼 조회서비스는 이벤트를 순차적으로 재생시켜 현재 시점의 객체를 생성합니다. 또한 특정 시점의 상태가 필요하면 재현할 수도 있습니다.

이벤트 소싱은 모든 쓰기를 이벤트로 전환해서 별도의 이벤트 스트림으로 스트림 저장소에 저장하는 방식입니다. 이벤트 스트림 저장소는 오로지 추가만 가능하게끔 해서 계속 이벤트들이 쌓이게 만듭니다. 실제로 필요한 데이터를 구체화시키는 시점에서는 그때까지 축적된 데이터를 바탕으로 작성하게 합니다.

각각의 이벤트는 딱 한 가지 액티비티에만 집중하게 되어 있습니다. 아무리 복잡한 Biz Logic이라 하더라도 굉장히 간단하게 만들 수 있습니다. 특히 쓰기 퍼포먼스 측면에서 강점을 지니며 CQRS와 같이 자주 사용됩니다.

반응형