2025년 10월 29일
볼트업 백엔드 시스템 개편 이야기 - 파트 1: 아키텍처 편
안녕하세요. 볼트업에서 백엔드 소프트웨어 개발을 맡고있는 Jay(손정연)입니다.
올해 3월, 전기차 충전소 플랫폼 볼트업이 리뉴얼 론칭되었습니다. 새로운 브랜드 아이덴티티와 사용자 앱을 선보였는데요. 달라진 점은 겉모습뿐만이 아닙니다. 볼트업의 백엔드 시스템도 이번에 유지보수와 확장이 쉬운 구조로 새롭게 개편되었습니다. 이 개편을 통해 볼트업은 빠르게 변화하는 전기차 충전 시장에 대응해 사용자의 충전 경험을 지속 개선할 수 있는 플랫폼으로 거듭났습니다.
이번 글은 ‘파트 1: 아키텍처 편’으로 새롭게 개편된 볼트업의 백엔드 시스템이 어떤 과정으로 설계되어 만들어졌는지 공유해 드리겠습니다. 그리고 이어지는 ‘파트 2: 마이그레이션 편’에서 어떻게 무중단으로 구 시스템의 충전기와 데이터를 신규 시스템으로 이관할 수 있었는지 상세히 다루겠습니다.
백엔드 시스템을 개편한 이유
기존 백엔드 시스템에는 몇 가지 문제점들이 있었습니다.
첫 번째로 시스템 내 애플리케이션 기능들이 관계형 데이터베이스 쿼리에 지나치게 의존적이었습니다. 사용자 앱이나 충전기에서 보내지는 요청이 수백 줄에 달하는 단일 SQL 쿼리로 처리되었습니다. 애플리케이션 서버가 있었지만, 정해진 DB 쿼리를 실행하고 그대로 결과를 전달하는 얇은 래퍼(Wrapper) 계층에 불과했습니다. 이 때문에 동일한 비즈니스 로직이 여러 쿼리에 중복되어 있었고 재사용하기 어려웠습니다. 그리고 새로운 기능을 추가하려면 비슷하게 수백 줄에 달하는 SQL 쿼리를 새로 작성해야 했습니다.
구 시스템은 볼트업이 운영되고 데이터베이스에 데이터가 쌓이면서 심각한 성능 문제를 겪고 있었습니다. 복잡한 비즈니스 로직을 단일 SQL 쿼리로 처리하려다 보니, 수많은 테이블에 대한 join 연산이 필수적이었고 결과적으로 매우 무겁고 느린 쿼리 응답시간을 가졌습니다. 더불어 시스템에서 발생하는 대량의 로그도 같은 운영 데이터베이스에 함께 저장하고 조회하다 보니, 누군가 운영 어드민에서 로그를 잘못 조회하는 날이면 사용자 앱에 성능 장애가 발생했습니다.
충전기와 웹소켓으로 통신하는 부분에도 문제가 있었습니다. 구 시스템은 웹소켓 통신 서버를 직접 구현하지 않았고, AWS(Amazon Web Services)의 CloudFront를 활용하여 HTTP 요청을 웹소켓 메시지로 중개해 충전기에 전달했습니다 [1]. 그런데 충전기에서 CloudFront로 응답한 웹소켓 메시지를 요청한 원서버가 받을 방법이 부재하여 처리가 불가능한 상태였습니다. 핵심이라고 볼 수 있는 충전기 통신이 사용하는 클라우드 서비스에 의존적이라는 점도 잠재적인 이슈였습니다.
그 밖에도 DB 테이블의 컬럼명이나 애플리케이션 코드에서 등장하는 변수명이 지나치게 약어로 되어있어서 코드의 의미를 파악하기 힘들고, 열거형 값들이 숫자 코드화되어 있었지만 의미를 나타내는 주석이 제대로 관리되지 않는 등 코드 유지보수에도 큰 어려움이 따랐습니다.
결과적으로 볼트업에 새로 합류한 저희 백엔드 엔지니어들은 기존 시스템이 빠른 외부 환경 변화에 맞추어 지속적으로 확장, 진화하기 어려운 구조라고 판단내렸고, 이를 달성할 수 있는 새로운 백엔드 시스템을 설계하여 만들기로 결정했습니다.
요구사항 분석
저희는 가장 먼저 리뉴얼될 볼트업의 요구사항을 분석했습니다. 이어지는 내용의 이해를 돕기 위해 그 당시 요구사항들을 간략히 소개해 드리겠습니다. 먼저 기능적 요구사항입니다. 가장 큰 틀에서 본 볼트업 플랫폼의 모습은 다음과 같습니다.

