[마이크로서비스패턴] 7장 마이크로서비스 쿼리 구현
7장. 마이크로서비스 쿼리 구현
7장 핵심내용
- 마이크로서비스 아키텍처에서 데이터를 쿼리하기 어려운 이유
- API 조합 패턴 응용 쿼리 구현
- CQRS 패턴 응용 쿼리 구현
1. API 조합 패턴 응용 쿼리
여러 서비스에 있는 데이터를 API를 통해 조회하고 그 결과를 조합하여 쿼리를 구현
- API 조합기 : 프로바이더 서비스를 쿼리하여 데이터 조회
- 클라이언트, API 게이트웨이, BFF(Backend For Frontend)
- 프로바이더 서비스 : 최종 결과로 반환할 데이터의 일부를 갖고 있는 서비슨
API 조합 패턴 이슈
- 누가 API 조합기 역할?
- 서비스 클라이언트 : 방화벽 외부 존재, 네트워크 느릴 경우 비실용적
- API 게이트웨이
- 스탠드얼론 서비스
- 효율적 취합 방법
- 리액티브 프로그래밍 모델 사용
API 조합 패턴 장단점
장점 : 쉽고 단순하게 쿼리 작업 구현
단점
- 오버헤드 증가
- 가용성 저하 우려
- 개선 방안 2가지
- 캐시 활용 : 프로바이더 서비스 이용 불가 시 API 조합기 내 캐시 반환
- 미완성된 데이터 반환
- 개선 방안 2가지
- 데이터 일관성 결여
2. CQRS 패턴
여러 서비스에 있는 데이터를 가져오는 쿼리는 이벤트를 이용하여 해당 서비스의 데이터를 복제한 읽기 전용 뷰를 유지
CQRS 필요성
여러 서비스 쿼리
복잡한 조건의 데이터 조회 시 API 조합기는?
- API 조합기로 데이터를 인메모리 조인 : 비효율적
- 필터링 대상 데이터 조회 후 그 외 필요한 데이터 제공 서비스에 요청 : 프로바이더 서비스가 대량 조회 API를 제공할 경우에만 현실성 있음. 데이터 하나씩 요청하는 것은 과도한 네트워크 트래픽 유발로 비효율적
단일 서비스 쿼리
- 서비스 DB가 효율적인 쿼리 미지원
- 지도 관련 쿼리는 일부 DB에서 적합 => 지원되지 않는 경우 쿼리 복잡해짐
- 관심사의 분리
- 데이터가 필요한 팀에서 쿼리를 구현하는 것이 적합
CQRS 장단점
장점
- 효율적인 쿼리 가능
- 다양한 쿼리 효율적 구현
- 이벤트 소싱 애플리케이션에서 쿼리 가능
- 관심사 분리
단점
- 복잡한 아키텍처
- 복제 시차 처리
- 커맨드/쿼리 양쪽 API가 클라이언트에 버전 정보를 전달해서 데이터 분간하도록 함.클라이언트는 최신 데이터 받을 때 까지 쿼리 쪽 뷰를 계속 폴링
- 커맨드 반환 데이터에 변경 내용 포함. UI에서 처리
가능한 한 API 조합 패턴을 사용하고, 꼭 필요한 경우에 한 하여 CQRS 사용
3. CQRS 뷰 설계
DB 선택
SQL vs NoSQL
~가 필요하면 | ~를 사용한다 | 예시 |
---|---|---|
JSON 객체를 PK로 검색 | 문서형 스토어(MongoDB, DynamoDB), 키-값 스토어(redis) | 고객별 MongoDB 문서로 주문 이력 관리 |
쿼리 기반 JSON 객체 검색 | 문서형 스토어 | MongoDB, DynamoDB로 고객 뷰 구현 |
텍스트 쿼리 | 텍스트 검색 엔진(es) | 주문별 일래스틱서치 문서로 주문 텍스트 검색 구현 |
그래프 쿼리 | 그래프 DB(Neo4j) | 고객, 주문, 기타 데이터의 그래프로 부정 탐지 구현 |
전통적인 SQL 리포팅/BI | 관계형 DB | 표준 비즈니스 리포트 및 분석 |
데이터 접근 모듈 설계
- 동시성 처리 : 뷰가 여러 종류의 애그리거트가 발행한 이벤트 구독 시 여러 이벤트 핸들러가 동일 레코드에 접근해 업데이트할 가능성 존재. -> 낙관적 잠금 or 비관적 잠금 둘 중 하나 사용
- 멱등한 이벤트 핸들러 : 멱등한 이벤트 처리. 이로 인해 최악의 경우 일시적으로 뷰 데이터 동기화되지 않을 수 있음.
- 최종 일관된 뷰 사용 : 커맨드 쪽 작업으로 인한 이벤트 ID 토큰 반환. 클라이언트는 쿼리에 해당 토큰을 보내 뷰 업데이트 여부 확인 가능. (클라이언트 단의 로직 추가… : FE/BE 나뉜 상황에서 이런 요청을 하는 것이 과연 가능할까??)
CQRS 뷰 추가 및 업데이트
- 아카이빙된 이벤트 이용 CQRS 뷰 구축 : 메시지 영구 저장 불가. AWS S3, Apache Spark 등을 통한 아카이빙 데이터 활용.
- CQRS 뷰 단계적 구축 : 애그리거트 인스턴스의 스냅샷 활용
4. CQRS 뷰 구현 : AWS Dynamo DB 응용
AWS Dynamo DB : NoSQL DB. 테이블의 처리 능력을 동적으로 가감 가능. JSON 객체와 같이 이름-값 쌍이 포함된 테이블로 구성.
EventHandler + Query + DAO + DB 테이블로 구성.
동시성 처리, 업데이트의 멱등성을 보장하기위해 DAO 로직이 복잡함. 업데이트의 멱등성은 event ID 값이 최신인지 확인하는 로직을 추가함으로써 해결.
마치며
- 조회 쿼리 구현 방식 : API 조합, CQRS 패턴
- API 조합 패턴이 구현 간단하기 때문에 가능한 한 많이 사용 : but, 인메모리 조인으로 비효율성 존재
- CQRS : 뷰 전용 DB 쿼리. 구현 복잡도는 높은 편
- 중복 이벤트 솎아내기, 동시 업데이트 처리 기능 필수