레이어드 아키텍처로 잘 나눠도 트래픽이 몰리면 한계가 온다. 일부 기능의 수요가 급증했는데 전체를 함께 확장해야 하는 상황이다. 그때 나오는 두 갈래다.

모놀리식

하나의 프로젝트, 하나의 프로세스에 전부 들어 있다. 전통적인 형태이고 소규모 테스트에서는 이쪽이 합리적이다. 개발 환경이 같아 복잡하지 않고, 개발과 빌드와 배포와 테스트가 쉬우며, 서비스 간 통신이 네트워크를 타지 않아 빠르다.

확장하려면 전체를 확장해야 한다. 보통 서버 스펙을 올리는 수직 확장이다. 배포도 느려서 한 줄 고쳐도 전체를 다시 빌드하고 올린다. 배포가 느린 문제는 무중단 배포로 던다.

확장 문제는 패턴 안에서도 완화할 수 있다. 멀티 모듈로 나눠두면 나중에 서비스가 커졌을 때 확장하기 쉽고, 응집도는 올라가고 결합도는 내려간다.

MSA

하나의 큰 애플리케이션을 작은 서비스 단위로 쪼개고, 각 서비스가 하나의 업무를 맡아 경량 API로 통신한다. 서비스마다 알맞은 기술과 언어를 고를 수 있고, 서버나 프로세스에 장애가 나도 격리와 복구가 쉬워 전체로 번질 가능성이 적다.

규모가 정하는 선택

모놀리식MSA
빌드와 배포느리다서비스별로 빠르다
일부 장애의 영향전체가 멈춘다그 서비스만 멈춘다
확장전체를 함께필요한 서비스만
내부 호출메서드 호출네트워크를 탄다
트랜잭션하나로 묶인다어렵다
데이터 조회조인하면 된다DB가 나뉘어 어렵다
테스트전 구간이 쉽다어렵다
이해 가능성커지면 아무도 모른다각각은 이해할 수 있다
관리단순하다어렵다

규모가 답을 정한다. 서비스가 작을 때 MSA는 과하고, 커진 뒤에는 모놀리식이 감당되지 않는다. 중간 단계로 모놀리식을 유지하면서 멀티 모듈로 나누는 선택지가 있다.

쪼갠 뒤에 남는 문제

서비스마다 로그가 따로 남으니 하나의 요청을 추적할 수 없다. ELK처럼 수집과 파싱과 시각화를 묶은 도구로 한곳에 모아 검색할 수 있게 한다. 데이터 콜렉터를 Fluentd로 바꾼 EFK 조합도 같은 자리다.

여러 서비스에 걸친 작업은 하나의 트랜잭션으로 묶을 수 없다. 그래서 묶기를 포기하고 다른 방법을 쓴다. 보상 트랜잭션은 실패했을 때 되돌리는 작업을 따로 수행해 일관성을 유지하고, 복합 서비스는 트랜잭션을 지원하는 네이티브 프로토콜로 두 시스템을 묶어 API로 노출한다. 유스케이스를 하나 두고 최종 결과가 맞는지 검증하게 하는 방법도 있다.

실무에서 가장 큰 장벽은 비용이다. DAU가 높지 않은데 무리하게 전환하면 서버와 모니터링과 로그 수집이 전부 배로 늘어 비용 폭탄을 맞는다.

관련

출처