백엔드 시스템과 연동되는 클라이언트 소프트웨어로 충전기 펌웨어, 사용자 앱, 운영 어드민, 그리고 환경부 시스템이 있습니다. 각 클라이언트는 시스템 내에서 다음과 같은 역할과 기능을 가집니다.
클라이언트 | 설명 |
|---|---|
충전기 (펌웨어) | - 전기차를 충전하는 장치 |
사용자 앱 | - 사용자용 모바일 애플리케이션 |
운영 어드민 | - 운영자용 웹 애플리케이션 |
환경부 시스템 | - 환경부 주도 로밍 중개 서버 |
그리고 이러한 클라이언트 소프트웨어를 이용하는 액터로 사용자, 운영자, 그리고 타사 플랫폼 사용자가 있습니다. 각 액터는 시스템 내에서 다음과 같은 유즈케이스를 가집니다.
액터 | 유즈케이스 |
|---|---|
사용자 | - 사용자는 사용자 앱에서 신규 가입한다. |
운영자 | - 운영자는 어드민에서 충전기를 등록한다. |
타사 플랫폼 사용자 | - 타사 사용자는 충전기에 회원카드를 태깅하여 충전 시작 전 사용자 인증을 수행한다. |
저희가 고려했던 비기능적 요구사항도 소개해 드리겠습니다. 다음과 같이 성능, 확장성, 가용성, 보안성, 관측성, 그리고 유지보수성 관점에서 요구사항을 정리했습니다.
항목 | 요구사항 |
|---|---|
성능 | - 충전기 1만5천대 이상 동시 웹소켓 연결 지원 |
확장성 | - 충전기 대수가 늘어나는 것에 비례하게 시스템 수평 확장 가능 |
가용성 | - 99.99% 가동 시간 유지 |
보안성 | - 개인정보 데이터 암호화 및 분리보관 |
관측성 | - 로깅, 모니터링 시스템 구축 |
유지보수성 | - 응집성 있는 시스템 컴포넌트 분리 |
이렇게 기능적, 비기능적 요구사항이 모두 정리되었습니다. 이어지는 내용에서 요구사항을 바탕으로 저희가 어떤 과정을 거쳐 시스템을 설계하고 발전시켜 나갔는지 설명하도록 하겠습니다.
시스템 컴포넌트 식별
시스템이라는 용어의 정의를 찾아보면 “상호작용하고 의존하는 여러 요소가 모여 하나의 통일된 전체를 이루는 집합체”라고 이야기합니다. 소프트웨어 시스템에서는 이 요소를 컴포넌트(정적인 코드 관점에서는 모듈)라고 부르는데요. 시스템 컴포넌트들의 역할을 잘 나누면 시스템을 이해하고 유지보수 하기가 쉬워집니다. 그리고 특정 컴포넌트의 변경이 다른 컴포넌트에 미치는 영향을 줄여 유연하게 시스템 기능을 변경할 수 있습니다. 일반적으로 이렇게 잘 분리된 컴포넌트는 높은 응집도와 상호 간에 낮은 결합도를 가진다고 이야기하는데요 [3].
저희는 볼트업의 백엔드 시스템을 높은 응집도와 낮은 결합도를 가진 컴포넌트들로 잘 나누기 위해, 먼저 앞서 정리된 유즈케이스에서 등장하는 개념들을 쭉 나열해 보았습니다. 이것들은 고유한 식별성(Identity)을 가진 개념으로 도메인 주도 설계(Domain-Driven Design)에서 용어를 따와 엔티티(Entity)라고 불렀습니다 [4].
결과적으로 아래와 같은 엔티티들을 발견할 수 있었습니다. 엔티티들 사이의 참조가 있는 경우에는 선으로 연결했습니다. 화살표가 가리키는 엔티티가 참조되는 엔티티입니다.

