Splitting a Monolith Into Two Services
한국어 원문으로 표시합니다.
목표
주문과 재고가 한 프로세스에 들어 있는 모놀리스를, 계약을 먼저 고정한 뒤 두 개의 독립 서비스로 분리하고, 분리 전후의 응답이 같은지 자동으로 검증한다.
왜 중요한가
서비스 분리에서 실제로 어려운 부분은 코드를 옮기는 일이 아닙니다. 옮기고 나서도 같은 답이 나오는지 확인하는 일, 그리고 데이터 소유권까지 함께 옮겼는지 확인하는 일입니다. 현장에서 가장 흔한 실패는 "서비스는 나눴는데 테이블은 공유"입니다. 이러면 배포는 독립됐지만 스키마 변경은 여전히 두 팀의 합의를 필요로 합니다. 결합은 코드가 아니라 데이터에 있었기 때문입니다. 그래서 이 실습은 코드를 옮기기 전에 계약(contract)을 파일로 먼저 고정하고, 마지막에 소스를 검사해 데이터 접근이 정말로 끊겼는지 확인합니다. 교살 무화과 방식에서 파사드 뒤의 두 구현이 같은 답을 준다는 확신이 없으면 트래픽을 넘길 수 없습니다.
단계
/opt/fixtures/msa/monolith.py를 127.0.0.1:8101 에 띄우고GET /health가 200 을 주게 한다.- 모놀리스의 라우트를 조사해
/root/msa/seams.txt에 한 줄에 하나씩경로 도메인형식으로 적는다.orders와inventory두 도메인이 모두 등장해야 하고 최소 4줄이어야 한다. /root/msa/contract.json을 만든다. 최상위 키는orders와inventory두 개이고, 각각port(정수)와paths(문자열 배열)를 가진다. orders 는 8103, inventory 는 8102 이다./root/msa/inventory_svc.py를 만들어 127.0.0.1:8102 에 띄운다.GET /stock/SKU-1이{"sku":"SKU-1","qty":<정수>}를 준다./root/msa/orders_svc.py를 만들어 127.0.0.1:8103 에 띄운다.POST /orders는{"sku":"SKU-1","qty":2}를 받아 재고 서비스에 물어본 뒤 충분하면 201 과order_id, 모자라면 409 를 준다.orders_svc.py소스에/opt/fixtures/msa/inventory.json같은 재고 데이터 경로가 없어야 하고, 대신 8102 호출이 있어야 한다./root/msa/parity.sh를 만든다. 같은 요청을 모놀리스(8101)와 새 주문 서비스(8103)에 보내 상태코드와 판정이 같으면PARITY OK를 출력한다. 실행 결과를/root/msa/parity.out에 남긴다./root/msa/decision.md에## 쪼갠 이유와## 쪼개지 말았어야 할 이유두 제목을 넣고 각각 30자 이상 쓴다.
참고
- 백그라운드 기동:
nohup python3 파일.py > /root/msa/파일.log 2>&1 & - 포트 확인:
ss -ltnp | grep 810 - 흔한 실수 1: 새 서비스가 재고 JSON 파일을 그대로 열어 읽는 것 — 그건 분리가 아닙니다.
- 흔한 실수 2: 응답 JSON 의 키 이름을 바꿔 버리는 것 — 계약을 먼저 적은 이유가 그것입니다.
모놀리스 띄우고 기준선 잡기
/opt/fixtures/msa/monolith.py 를 127.0.0.1:8101 에 띄우고 GET /health 가 200 을 주게 한다.
/opt/fixtures/msa/monolith.py 를 python3 로 실행하면 8101 포트에 뜹니다. 백그라운드 실행(&)과 로그 리다이렉션을 잊지 마세요.
이음매(seam) 목록 만들기
모놀리스의 라우트를 조사해 /root/msa/seams.txt 에 한 줄에 하나씩 경로 도메인 형식으로 적는다. orders 와 inventory 두 도메인이 모두 등장해야 하고 최소 4줄이어야 한다.
쪼개기 전에 경계 후보를 먼저 적습니다. 모놀리스의 라우트 정의를 grep 해서 경로와 담당 도메인을 한 줄씩 적으세요.
두 서비스의 계약 고정하기
/root/msa/contract.json 을 만든다. 최상위 키는 orders 와 inventory 두 개이고, 각각 port(정수)와 paths(문자열 배열)를 가진다. orders 는 8103, inventory 는 8102 이다.
코드보다 계약이 먼저입니다. JSON 으로 서비스명, 포트, 노출 경로를 적습니다. 재고 서비스가 무엇을 약속하는지가 핵심입니다.
재고 서비스 분리하기
/root/msa/inventory_svc.py 를 만들어 127.0.0.1:8102 에 띄운다. GET /stock/SKU-1 이 {"sku":"SKU-1","qty":<정수>} 를 준다.
재고 관련 로직만 새 파일로 옮겨 8102 에 띄웁니다. 응답은 sku 와 qty 를 담은 JSON 이어야 합니다.
주문 서비스 분리하기
/root/msa/orders_svc.py 를 만들어 127.0.0.1:8103 에 띄운다. POST /orders 는 {"sku":"SKU-1","qty":2} 를 받아 재고 서비스에 물어본 뒤 충분하면 201 과 order_id, 모자라면 409 를 준다.
주문 서비스는 재고를 직접 읽지 않고 HTTP 로 물어봅니다. 재고가 모자라면 409 를 돌려주는 것이 계약입니다.
데이터 소유권 분리 증명하기
orders_svc.py 소스에 /opt/fixtures/msa/inventory.json 같은 재고 데이터 경로가 없어야 하고, 대신 8102 호출이 있어야 한다.
주문 서비스 소스에 재고 데이터 파일 경로가 남아 있으면 아직 결합돼 있는 것입니다. 소스를 검사해 보세요.
모놀리스와 응답 동등성 비교하기
/root/msa/parity.sh 를 만든다. 같은 요청을 모놀리스(8101)와 새 주문 서비스(8103)에 보내 상태코드와 판정이 같으면 PARITY OK 를 출력한다. 실행 결과를 /root/msa/parity.out 에 남긴다.
같은 입력을 두 경로에 넣고 결과를 비교하는 스크립트를 씁니다. 두 응답이 같으면 PARITY OK 를 출력하게 하세요.
분리 판단 기록 남기기
/root/msa/decision.md 에 ## 쪼갠 이유 와 ## 쪼개지 말았어야 할 이유 두 제목을 넣고 각각 30자 이상 쓴다.
쪼갠 근거와 쪼개지 말았어야 할 근거를 각각 적습니다. 지정된 두 개의 마크다운 제목을 정확히 써야 채점이 됩니다.