커머스 백엔드를 한 번이라도 직접 운영해봤다면, 주문-재고-결제 로직이 한 덩어리로 뭉쳐 있을 때 어떤 일이 생기는지 안다. 주문 상태 하나를 바꾸려다 재고 계산 버그를 건드리고, 결제 취소 로직이 포인트 적립 코드와 얽혀 있어서 수정 범위를 예측하기가 어렵다. 대부분의 커머스 플랫폼이 이 문제를 "잘 만든 모노리스"로 해결하려 하지만, Medusa v2는 방향을 다르게 잡았다.
Medusa v2의 핵심은 Cart, Order, Inventory, Pricing을 각각 독립 Module로 분리한 것이다. 각 Module은 자체 데이터베이스 스키마를 갖고, 다른 Module을 직접 import하거나 참조하는 구조를 허용하지 않는다. 모듈 간 연결은 "Link" 레이어를 통해서만 가능하다. 이 제약이 처음엔 번거롭게 느껴지지만, 덕분에 한 Module의 변경이 다른 Module로 전파되는 사이드 이펙트를 구조적으로 차단한다. 마이크로서비스 아키텍처에서 서비스 간 직접 DB 접근을 금지하는 원칙을, 단일 레포 안에서 모듈 레벨로 구현한 셈이다.
또 하나 주목할 개념이 Workflow다. 주문 생성처럼 여러 도메인에 걸친 작업을 step 단위로 정의하고, 각 step이 실패했을 때 이미 완료된 step을 역순으로 롤백하는 보상 트랜잭션을 내장한다. "결제는 완료됐는데 재고 차감에서 예외가 터지면?" — 커머스 팀이라면 한 번쯤 야간에 핫픽스를 배포했을 그 시나리오를, Workflow 엔진이 프레임워크 레벨에서 Saga 패턴으로 다룬다. 분산 트랜잭션 로직을 직접 구현할 필요가 없어진다.
물론 비용이 있다. medusa.config.ts에서 Module을 등록하고 Link를 정의하고 Workflow를 체이닝하는 과정은 러닝커브가 가파르다. 첫 셋업에서 Hello World 수준까지 가는 데도 상당한 개념 이해가 선행되어야 한다. 이 복잡성은 Medusa가 스스로 선택한 트레이드오프다 — 빠른 시작보다 장기 유지보수를 우선했다. B2B 가격 정책, 멀티벤더 재고 분리, 구독과 일회성 구매가 혼재하는 시스템을 나중에 리아키텍처 없이 소화하려면, 처음부터 이 구조를 이해하고 시작하는 편이 낫다는 판단이 코드베이스에 담겨 있다.