그다음, 저희는 참조 관계 선이 덜 끊어지는 방향으로 엔티티를 4개의 그룹으로 나누었습니다. 그리고 이 그룹을 도메인 주도 설계의 바운디드 컨텍스트(Bounded Context)와 유사하게 초기 시스템의 컴포넌트 단위로 정했습니다 [4]. 당연히 이때의 구분은 완벽하진 않았고, 도메인 요구사항과 컴포넌트 관계에 대한 구성원들의 이해도가 높아지면서 지속적인 구조 개선이 이루어집니다.

이어서 컴포넌트별로 개발 담당자를 정했는데요. 당시 백엔드 엔지니어는 모두 4명이었습니다. 작업량이 많아 보였던 CSMS(Charge Station Management System) 컴포넌트에 2명, User 컴포넌트에 1명, 그리고 Billing 컴포넌트에 1명을 할당했습니다. Roaming 컴포넌트는 우선순위가 낮아 일단 작업을 미루었습니다.
작은 규모였지만 저희는 컴포넌트 단위로 담당자를 지정했고, 각자 맡은 컴포넌트에 오너십을 가지고 개발을 진행했습니다. 역 콘웨이의 법칙(Inverse Conway Maneuver)을 따랐는데요 [5]. 시스템 구조와 유사하게 서로의 작업에 대해 느슨한 의존성을 가지고, 컴포넌트 간 연동이 필요한 부분에서만 커뮤니케이션이 이뤄지며 효율적인 업무가 가능했습니다.
모놀로식 vs 마이크로서비스
본격적인 코드 작업이 시작되기 전에 큰 의사결정이 하나 있었습니다. 그것은 바로 각 컴포넌트를 모듈로 만들어 컴파일 타임에 통합하는 모놀로식(Monolithic) 아키텍처로 시스템을 구성할지, 아니면 각 컴포넌트를 마이크로서비스로 만들어 런타임에 통신으로 통합하는 분산 아키텍처로 시스템을 구성할지 선택하는 것이었습니다.
두 아키텍처의 장단점은 일반적으로 아래와 같다고 알려져 있는데요 [6].
구분 | 모놀리식 아키텍처 | 마이크로서비스 아키텍처 |
|---|---|---|
장점 | - 구조 단순 | - 서비스별 독립 배포와 확장 가능 |
단점 | - 코드베이스 커짐 | - 네트워크 통신 복잡도 증가 |
많은 논의 끝에, 저희는 결과적으로 마이크로서비스 아키텍처(Microservices Architecture, MSA)를 선택했습니다.
가장 중요하게 생각했던 것은 엔지니어들의 작업 독립성과 자율성이었습니다. 저희는 가능한 병렬적으로 작업을 진행해 빠르게 시스템 개편을 완료하고자 했습니다. 그래서 코드의 충돌과 병합이 자주 반복되는 모놀리식 아키텍처보단, 분리된 코드베이스에서 각 담당자가 독립적으로 개발을 진행할 수 있는 MSA가 더 적합하다고 판단했습니다.
그리고 저희 시스템은 사용자 앱에서 발생하는 트래픽보다 충전기에서 발생하는 트래픽이 훨씬 클 것으로 예상되었습니다. 그래서 충전기의 트래픽을 처리하는 CSMS 컴포넌트만 선택적으로 인프라 자원을 확장할 수 있는 MSA가 더 높은 점수를 얻었습니다.
다만 MSA가 분산 시스템으로써 가지는 복잡성에 대해서는 다들 우려했습니다. 여러 마이크로서비스에 걸쳐 데이터를 수정하는 경우, 데이터 일관성 유지를 위해 실패 보상 로직이 필요했습니다 [7]. 그리고 언제든지 마이크로서비스 사이의 통신이 실패할 수 있다는 점도 염두해 두어야 했습니다. 그럼에도 저희는 엔지니어들의 작업 독립성을 더 중요한 가치로 여겼고, 향후 시스템 확장에도 MSA가 더 유리할 것으로 판단해 최종적으로 MSA를 선택했습니다.
오케스트레이터와 유닛 서비스: 서비스 계층 분리
MSA를 채택한 이후, CSMS 컴포넌트는 CSMS, User 컴포넌트는 User 서비스, Billing 컴포넌트는 Billing 서비스라는 이름으로 개발이 진행되었습니다. 이 당시 CSMS는 충전기와 연관된 데이터를 관리하는 기능과 충전기 요청을 받아 다른 서비스들의 기능을 조합해 유즈케이스를 처리하는 로직이 함께 존재했습니다. 마찬가지로 User 서비스도 사용자와 연관된 데이터를 관리하는 기능과 사용자 앱, 그리고 운영 어드민에서 요청되는 유즈케이스를 처리하는 로직이 함께 있었습니다.
저희는 하나의 서비스 안에 두 가지의 관심사가 혼재되어 있었다고 판단했고, 아래와 같이 두 가지 서비스 계층을 구분하여 분리하는 작업을 진행했습니다.
서비스 분류 | 역할 |
|---|---|
유닛 서비스 (Unit Service) | - 도메인별 원천 데이터 관리 |
오케스트레이터 (Orchestrator) | - 유닛 서비스를 조합하여 유즈케이스 구현 |

