● API Composition 패턴
• API Composition은 클라이언트에서 하나의 API만을 호출해서 잘게 쪼개진 API들의 응답을 모아서 보내주는 것이다.
• 클라이언트에서 API Composer(조합기)로 요청을 하면 API Composer에서 각각의 마이크로 서비스에 필요한 요청을 보내고, 응답값을 메모리에서 조인해 클라이언트에 반환한다.
• 장점 : 클라이언트 입장에서 간단하게 필요한 데이터를 쿼리 할 수 있다
• 단점 : 인메모리 조인이기 때문에 대용량 데이터 조회 시 비효율적일 수 있다.
• 보통 대용량 데이터 조회 시에는 API Composition보다는 CQRS Pattern을 사용하는 것 같다.
• API조합기는 Client단에 만들 수 있다. ajax()로 화면 partial refresh를 하는 방법이 대표적인 예이다.
예를들면, 주문현황 화면은 주문서비스(음식점명 리턴), 주방서비스(조리상태 리턴), 배달서비스(배달상태, 배달예정시간 리턴), 회계서비스(결제상태 리턴)를 ajax의 non-blocking방식으로 호출하여 결과가 리턴되면 화면의 해당 영역만 바꾸는 방식을 사용합한다.
• API조합기는 서버단에 만들 수도 있다. API Gateway나 BFF(Backend For Frontend)로 구현한다.
이 패턴은 서버단의 API조합기가 각 서비스의 API를 호출하여 받은 결과를 조합하여 Client에 반환한다.
위 Client단에 위치할 때는 Client와 Server간에 트래픽이 4번 이었는데, Server단에 위치하면 1번으로 줄어든다.
• API조합기를 Client에 둘것인가? Server에 둘것인가 ?
○ Client(웹브라우저, 모바일단말기)가 서버와 같은 네트워크 Zone (예: 인트라넷) => Client단
○ Client가 서버와 다른 네트워크 zone(예: 모바일단말기같이 방화벽 외부)이거나 Client-server간 네트워크가 느림
- 취합로직이 복잡하면 BFF 어플리케이션 개발
- 비즈니스로직 없이 기계적 취합만 하면 되면 API Gateway
• BFF는 마이크로서비스별 1개가 아니라 Client type(웹, 모바일, 3rd party 등)별, 최상위 또는 차상위 domain별 등 적절한 기준별로 만든다.
● CQRS(Command Query Responsibility Segregation) 패턴
• 데이터를 읽어오는 작업과 데이터를 변경하는 작업의 책임을 분리하는 것이다.
• Command(Create, Update, Delete) 와 Query(Read)를 분리
CQRS의 장점
• 독립적인 스케일링 : CQRS는 읽기와 쓰기 각각에 대해 독립적으로 스케일링을 하는 것을 가능하게 해준다. 이는 Lock 경합이 훨씬 더 적게 발생게 된다.
• 최적화된 데이터 스키마 : 읽기 저장소는 쿼리에 최적화된 스키마를 사용할 수 있고, 쓰기 저장소는 쓰기에 최적화된 스키마를 사용할 수 있다.
• 보안 : 읽기와 쓰기를 분리함으로써 보안 관리가 용이해진다.
• 관심사 분리 : 읽기와 쓰기에 대한 관심사 분리는, 시스템의 유지 보수를 더 쉽게 해 주고 유연하게 해 준다. 대부분의 복잡한 비즈니스 로직은 쓰기 모델에 들어가고, 상대적으로 읽기 모델은 간단해진다.
• 간단한 쿼리 : 읽기 저장소의 materialized view를 통해, 복잡한 조인문을 사용하지 않을 수 있다.
CQRS를 구현하기 위해선 다음과 같은 어려움이 있다.
• 복잡성 : CQRS의 기본 아이디어는 간단하다. 하지만 이 패턴은 만약 이벤트 소싱 패턴을 포함할 경우, 더 복잡해질 수 있다.
• 메세징 : 메세징이 CQRS의 필수요소는 아니지만, 명령(Command)을 수행하고 업데이트 이벤트를 발행하는 것이 보편적인 사용법이다. 이 경우 어플리케이션은 반드시 메세지 실패나 중복 메세지와 같은 것들에 대한 처리를 해야 한다.
• 데이터 일관성 : 만약 읽기/쓰기 저장소가 분리된다면, 읽기 데이터가 최신의 데이터가 아닐 수도 있다. 읽기 저장소에는 쓰기 저장소의 변경 사항들이 반영되어야 하는데, 이에는 딜레이가 생기기 때문이다.
CQRS는 다음과 같은 경우에 사용을 고려해볼 수 있다.
• 많은 사용자가 동일한 데이터에 병렬로 액세스하는 도메인. CQRS는 도메인 레벨에서의 병합 충돌을 최소화할 수 있도록 충분히 세분화된 명령(Command)를 정의하는 것을 가능하게 해 준다.
• 복잡한 프로세스나 도메인 모델을 통해 가이드되는 작업 기반 사용자 인터페이스. 쓰기 모델은 비즈니스 로직, 유효성 검사 등을 모두 가진 완전한 명령(Command) 처리 기능을 가진다. 쓰기 모델은 관련된 객체들의 집합을 하나의 단위(DDD에서의 aggregate)로 다룰 수 있고, 이 객체들이 항상 일관된 상태를 가지도록 보장할 수 있다. 읽기 모델의 경우 비즈니스 로직이나 유효성 검사 같은 것 없이, 오직 DTO만 반환한다. 읽기 모델은 최종적으로 쓰기 모델과 일치하게 된다. (딜레이는 있을 수 있음)
• 데이터 읽기의 성능이 데이터 쓰기의 성능과 별도로 조정이 가능해야 할 때. 특히 읽기의 수가 쓰기의 수보다 훨씬 많을 때. 이 경우, 읽기 모델은 스케일 아웃을 하고, 쓰기 모델은 적은 수로 유지할 수 있다. 적은 수의 쓰기 모델은 병향 충돌의 가능성을 최소화해준다.
• 한 팀은 쓰기 모델에 대한 복잡한 도메인 모델에만 집중해야 하고, 다른 한 팀은 사용자 인터페이스에 대한 읽기 모델에만 집중해야 할 때
• 시스템이 시간이 지남에 따라 계속해서 진화하고, 여러 버전을 가질 수 있으며, 정기적으로 바뀔 수 있는 경우
• 다른 시스템과의 통합, 특히 이벤트 소싱과 결합할 때. 서브시스템의 일시적 장애가 다른 시스템에 영향을 줘선 안된다.
다음과 같은 경우에는 CQRS 사용이 권장되지 않는다.
• 도메인과 비즈니스 로직이 간단할 때
• 단순한 CRUD일 때
참고 및 사진 출처
https://happycloud-lee.tistory.com/154
https://logical-code.tistory.com/211
https://medium.com/@knoldus/read-model-and-write-model-cqrs-reactive-architecture-3463b5dee9b3
https://chacha95.github.io/2022-03-23-cqrs/
https://mslim8803.tistory.com/m/73
'MSA' 카테고리의 다른 글
MSA 프로젝트 중 MVP를 만들었던 이유(feat. 일정 딜레이) (0) | 2022.11.23 |
---|---|
CQRS 구현 - Redis, Kafka 적용 (0) | 2022.11.23 |
MSA, Software Architecture : Layered Architecture (0) | 2022.10.19 |
MSA 설계, DDD(Domain Driven Design), Event Storming (0) | 2022.10.14 |
애자일(Agile), 스크럼(Scrum), 스프린트(Sprint) (0) | 2022.09.30 |
댓글