마이크로서비스 아키텍처 · 모놀리스에서 MSA 로 · 이론
쪼개면 무엇이 좋아지고 무엇이 나빠지는가
한 줄 요약
마이크로서비스는 성능을 위한 선택이 아니라, 팀이 서로를 기다리지 않고 배포하기 위한 선택이다. 그 대가로 함수 호출이었던 것이 네트워크 호출이 된다.
왜 이게 필요했나
모놀리스가 나쁘다는 말을 자주 듣습니다. 하지만 실제로 무너지는 순서를 보면 코드가 먼저가 아닙니다. 배포가 먼저입니다. 한 저장소에 여덟 팀이 커밋하고, 릴리스 브랜치를 자르는 데 이틀이 걸리고, 한 팀의 버그로 전체 배포가 멈추는 상황 — 여기서 사람들이 "쪼개자"고 말하기 시작합니다.
그 진단은 대체로 맞습니다. 문제는 그다음입니다. 쪼개는 순간 잃는 것들의 목록이 대개 준비돼 있지 않습니다. 모놀리스 안에서 inventory.reserve(sku, 3) 은 나노초 단위의 함수 호출이었고 실패할 수 없었습니다. 서비스로 나눈 순간 그것은 밀리초 단위의 HTTP 호출이 되고, 타임아웃될 수 있고, 반쯤 성공할 수 있고, 상대가 재시작 중일 수 있습니다. 그리고 그 호출을 감싸는 트랜잭션은 더 이상 존재하지 않습니다.
어떻게 동작하나
판단의 기준은 세 가지입니다.
첫째, 배포 독립성이 실제로 필요한가. 두 기능이 항상 같이 배포된다면 나누는 이득이 거의 없습니다. 나눠 놓고도 늘 함께 릴리스한다면 그건 분산 모놀리스이고, 모놀리스의 단점에 분산 시스템의 단점을 더한 것입니다.
둘째, 데이터가 갈라지는가. 두 서비스가 같은 테이블에 쓰기를 계속한다면 경계가 잘못 그어진 것입니다. 서비스 경계는 코드 경계가 아니라 데이터 소유권 경계입니다.
셋째, 팀이 있는가. 서비스마다 온콜을 설 사람이 필요합니다. 세 명짜리 팀이 아홉 개 서비스를 운영하면 배포가 빨라지는 대신 새벽 호출이 세 배가 됩니다.
전환 방법은 빅뱅이 아니라 교살 무화과(Strangler Fig)입니다. 앞에 파사드를 두고, 한 기능씩 새 서비스로 옮기고, 트래픽을 비율로 넘기고, 안정되면 모놀리스에서 그 코드를 지웁니다. 변환 → 공존 → 제거를 반복합니다. 이 방식의 핵심은 언제든 되돌릴 수 있다는 점입니다. 파사드의 라우팅 한 줄만 되돌리면 됩니다.
현장에서 만나는 모습
파사드는 대개 API 게이트웨이(Kong, Envoy, NGINX)가 맡습니다. 여기에 부패 방지 계층(Anti-Corruption Layer)을 함께 둡니다. 레거시의 데이터 모델이 새 서비스로 스며들지 않게 번역해 주는 층입니다. 이걸 생략하면 새 서비스가 6개월 만에 레거시 스키마를 그대로 닮아 갑니다. 그러면 쪼갠 의미가 사라집니다.
가장 자주 보는 실패는 "재고 서비스를 뗐는데 재고 테이블은 그대로 공유"입니다. 이렇게 하면 배포는 나뉘었지만 스키마 변경은 여전히 두 팀의 합의가 필요합니다. 결합은 코드가 아니라 데이터에 있었기 때문입니다.
다음 실습에서 할 것
주문과 재고가 한 프로세스에 들어 있는 모놀리스를 받아, 계약을 먼저 문서로 고정하고, 두 개의 서비스로 나눕니다. 나눈 뒤 두 구현의 응답이 같은지 자동으로 비교하는 스크립트를 만들고, 마지막에 "이건 쪼개지 말았어야 했다"에 해당하는 근거도 한 줄 적습니다.