우선 CSMS 컴포넌트 담당자가 CSMS에서 Charger 서비스를 분리했습니다. CSMS에는 OCPP 프로토콜로 충전기와 통신하는 맥락에서 사용되는 ‘OCPP 충전기’ 엔티티만 분리하여 남겼습니다. 기존 나머지 충전기와 관련된 엔티티들은 모두 Charger 서비스로 이관했습니다. 그리고 CSMS에는 다른 서비스의 기능들을 조합해 충전기 요청을 처리하는 로직을 남기고, Charger 서비스로 자주 재사용되는 충전기 관련 엔티티 조회, 변경 로직을 옮겼습니다.
동시에 User 컴포넌트 담당자도 User 서비스에서 App/Admin 오케스트레이터를 분리했습니다. App/Admin 오케스트레이터로 사용자 앱과 운영 어드민의 요청을 처리하기 위한 로직을 옮겼고, User 서비스에 자주 재사용되는 사용자 관련 엔티티 조회, 변경 로직을 남겼습니다. 다만 App과 Admin 오케스트레이터는 서로 공유하는 엔티티와 비즈니스 로직들이 많아서, 코드 레벨에선 모듈을 공유하고 런타임 애플리케이션만 분리하여 구동시키는 형태로 설계했습니다.
두 계층으로 시스템 내 서비스들을 분류하자 시스템에 몇 가지 개선점이 생겼습니다. 첫 번째로 재사용이 어려운 클라이언트별 유즈케이스 처리 로직이 오케스트레이터로 이동하면서, 유닛 서비스는 도메인 단위로 기능이 명확히 나뉘어 재사용성이 크게 증가했습니다. 두 번째로 오케스트레이터가 중간에서 서비스를 조율하면서, 서비스 간 상호 의존성이 줄어들고 전체 시스템의 의존 관계가 단순해졌습니다. 마지막으로 신규 제품의 개발이 새로운 오케스트레이터를 추가하는 방식으로 쉬워졌습니다. 필요한 유닛 서비스들을 조합해 신규 제품에 필요한 백엔드 기능들을 빠르게 구현할 수 있었습니다.
충전 엔티티에서 사용자 관심사 분리
그다음 시스템에 찾아온 변화는 ‘충전 엔티티’와 ‘주문 엔티티'의 분리입니다. 기존에는 어떤 사용자가 어떤 결제 금액만큼 충전을 이용했는지 알 수 있도록 충전 엔티티가 사용자 ID와 결제 금액값을 포함하고 있었습니다. 저희는 충전 엔티티가 충전기, 충전량, 충전 속도와 같은 Charger 서비스의 고유 관심사뿐만 아니라 사용자, 요금제, 결제 금액과 같은 사용자의 관심사까지 포함하고 있다고 인지하게 되었습니다. 그래서 충전 엔티티에서 사용자 관심사를 주문 엔티티로 분리하고, 이것을 App/Admin 오케스트레이터의 공유 모듈로 옮겼습니다. 결과적으로 아래와 같은 모습이 되었습니다.

서비스 경계를 넘나드는 엔티티 간 의존 관계의 수가 줄어들고 시스템 구조가 더욱 단순해졌습니다. 그리고 충전 엔티티는 이제 더 이상 어떤 사용자가 얼마를 결제했는지 알 필요가 없어졌습니다. 대신 Charger 서비스가 충전 엔티티의 생성이나 변경 시 시스템 내 이벤트 큐로 이벤트를 발행합니다. 그리고 App 오케스트레이터가 이 이벤트를 구독하여 주문 엔티티를 생성하고, 충전 종료 시점에 요금 정보에 따라 결제를 진행하게 됩니다.

