세션명: AWS에서 분산 디자인 패턴 구현하기
일시: 2024.05.17 13:10 ~ 13:50
장소: 1F 그랜드볼룸 101호
작성자 : Cloud Technology Center / 고준성
•
세션 신청 이유와 배우고 싶은 것
세션명으로는 어떠한 기술을 소개할지 어떠한 내용을 말할지는 확실하게 알 수 없지만,
AWS에서 분산 디자인 패턴 구현하기라는 주제만으로도 나의 흥미를 돋궜습니다.
분산 디자인 패턴 구현 세션에서는 어떠한 내용을 배울 수 있고 이 기술을 프로젝트에 어떻게 적용해볼 수 있는지 고민해볼 수 있는 재미가 있을 것 같아 신청했습니다.
•
소개
많은 현업에서 마이크로서비스 아키텍처(MSA)에 대해 관심이 많아지는 요즘 익숙한 주제일 수 있습니다. 이번 세션은 도메인 주도 개발 관련 내용을 포함하여 가상의 시나리오를 분산 디자인 패턴으로 구현하여 설명해주고 데모를 보여주는 세션입니다.
•
모놀리식 서비스
해당 세션을 진행하기 전에 하나의 예시를 들어주셨습니다. 사람들이 새 건물을 좋아하는 이유는 무엇일까요? 그 시대의 감성이 묻어나며 건물이 깨끗하고 세련되었기에 사람들이 좋아합니다. 하지만 이러한 새 건물도 시간이 지날수록 건물이 낡게 됩니다. 그래서 건물을 사용하는 사람들의 니즈에 맞추어서 내외부를 리모델링하여 사용하는 경우도 볼 수 있습니다.
우리가 하려는 서비스도 마찬가지 입니다. 처음부터 복잡할 필요는 없습니다. 간단하게 시작해서 필요한 니즈에 맞추어 늘려 나갈 필요가 있습니다. 프로젝트 시작부터 사용자의 니즈 파악이 바로 되지 않기 때문에 모놀리식 구조로 시작하는 것도 나쁘지 않다고 설명해주십니다.
설명해주신 것처럼 모놀리식 구조를 많은 곳에서 아직도 사용하고 있으며 전혀 올드하거나 나쁜 구조는 아니라고 생각합니다. 여러가지 기능을 단시간에 구현하여 테스트하고 확인해볼 수 있고 그런 과정을 최소한의 리소스로 만들어낼 수 있기 때문입니다.
•
적응형 시스템 설계
이후 모놀리식 시스템을 적응형 시스템으로 설계하여 바꾸어야 합니다. 변경되는 기능을 최소한의 비용과 리소스만으로 구축할 수 있도록 적응형 시스템으로 설계해야 합니다. 그렇게하면 서비스를 비즈니스와 기술 변화에 빠르게 적응할 수 있습니다.
이제 시작한 서비스에서 장애가 발생할 가능성은 적지만, 서비스가 성장하고 사용자가 많아지면 이야기가 달라집니다. 대규모 읽기와 쓰기로 병목 현상이 발생할 수 있으며, 그로 인한 트랜잭션으로 지연시간이 악화될 수 있습니다. 물론 기존 서비스를 Scale Up 하거나 Scale Out 하면서 증가하는 사용자를 대응할 수 있겠지만, 블랙프라이데이와 같은 거대한 행사를 진행한다면 처음 모놀리식 구조는 답이 아닐 수도 있습니다.
그러한 이유로 해당 세션에서는 분산 디자인 패턴이 위 이슈를 해결할 수 있는 하나의 아키텍처가 될 수 있을 것 같다고 소개하고 있습니다.
분산 디자인 패턴을 소개하기 위해 유니콘 리테일 서비스라는 가상의 이커머스 서비스를 만들어 해당 시나리오를 사용했습니다. 이 플랫폼에서는 유니콘을 판매하는 서비스로, 고객은 웹사이트에서 유니콘을 구매할 수 있다는 시나리오 입니다. 기능은 현재 가지고 있는 금액을 나타내는 지갑 기능과, 판매하는 유니콘 상품의 이름, 그리고 그 상품의 가격과 구매하는 버튼 기능이 있습니다.
리테일 시스템에서는 제품을 구매하면 잔액이 감소하고 구매된 제품을 예약하는 기능이 있습니다. 그리고 서비스는 계속해서 진화합니다. 새로운 비즈니스로 고객이 구매한 제품에 대한 일정 금액을 포인트로 돌려받은 충성 고객을 위한 로열티 포인트 서비스를 개발하려고 합니다. 이 때, 기존 시스템에 적용할지, 아니면 별도의 서비스로 가져갈지에 대한 고민을 시작합니다. 사실 정답은 없습니다. 전략을 고민해보고 맞는 전략으로 가야할 것입니다. 그래도 추가로 한 가지 상황을 더 추가한다면, 로열티 서비스를 오픈하고 나서 블랙프라이데이와 같은 행사가 있다고 하면 아무래도 기존 서비스에 추가하는 모놀리식 보다는 분산 디자인 패턴이 유리하다고 생각합니다. 새로운 로열티 포인트 서비스를 기존 서비스에 유연하게 테스트를 해볼 수 있으며, 새로 도입했던 로열티 시스템에 장애가 나더라도 기존 시스템에는 영향없도록 설계가 가능하기 때문입니다.
•
도메인 주도 디자인 (DDD)
분산 시스템을 도입하면 복잡해지게 됩니다. 서비스는 이미 복잡한데 어떻게 분리할 수 있고, 어떻게 분리해야할지 고민이 될테고, 업계에서는 많이 사용되는 패턴 중 하나인 Domain Driven Design(DDD)을 도입합니다. DDD를 위해 서로 다르게 불렀던 용어 등 기능 정의가 필요합니다.
그리고 바운디드 컨텍스트 형태로 서비스 설계가 필요합니다. 복잡한 시스템 내에서 경계와 범위를 정의하는 것을 말합니다. 시나리오 기준으로 본다면, 회원, 구매 부분을 리테일 컨텍스트로 나누고 구매했을 때 로열티 포인트를 지급할 수 있도록 로열티 포인트 컨텍스트를 나눌 수 있습니다. 이렇게 분리하면 컨텍스트 서로 간에는 영향을 최소화할 수 있도록 관리가 가능합니다.
•
시나리오 (바운디드 컨텍스트 내부)
유니콘 웹사이트에서 유니콘을 구매하는 시나리오는, 가장 먼저 원하는 유니콘을 고르고 구매를 결정합니다. 백엔드에서는 리테일 컨텍스트 로직을 수행하고 구매가 성공적으로 완료하게 되면 로열티 컨텍스트로 전달하여 동작하게 됩니다. 리테일 바운디드 컨텍스트와 로열티 바운디드 컨텍스트 사이에 어떠한 이벤트를 두어야 될까요? 여러 요소들을 놓치지 말고 고려해야할 것 입니다. 서비스는 어떻게 단순하게 구성할 것이며, 확정성은 어떻게 고려해야하고 그렇게 도입했을 때 성능은 어떠할 것이며 이런 부분들 하나하나를 놓쳐서는 안됩니다.
특히, 이커머스 시스템에서 결제 체크아웃 로직은 중요한 부분 중 하나입니다. 이 프로세스에서 장애가 났을 때, 가장 큰 리스크를 안는 부분은 어디일까요? 상품 구매를 위해 재고를 예약하고 잔액이 감소했는데, 재고가 없다면 고객에게 유니콘 배송을 할 수 없으니 잔액 감소 단계의 리스크가 세션에서 소개한 단계 중에선 가장 크다고 설명했습니다.
•
Saga 오케스트레이션이란?
앞서 설명한 리스크 감소를 위해 단계별 워크플로우를 관리하는 것도 중요합니다. Saga 패턴을 이용하여 각각의 서비스를 일관성있게 정합성을 맞출 수 있다고 합니다.
•
리테일 기능의 솔루션 아키텍처
Saga Orchestration을 쉽게 구현할 수 있도록 AWS의 Step Function을 이용했습니다. 아이템 예약에 대한 AWS Lambda 함수, 구매를 진행하면 사용자 결제에 대한 잔액을 인출하는 AWS Lambda 함수 등으로 구성을 할 테고, 실패 할 경우를 대비한 실패 프로세스를 구현했습니다. 결제를 실패했을 경우, 잔액을 상환하고 예약된 아이템을 다시 재입고 시키는 모든 과정들을 AWS Lambda 함수를 이용하여 도메인 이벤트로 구현하였다 소개하고 있습니다.
•
Step Function
다시 앞서 아키텍처에서 설명한 과정들을 Step Function으로 보다 쉽게 구현했습니다. 시각적으로 표현할 수 있는 문법들을 제공하고 있어 위 서비스를 이용하면 손쉽게 구현이 가능하다고 소개했습니다. Step Function과 같은 시각적 표현이 코드로만 되어있는 것보다는 훨씬 이해하기는 쉬웠던 것 같습니다.
•
로열티 도메인
앞에서는 Saga 패턴을 이용하여 트랜잭션 일관성에 대해서 다뤘습니다. 앞에서 구매 완료를 진행하면 도메인 이벤트를 발행하여 로열티 시스템을 동작하게끔 구성되어 있다고 소개하고 있습니다. 이러한 이벤트들을 규칙을 구성하고 이러한 모든 비즈니스 규칙에 부합하는지 유효성 체크가 필요합니다. 위 사진과 같은 여러 상황, 규칙에 부합이 된다면 혜택과 보상을 제공할 수 있을 겁니다.
•
포인트 시스템의 도전과제
포인트 시스템의 요구사항은 구매한 물건에 따른 포인트를 제공하면 됩니다. 몇 일 동안 여러 번 물건을 구매했을 때, 포인트를 받을 수 있으나 포인트의 만료 기간이 존재하지 않다면 복잡한 부분은 없을 겁니다. 하지만 포인트에 만료기간이 존재한다면 복잡해질겁니다. 만료기간에 따른 포인트는 줄어들어야 하기 때문입니다. 이러한 포인트 시스템의 도전과제로는 개별적으로 발생하는 포인트에다가는 단일 레코드 방식을 취할 수 없습니다. 또한 만료기간이 존재하는 포인트의 경우에는 사용자에 따른 처리량을 위한 레이턴시가 있을 수 있고 시스템 부하가 발생할 수 있습니다. 또한 오랜 시간이 걸릴 수 있으며 만료 처리를 위해 그 시스템에서 기간내에 처리할 수도 없을 겁니다. 또한 변경될 수 있는 규칙에 따른 유연성을 고려하여 시스템에 반영할 수 있도록 해야합니다.
•
도전과제 해결을 위해 이벤트 소싱과 CQRS 적용
이러한 도전과제 해결을 위해서는 이벤트 소싱과 CQRS 적용을 소개하고 있습니다. 새로운 이벤트를 발생하면 마지막에 Append 되는 이벤트 소싱 방법과 완벽한 데이터베이스는 없다는 전제하에 퍼포먼스 향상 효과를 기대할 수 있는 명령 쿼리 책임 분리를 이용한 방법을 소개해주었습니다.
•
로열티 도메인 기능의 솔루션 아키텍처
앞서 리테일 도메인에서의 구매 트랜잭션이 발생 했을 때의 이벤트를 이벤트브릿지에서 받아 처리하여 캠페인 프로세싱을 통해 유효성을 체크합니다. 캠페인 룰에 일치하면, 포인트 트랜잭션을 통해 커맨드 핸들러로 다이나모 디비를 이용하여 포인트 내역을 저장, 일자별 잔액 프로세스를 통해 다이나모 디비에 일자별 잔액을 저장합니다. 이후, 사용자의 조회를 위해 API 게이트웨이로 API를 제공할 수 있습니다.
•
통합 아키텍처
리테일 컨텍스트에서 구매 트랙잭션에 대해서 성공적으로 완료가 되면, Step Function에서 Event Bridge로 처리하며 로열티 컨텍스트로 전달하여 포인트가 쌓이고 최종적으로 API Gateway의 API를 통해서 사용자에게 포인트를 전달하는 것입니다.
비즈니스 전략을 소프트웨어 아키텍처 도메인과 일치해서 적응형 소프트웨어 시스템을 구축하는 것을 말하면서 분산 디자인 패턴에 대해서 소개했습니다. 사용 사례에 맞는 올바른 아키텍처를 선택하고 결정하여 나은 시스템이 되도록 고민해야 할 것입니다. 금일 3가지의 분산 디자인 패턴을 소개했으니 다시 복습해야겠다고 생각합니다.
•
결론
오늘 세션에서는 한 번쯤은 공부해봐야겠다라고 고민했던 내용들을 배울 수 있어서 좋았습니다. 도메인 주도 디자인을 적용하고 Saga 패턴과 이벤트 소싱 & CQRS가 적용된 아키텍처를 이해하고 데모를 통해서 확인해 볼 수 있어서 좋았습니다. 시간되면 기능 구현 및 테스트 해보고 싶다라는 생각을 하게 되었고 추후에 더 깊게 공부해야겠다라고 생각했습니다.