Development··6 min read

마이크로서비스가 정답이 아닌 경우

마이크로서비스로 전환했다가 다시 모놀리스로 돌아온 경험담.

"우리도 마이크로서비스 해야 하지 않을까"

2024년, 팀 리드가 회의에서 이 말을 꺼냈다. 넷플릭스도 하고, 쿠팡도 하고, 우리도 해야 하지 않겠냐고. 팀원 6명, DAU 5천 명의 B2B SaaS.

결론부터 말하면, 8개월 후에 다시 모놀리스로 돌아왔다.

5개로 쪼갰다

모놀리스였던 Spring Boot 앱을 사용자 서비스, 주문 서비스, 결제 서비스, 알림 서비스, 리포트 서비스로 분리했다. 각 서비스에 별도의 DB를 할당하고, 서비스 간 통신은 REST API로 했다.

분리하는 데 3개월이 걸렸다. 코드를 나누는 건 어렵지 않았다.

문제는 데이터였다.

JOIN 한 줄이면 될 걸

주문과 결제가 분리되니까 트랜잭션이 깨졌다. 주문은 생성됐는데 결제가 실패한 경우를 처리해야 했다. Saga 패턴을 도입했는데, 보상 트랜잭션 로직이 원래 비즈니스 로직보다 복잡해졌다.

리포트 서비스는 더 심각했다. 매출 리포트를 만들려면 주문, 결제, 사용자 데이터가 모두 필요했다. 세 서비스에 각각 API 호출을 하고 조합해야 했다. 모놀리스에서 JOIN 한 줄이면 될 걸, 200줄의 코드가 필요했다.

(이때부터 뭔가 잘못되고 있다는 걸 느꼈다.)

운영이 감당이 안 됐다

서비스 5개 곱하기 환경 3개면 15개의 배포 파이프라인이다. 각 서비스의 API 버전 호환성 관리, 서비스 간 장애 전파 추적, 분산 로그 수집.

팀원 6명이 감당하기엔 너무 컸다. 새 기능 하나 개발하는 데 3개 서비스를 동시에 수정해야 하는 경우가 많았고, 배포 순서까지 신경 써야 했다. 디버깅도 고통이었다. 모놀리스에서는 스택 트레이스 하나면 원인을 찾을 수 있었는데, 이제는 요청이 3개 서비스를 거치면서 어디서 문제가 생겼는지 추적하는 것 자체가 일이 됐다.

Jaeger 설정하고 익숙해지는 데 2주. 원래 기능 개발에 쓸 시간이었다.

6개월 차에 팀 전체가 지쳤다

새 기능 출시 속도가 전환 전의 절반으로 떨어졌다. 기술 부채는 늘어나고, 고객 불만은 쌓이고.

팀 회고에서 솔직하게 이야기했다. "우리 규모에서 마이크로서비스는 시기상조였다." 다행히 팀 리드도 동의했고, 다시 모놀리스로 합치는 작업을 시작했다.

합치는 건 쪼개는 것보다 빨랐다. 2개월 만에 원래 구조로 돌아왔다. 돌아온 날 팀원 한 명이 말했다. "JOIN이 이렇게 반가울 줄 몰랐어요."

근데 마이크로서비스가 나쁘다는 건 아니다

조건이 맞으면 강력한 아키텍처다. 팀이 서비스별로 독립적으로 운영될 수 있을 만큼 충분히 크고, 각 서비스의 배포 주기가 실제로 다르고, 트래픽 패턴이 서비스마다 현저히 다른 경우.

우리는 이 중 하나도 해당되지 않았다. 6명이 하나의 제품을 만들고 있다면 모놀리스가 자연스럽다.

8개월의 수업료

지금은 모듈러 모놀리스 구조를 잘 유지하고 있다. 코드 레벨에서 관심사를 분리하되, 배포는 하나로 한다. 나중에 팀이 20명이 넘고 배포 충돌이 잦아지면 그때 자연스럽게 서비스를 분리하면 된다.

기술은 문제가 생겼을 때 도입하는 거지, 문제가 생기기 전에 미리 도입하는 게 아니다.

관련 글