이러한 관심사 분리는 볼트업 회원이 아닌 제휴 사용자들이 볼트업의 충전기를 이용하게 되면서 그 장점을 더 발휘하게 됩니다. 환경부 중심 협약 아래 타사 충전소 플랫폼 사용자와, 이어서 제휴를 맺은 카카오 내비 앱의 사용자가 볼트업의 충전기를 이용할 수 있었습니다.
저희는 제휴 사용자를 위한 유즈케이스를 구현할 때도 동일한 Charger 서비스의 엔티티와 핵심 비즈니스 로직을 그대로 재사용했습니다. 그 결과 다양한 유형의 사용자들이 충전기를 이용하는 상태가 자연스럽게 동기화되었고, 충전기 상태에 의존하는 다른 오케스트레이터 기능에도 즉시 반영되었습니다.
사용자 유형별로 달라지는 인증 로직과 요금 정보는 별도의 오케스트레이터를 만들어 구현했습니다. 각 오케스트레이터는 충전 관련 이벤트를 구독하면서, 자체 요금제를 반영해 주문 정보를 갱신하고 제휴사 시스템과 연동됩니다. Charger 서비스에서 사용자 유형별로 로직을 분기하지 않고, 외부 오케스트레이터에 사용자마다 달라지는 기능을 구현함으로써, 결과적으로 시스템은 향후 또 다른 사용자 유형이나 결제 수단을 쉽게 추가할 수 있는 유연성을 얻었습니다.
리뉴얼 론칭과 그 이후
테크 조직에 새로운 백엔드 엔지니어들이 합류하면서, 미루어왔던 Roaming 서비스가 완성되었습니다. 이와 함께 앱 푸시, SMS 문자, 이메일을 전송하는 역할로 Messaging 서비스가 시스템에 추가되었고 구 시스템의 데이터를 활용하고 이관하기 위한 목적으로 Legacy 서비스가 새로 만들어졌습니다.
비슷한 시점에 프론트엔드 엔지니어들이 개발하고 있던 사용자 앱과 어드민까지 개발이 완료되면서, 리뉴얼 볼트업 론칭의 모든 준비가 끝났습니다. 론칭 시점의 백엔드 시스템 모습은 다음과 같았습니다.

저희는 정식 론칭 일주일 전에, 사용자 앱을 공개해 회원가입과 결제수단 등록을 먼저 받았습니다. 구 시스템 사용자의 계정 전환 피로도를 낮추기 위한 조치였지만, 엔지니어들에게는 미리 신규 시스템의 정상 동작 여부를 확인해볼 수 있는 좋은 기회였습니다. 그로부터 일주일 후 대망의 론칭일이 찾아왔고, 충전을 포함한 리뉴얼 볼트업의 모든 것을 외부에 공개했습니다. 다행히 장애 없이 모든 기능이 정상 동작했고 론칭을 성공적으로 마무리할 수 있었습니다.
론칭 이후에도 시스템은 지속적으로 발전해왔습니다. 론칭 후로 7개월이란 시간이 더 흘렀는데요. 지금 시점의 시스템의 모습은 다음과 같습니다.

