결론 먼저 — 한 서비스 vs 두 서비스, 4축 비교
| 축 | 한 서비스 | 두 서비스 분리 |
|---|---|---|
| 장애 격리 | 한쪽이 죽으면 둘 다 | 격리됨 |
| 배포 주기 | 가장 느린 쪽에 묶임 | 독립 |
| 의존성 그래프 | 코드 안에서 얽힘 | 네트워크 경계로 강제 분리 |
| 디버깅 시 의심 범위 | 전체 코드베이스 | 신호 따라 좁아짐 |
| 초기 코드 라인 | 적음 | 약간 늘어남 |
분리는 코드를 늘리는 결정이 아니라, 코드 변경의 결을 가지런하게 만드는 결정이다.
미디어 평면과 비즈니스 평면, 무엇이 다른가
미디어 평면 (media plane)
- RTP forward, ICE 협상, codec, panic 격리
- 한 통화의 latency가 사용자 경험에 직결
- 에러 = 즉시 통화 실패 (동기적 영향)
비즈니스 평면 (control / business plane)
- 세션 메타(누가 누구에게, 언제), 권한, billing, 통계 집계
- “통계가 1초 늦게 들어와도 사용자가 모른다”가 허용되는 환경
- 에러 = 후속 처리 지연 (eventual consistency 허용)
이 둘은 시간 축의 단위가 다르다. 미디어는 ms 단위, 비즈니스는 초~분 단위. 같은 프로세스에 두면 더 빡빡한 SLA에 양쪽 다 묶이게 된다.
같이 두면 무슨 일이 생기나
데모를 짤 때 처음에는 한 프로세스에 두 책임을 다 넣어 봤다. 코드량은 작아 보였지만 곧 두 가지 부담이 드러났다.
- 비즈니스 로직 한 줄을 고치려고 미디어 프로세스까지 재시작해야 한다 → 진행 중인 데모 통화가 끊김
- 비즈니스 평면의 e2e 테스트가 도는 동안 미디어 코드가 굳어 있다
- 한쪽 panic이 다른 쪽까지 죽인다
코드량이 작을 때는 잘 보이지 않는 이 비용이, 데모를 며칠 굴리는 사이에 누적된다는 게 핵심이었다.
두 서비스를 어떻게 잇나 — 3가지 패턴
| 패턴 | 장점 | 단점 |
|---|---|---|
| 직접 RPC (gRPC / HTTP) | 단순, 디버깅 쉬움 | 강결합, 서비스 간 빌드/테스트 복잡 |
| 메시지 큐 (NATS / RabbitMQ / Kafka) | 비동기, 부하 분산 자연스러움 | 복잡도 증가, 메시지 추적 도구 필요 |
| 공유 DB / Redis | 가장 가벼움 | 책임 경계가 흐려짐, 스키마 변경이 양쪽에 영향 |
1:1 음성 데모 수준에서는 직접 RPC가 가장 자연스러웠다. 통화 시작·종료 같은 시점 신호만 비즈니스 평면이 받아 두면 충분하기 때문이다.
언제 분리하지 말아야 하나
- 한 사람이 처음부터 끝까지 짜는 데모 / PoC — 분리 비용이 본질 학습을 가린다
- 책임이 정말로 한 가지인 작은 도구 — Conway’s Law를 거꾸로 적용하는 셈
- 두 평면 모두 한 함수 안에 들어가는 수준의 단순 흐름
분리는 무조건 좋은 결정이 아니라, 코드 변경의 결이 갈리기 시작했을 때 의미가 생긴다.
개인 메모 — “한 프로세스 안에서 두 책임이 부딪힐 때”
처음에는 “어차피 도메인이 같으니 한 서비스로 두는 게 단순하지 않나”라고 생각했다. 코드량이 작은 단계에서는 그게 맞았다. 그런데 데모를 며칠 굴리면서 비즈니스 로직 한 줄을 고치려 할 때마다 미디어 코드의 e2e가 같이 도는 부담을 직접 느꼈고, 그제야 두 평면을 가르는 게 의미가 있다는 걸 알게 됐다.
분리한 후로는 한쪽을 만지는 사이 다른 쪽을 신경쓰지 않아도 된다는 단순한 이점이 생각보다 크게 다가왔다. 12-Factor App의 process 분리 원칙이 작은 데모에서도 의미가 있다는 걸 짧은 경험으로 확인한 셈이다.
답글 남기기