티스토리 뷰
0. 들어가며
안녕하세요. Vertical Engineering 팀에서 백엔드 엔지니어로 일하는 이지민입니다. 지마켓에서는 지난 7월에 실시간 가격비교가 가능한 렌터카 예약 서비스를 출시했습니다.
본 글을 통해 지마켓 내에서 신규 여행 플랫폼을 구축하면서 고민했던 점들을 공유드리고자 합니다.
글은 먼저 오픈마켓에서 여행 도메인이 지닌 어려움을 소개한 후, 이를 해결하기 위해 적용한 MSA 패턴을 살펴보는 순으로 진행하겠습니다.
1. 오픈마켓에서 여행 플랫폼의 특징
오픈마켓에서 여행 상품을 판매하는 것은 배송 상품과 비교했을 때, 크게 3가지가 다릅니다.
- 예약을 대행한다.
- 예약은 시간을 사고파는 것이다.
- 여행 상품은 상품군에 따라 고객에게 제공하거나, 받아야 하는 정보의 편차가 크다.
이러한 차이점은 개발자 관점에서 다음과 같이 풀어쓸 수 있습니다.
- 여행 공급 업자의 상품을 대신 판매한다.
- 실시간성이 중요하다.
- 여행의 특수성 때문에 커머스와 구분되는 도메인 관리가 필요하다.
이러한 특수성 때문에 여행 플랫폼에는 두 가지 미션이 주어졌습니다.
- 낮은 결합도: 제휴사, 커머스 시스템과 느슨하게 연결되어야 한다.
- 높은 응집도: 여행 도메인의 특수성을 여행 플랫폼에 모아두어야 한다.
2. 지마켓 속 예약 도메인 찾아보기
오픈마켓 홈에서 여행 상품을 찾고, 예약하는 과정을 떠올려보겠습니다. 일반적으로 알고 있던 화면이, 어느 순간 여행을 위한 화면으로 바뀌어있을 거예요.
지마켓에는 여행 플랫폼 진입을 위한 경로가 곳곳에 숨어있습니다. 다음과 같은 게이트를 통해 고객은 예약 상품을 발견하게 됩니다.
고객이 여행 상품 정보를 확인하고, 예약을 마이페이지에서 살펴보기까지의 과정은 다음과 같습니다.
얼핏 보기에는 하나의 여행 플랫폼처럼 보입니다. 그러나 각 화면을 책임지는 정과 부가 나눠집니다.
이러한 전체 프로세스는 예약 플랫폼, 커머스 시스템, 여행 공급 제휴사가 서로 상호작용하며 완성합니다.
이렇게 혼란스러운 도메인 간의 관계 속에서 응집도 높은 여행 도메인 개발을 위해서, 신규 여행 플랫폼에서 MSA를 적용하게 되었습니다.
3. 애플리케이션 아키텍처 패턴
도메인의 특수성으로 인한, 여행 플랫폼의 두 가지 미션을 다시 상기해 보겠습니다.
- 낮은 결합도: 제휴사, 커머스 코어 시스템과 느슨하게 연결되어야 한다.
- 높은 응집도: 여행 도메인의 특수성을 여행 플랫폼에 모아두어야 한다.
이를 위해 여행 플랫폼에서는 MSA를 위한 대표적인 애플리케이션 아키텍처 패턴을 사용했습니다. 본 순서대로 적용 사례를 설명하겠습니다.
- Service Aggregator
- BFF (Backend for front)
- EDA (Event-driven architecture)
- ACL (Anti-corruption layer)
(1) Service Aggregator
Service Aggregator은 클라이언트로 요청을 받아서, 필요한 MSA 애플리케이션들을 호출하고 취합하는 역할을 담당합니다.
예약 플랫폼에서는 높은 응집도를 위해, 바운디드 컨텍스트를 기준으로 MSA 애플리케이션을 분리했습니다.
그리고 API를 조합하여 비즈니스를 구현해야 하는 것들은 목적에 맞는 Service Aggregator으로 분리했습니다.
각 Aggregator의 역할은 다음과 같습니다.
- Partner Service Aggregator: 제휴사 연동
- Commerce Service Aggregator: 커머스 연동을 위한 인터페이스 제공
- Front Service Aggregator: 전시 화면을 위한 프론트 서버
이를 통해 연동용 도메인과 핵심 도메인이 느슨하게 연결될 수 있었습니다.
바운디드 컨텍스트란? 도메인 모델을 구성하다 보면 각 도메인 모델과 다른 도메인 모델 간의 경계가 보이는데, 이 경계를 바운디드 컨텍스트라고 합니다.
(2) BFF (Backend for front)
BFF(Backend for front) 이란, 백엔드 애플리케이션이 프론트엔드에 표현되는 데이터를 책임지는 것을 말합니다. 그래서 프론트엔드는 UI 화면 개발에 집중할 수 있습니다.
여행 플랫폼의 일부 Service Aggregator 애플리케이션은 BFF의 역할도 담당합니다.
예를 들어, Commerce Service Aggregator는 커머스 화면에서 예약 주문을 표현할 때 필요한 데이터를 제공하는 역할을 담당합니다. 이 영역에 BFF의 개념을 적용했습니다.
이는 두 가지 목적을 이루기 위함이었습니다.
- 여행 플랫폼에서 프론트에서 사용되는 데이터를 최대한 제어할 수 있어야 한다.
- 커머스 도메인에서는 예약 주문을 위한 UI 화면 개발에 집중한다.
다음은 주문내역을 표현할 때 사용되는 API 응답 샘플입니다. 버튼의 활성화 여부, 툴팁 메시지, 버튼 링크 등을 응답으로 제공하여, 프론트엔드에 친화적인 데이터를 제공하고자 하였습니다.
(3) EDA (Event-driven architecture)
신규 예약 플랫폼에서는 도메인 간의 의존성을 줄이고, 동시 처리량을 높이기 위하여 카프카를 적극적으로 사용했습니다.
대표적인 예로는 상품 등록 워크플로우가 있습니다. 여행 도메인의 특수성으로 인해, '상품 등록'은 다른 시스템에 의존하는 여러 작업으로 구성되어 있습니다.
다음과 같은 워크플로우를 하나의 프로세스로 개발했을 때, 다음과 같은 단점이 있습니다.
- 낮은 내결함성: 한 작업에서 장애가 발생하면, 전체 장애로 전파된다. 이 경우, 트러블슈팅과 부분 복구가 어렵다.
- 확장성 저하: 각 작업 별로 리소스를 유연하게 투입할 수 없다.
- 높은 결합도: 하나의 프로세스에서 여러 도메인이 뒤섞인다.
이러한 의존성을 단순하게 하기 위해, '상품 등록'을 여러 개의 이벤트로 나누어 관리했습니다. 비즈니스 토폴로지는 다음과 같은 형태가 되었습니다.
이는 두 가지 장점을 가져다주었습니다.
- 각 애플리케이션 컨슈머에서 독자적인 비즈니스를 전개할 수 있습니다.
- 각 작업별 처리 속도를 개발자가 손쉽게 제어할 수 있습니다.
두 번째 장점은 상품 등록 워크플로우에서 큰 효과가 있었습니다. 상품 등록은 연동하는 서버에 따라 작업 단계별 처리 속도가 달랐습니다. 일부 서버는 처리율 제한 장치가 있어서 초당 처리량이 제한되었습니다. 이 경우 토픽의 파티션 수, 컨슈머의 동시성 설정 (consurrency), 컨슈머 파드 수를 조정하여 작업이 천천히 처리될 수 있도록 하였습니다.
(4) ACL (Anti-corruption layer)
신규 여행 플랫폼에서 기존 시스템의 기능을 사용해야 하지만, 두 가지 이유로 시스템 연계가 어려운 경우가 있었습니다.
1. 인프라스트럭처가 다르다.
REST API으로 기능이 제공되지 않아, 데이터베이스에 직접 접근해야 하는 경우가 있었습니다.
2. 데이터 모델이 다르다.
REST API으로 기능이 제공되지만, 클라이언트에서 너무 많은 컨텍스트를 알고 있어야 하는 경우가 있었습니다.
이러한 배경으로 기존 시스템을 쉽게 호출할 수 있도록 변환하는 코드가 필요해졌습니다. 변환 코드가 여러 애플리케이션에 전파되어, 코드가 오염되는 문제를 방지하고자, ACL을 도입하게 되었습니다.
ACL(Anti-corruption layer, 부패 방지 계층)은 신규 애플리케이션과 기존 시스템 사이에 있는 중간 계층 애플리케이션입니다. 다른 인터페이스로 구현된 시스템이 같은 언어로 통신할 수 있게, 변환해 주는 역할을 담당합니다.
이를 통해 클라이언트는 기존 시스템을 쉽게 사용할 수 있게 되었습니다. 그리고 기존 시스템 연동을 위한 변환 코드를 anti-corruption layer에 모아두어, 애플리케이션 개발과 운영이 수월해졌습니다.
4. 아쉬운 점
개발을 하면서 아쉬움 또한 있었습니다.
카프카 이벤트를 단순하게 필터링하고, 조인해야 하는 필요성이 있었습니다. 이를 해결하는 방법으로 카프카 스트림즈의 로컬 인메모리를 사용하는 대안을 검토했습니다.
그러나 카프카 스트림즈에 대한 숙련도가 부족하여, 신규 플랫폼에 빠르게 도입하기 어려웠습니다. 그래서 익숙한 솔루션인 레디스를 임시 메모리로 사용하게 되었습니다.
익숙한 방법을 사용하여, 요구사항을 빠르게 개발할 수 있었습니다. 그러나 이는 다음과 같은 사이드 이펙트를 발생시킬 수 있어서, 아쉬움이 남았습니다.
- 레디스 서버 관리 비용 증가
- 레디스 장애 시, 데이터 복구가 어려움
5. 마치며
신규 여행 플랫폼은 고객에게 새로운 여행 상품 구매 경험을 제공하는 것을 목표로 합니다. 독립적인 시스템을 구축하여 고객에게 안정적인 서비스를 제공하고자, 클라우드 네이티브 아키텍처를 지향하고 있습니다.
본 글에서는 신규 여행 플랫폼을 구축하면서, 맞닥뜨린 문제와 아키텍처 패턴 사례를 소개해 드렸습니다. 아키텍처 패턴의 장점을 위주로 설명드렸지만, 이 또한 몇 가지 단점이 존재합니다.
- 중간계층 추가로 인한 응답시간 지연
- 로직 흐름 파악이 어려움
이러한 단점이 있음에도 신규 여행 플랫폼에서는 MSA와 패턴들이 주는 이점이 컸다고 생각합니다. 복잡한 도메인 간의 관계를 단순하게 만든 것들이, 향후에 높은 생산성으로 이어질 것이라고 기대합니다.
긴 글 읽어주셔서 감사합니다.
'Backend' 카테고리의 다른 글
Gmarket Mobile Web Vip 레거시 성능 개선기 (0) | 2023.12.06 |
---|---|
Kotlin에서 리스트 추출하기 : subList, slice, take, drop (0) | 2023.11.22 |
G마켓 쿠폰적용가 도입기 - 캐시를 중심으로 (0) | 2023.08.02 |
API 메시업과 Fault Tolerance 문제 해결 전략 (1) | 2023.07.19 |
일관적인 에러응답을 달라! (1) | 2023.06.21 |