충전기 제조사에 제공하는 ‘제조사 개발 도구’, 충전기 공사 업체에 제공하는 ‘공사 업체 도구’와 같이 운영 업무를 효율화하기 위한 제품들을 새롭게 출시했습니다. 그리고 충전기 로그를 기반으로 이상 동작을 감지해 보고하는 ‘충전기 이상 감지 시스템’을 만들어, 운영자가 충전기 고장에 더 신속하게 대처할 수 있게 했습니다. 나아가 시스템에서 발생하는 데이터를 통합하고 분석하기 위한 데이터 웨어하우스(Data Warehouse)를 구축했고, 볼트업 구성원들이 보다 쉽게 비즈니스 인사이트를 발견할 수 있게 도왔습니다. 이처럼 빠르고 다양한 발전은 유연하고 확장성이 높은 시스템 설계 덕분에 가능했습니다.
인프라 구성
지금까지 볼트업 백엔드 시스템의 발전 과정을 주로 애플리케이션 관점에서 다루었습니다. 이는 저희가 시스템 설계 시 애플리케이션 관점의 확장성과 유지보수성을 중요하게 생각했기 때문인데요. 독자분들의 참고를 위해, 이번에는 인프라 관점에서 볼트업 시스템이 어떻게 구성되어 있는지도 짧게 소개하겠습니다.
볼트업은 전기차 충전소 플랫폼이라는 특성상, 온라인 커머스나 콘텐츠 플랫폼에 비해 상대적으로 트래픽 규모가 크지 않습니다. 따라서 복잡하거나 특별한 인프라 기술이 요구되지 않았는데요. 저희는 사용료 다음으로 유지보수성을 가장 중요한 기술 선택 기준으로 삼았습니다. 결과적으로 기본적이고 잘 알려진 기술들이 주로 채택되었습니다.
저희는 Google Cloud Platform(GCP)을 사용했습니다. 그리고 GCP가 제공하는 관리형 서비스(Managed Services)를 적극적으로 활용했습니다. 관리형 서비스를 잘 활용하면 데이터센터 이중화나 데이터 백업 등 시스템 가용성을 높이는데 필요한 기능들을 손쉽게 구축할 수 있었습니다. 많은 노력을 들이지 않고도 무중단 인프라 유지보수가 가능하다는 점도 큰 장점이었습니다.
결과적으로 볼트업 백엔드 시스템은 다음과 같은 다양한 GCP 서비스들로 구성되어 안정적으로 잘 운영되고 있습니다.
범주 | 서비스 |
|---|---|
컴퓨팅 | Kubernetes Engine |
데이터베이스 | Cloud SQL (MySQL) |
메모리 캐시 | MemoryStore (Redis) |
스토리지 | Cloud Storage |
이벤트 큐 | Pub/Sub |
네트워크 제어 | Virtual Private Cloud, Cloud Armor, Cloud DNS, Cloud Load Balancing |
운영 관측 | Cloud Logging, Cloud Monitoring, Cloud Trace |
데이터 분석 | BigQuery |
마치며
파트 1에서는 볼트업 백엔드 시스템이 새롭게 설계되고 만들어지는 과정, 그리고 저희 백엔드 엔지니어들이 어떤 판단 기준을 가지고 시스템 구조를 변화시켜 나갔는지 상세히 살펴보았습니다.
이번 개편 과정에서 저희가 배운 점이 있다면, 그것은 미래의 요구사항을 예측하는 것은 어렵고 처음부터 시스템을 완벽하게 설계하는건 불가능하다는 점입니다. 소프트웨어 시스템의 본질인 ‘유연성’을 살려 변경과 확장이 쉬운 구조로 시스템을 설계하는 것이 중요하다고 느꼈습니다. 처음부터 완벽한 설계를 목표로 복잡한 추상화를 도입하기보다는, 가능한 단순하게 시작하고 실제 마주하는 요구사항에 맞춰 시스템을 점진적으로 진화시켜나가는 것이 현명한 접근법 같습니다.
볼트업은 이번 개편을 통해 유연하게 변화하고 진화할 수 있는 플랫폼으로 거듭났습니다. 이 토대 위에서 저희는 사용자의 충전 경험을 꾸준히 개선시켜 나갈 것입니다. 그리고 자동화를 통해 내부 운영 프로세스도 점진적으로 효율화해 나갈 계획입니다. 앞으로 볼트업이 만들어갈 발전에도 많은 관심 부탁드립니다. 이어지는 '파트 2: 마이그레이션 편'에서 뵙겠습니다.
참고문헌
[1] AWS. Use WebSockets with CloudFront distributions. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-working-with.websockets.html
[2] Open Charge Alliance. Open Charge Point Protocol (OCPP). https://openchargealliance.org/protocols/open-charge-point-protocol
[3] L. Constantine, E. Yourdon. Structured Design: Fundamentals of a Discipline of Computer Program and Systems Design. Yourdon Press, 1979.
[4] E. Evans. Domain-Driven Design: Tackling Complexity in the Heart of Software. Addison-Wesley, 2003.
[5] Thoughtworks. Inverse-Conway-Maneuver: How to speed up product development teams successfully. https://www.thoughtworks.com/insights/blog/customer-experience/inverse-conway-maneuver-product-development-teams
[6] S. Newman. Building Microservices: Designing Fine-Grained Systems. O'Reilly Media, 2015.
[7] Microsoft Learn. Saga Design Pattern. https://learn.microsoft.com/en-us/azure/architecture/patterns/saga