Monolithic Architecture 그리고 MSA
MSA(Micro service Achitecture)란?
하나의 큰 어플리케이션을 여러개의 작은 어플리케이션으로 나누어서 변경, 조합이 가능하도록 만든 아키텍처 입니다.
그렇다면 마이크로 서비스 아키텍처의 등장배경은 무엇일까요? 왜 MSA가 등장하게 되었을까요?
MSA의 등장 배경
MSA의 등장배경을 이해하기 위해서는 기존방식인 Monolithic Architecture에 대해 이해하고 그문제점에 대해 이해해야 합니다.
모놀리틱 아키텍처와 마이크로 소프트 아키텍처의 차이점
모놀리틱 아키텍처는 소프트웨어의 모든 구성요소가 한 프로젝트에 통합되어 있는 구조입니다.
만약 소규모 프로젝트를 진행한다면 Monolithic Architecture가 훨씬 합리적이고 구성하기도 쉽고
이식하기도 쉬울 것입니다. 유지보수도 용이한 장점이 있습니다.
하지만 이 Monolithic Architecture는 프로젝트가 복잡해지고 커짐에 따라서 많은 단점들이 발생합니다.
- 서비스및 프로젝트의 크기가 커질수록 시스템 전체 구조를 파악하는데 어려움이 있습니다.
- 빌드 시간, 테스트 시간, 배포 시간이 기하급수적으로 늘어나게 됩니다.
- 어느 한 부분에서 장애가 일어나면 전체 서비스에 문제가 생길 가능성이 커집니다.
이러한 문제들이 발생하기 시작하면서 그 문제점을 해결하기위해 MSA가 탄생하게 되었습니다.
MSA의 특징 및 서비스를 분리하는 기준
그렇다면 MSA의 특징은 무엇이 있을까요? 서비스는 어떻게 분리를 할까요?
모놀리틱 아키텍처로 구성된 사진
이해를 돕기 위해서, 아마존(Amazon.com)과 유사한 온라인 쇼핑몰을 만든다고 가정해 보겠습니다. 기본적으로 처음 설계되는 애플리케이션의 구조는 그림 1과 같이 비즈니스 로직을 담당하고 있는 애플리케이션이 존재하고, 해당 애플리케이션은 데이터베이스 등 외부 시스템과 특정 프로토콜로 통신을 하게 됩니다. 또한, 사용자에게 인터페이스를 제공하기 위해서 HTML을 렌더링하는 부분과 RESTful API를 제공하는 부분을 갖게 됩니다. 이렇게 구성된 애플리케이션의 소스코드는 하나의 프로젝트로 구성되어 있으며 단일한 패키지로 배포되게 됩니다.
이러한 구성의 애플리케이션은 특별히 이상할 것도 없고 실제로 많은 서비스들이 이와 같은 구성으로 이루어져 있습니다. 이렇게 단순한 구성의 애플리케이션은 로컬 환경에서 개발하기에도 편리하고 통합 시나리오 테스트를 수행하기에도 가장 손쉬운 구성입니다. 또한, 모든 코드가 하나의 묶음으로 구성되어 있기 때문에 배포도 매우 간편해집니다.
하지만 이러한 단순한 애플리케이션의 아키텍처는 서비스가 지속적으로 성장하고 규모가 커질 때 한계에 부딪히게 됩니다. 예를 들어, 3명의 개발자가 몇 가지 핵심 기능을 개발할 때에는 이와 같은 모놀리틱 아키텍처가 최적의 효율성을 보장하지만 개발자의 규모가 수십에서 백명 이상이 되고 서비스의 복잡도가 증가되면 아주 간단한 기능을 하나 추가하기 위해서도 매우 많은 줄의 코드를 수정해야함은 물론, 코드의 변화가 영향을 미치는 범위가 증가되었기 때문에 간단한 변화 하나에도 통합 테스트가 필요하게 됩니다.
많은 회사에서는 이러한 문제를 해결하기 위해서 여러가지 프로세스를 도입하고 애자일 철학을 기반으로 둔 여러가지 방법론을 적용해보고자 노력합니다. 하지만 실제로 이러한 시도가 서비스 구조의 근본적인 원인을 해결하지는 못하기 때문에 좋은 성과를 거두지 못하게 됩니다. 대부분의 경우 근본적인 원인은 서비스의 구조 자체가 너무 복잡하다는 점입니다. 복잡한 구조는 서비스 초창기 부터 함께 개발을 하여 전체 히스토리를 알고 있는 소수의 개발자를 제외하고는 대부분의 개발자들이 전체적인 시스템의 구조를 알지 못하기 때문에 재활용 가능한 모듈을 무시하고 중복된 코드를 생산하게 되며 사용하지 않는 코드가 기술 부채로 계속 쌓이게 됩니다. 또한, 코드가 서로 다양한 방식으로 연관되어 있기 때문에 간단한 버그 수정이 더 큰 버그를 양산하게 되는 결과를 초래합니다.
서비스 복잡도가 증가하면서 모놀리틱 아키텍처가 가지는 문제점들은 배포 시간의 증가, 부분적 스케일 아웃의 어려움, 안정성의 감소 등 여러가지가 있습니다. 그 중에서도 굳이 한가지를 꼽자면 애플리케이션을 구성하는 프로그래밍 언어, 또는 프레임워크의 변경이 거의 불가능에 가까울 정도로 어렵다는 점 입니다. 예를 들어, 애플리케이션에서 사용자의 인증만을 담당하는 요소가 별도의 서비스로 구현되어 있다면 필요에 따라 성능과 안정성을 증가시킬 수 있는 새로운 프레임워크로 변경하는 것을 고려해볼 수 있습니다. 하지만 만약 전체 애플리케이션이 하나로 묶여 있다면 그 동안 개발된 방대한 양의 코드를 새로운 언어, 또는 프레임워크로 전환해야 하기 때문에 대부분 시도조차 할 수 없을 것 입니다.
MSA의 예시를 표현한 구조도
위그림은 마이크로서비스 아키텍처의 개략적인 모습을 몇 가지 예시로 나타낸 그림이며 이 예시는 총 4개의 마이크로 서비스로 구성되어 있습니다. 사용자 서비스는 REST API를 이용해서 주문 서비스를 활용하며 API Gateway를 통해 정보를 웹브라우저 화면에 표시하거나 모바일 클라이언트에 데이터를 제공합니다. 또한, 사용자에게 알림이 필요한 경우 실제 알림이 어떤 과정을 통해서 처리되는지 신경쓸 필요없이 알림 서비스(Notification service)를 이용하여 원하는 요청을 호출할 수 있습니다. 그림에 표시된 API Gateway는 다른 글에서 좀더 다루도록 하겠습니다.
마이크로서비스 아키텍처를 나타낸 그림에서 주목할 점은 사용자를 위한 데이터베이스와, 주문을 위한 데이터베이스가 따로 표시되어 있다는 점입니다. 이 부분은 실제로 마이크로서비스 아키텍처를 구현할 때 매우 중요한 부분인데, 전통적인 모놀리틱 아키텍처에서 주로 개발을 했던 경험에 비추어 보면 데이터의 트랜잭션 관리나 정규화 등의 관점에서 매우 비효율적으로 보일 수 있습니다.
물론, 하나의 데이터베이스를 각각의 개별 서비스가 공유해서 사용하는 방식도 가능하지만 마이크로서비스 아키텍처가 가지는 근본적인 장점을 최대한 활용하기 위해서는 이렇게 서비스별로 별도의 데이터베이스를 사용하는 것이 필요합니다. 또한, 데이터베이스(DBMS)의 종류 자체도 반드시 한가지 통일할 필요 없이 데이터의 특성과 서비스가 가지는 특수성에 따라 가장 효율적인 데이터베이스를 선택하여 사용하는 것도 가능합니다.
예를 들어, 어떤 서비스에서 사용하는 데이터는 변경이 적고 주로 읽기(read) 작업만 수행되는 반면, 또 다른 서비스의 데이터는 읽기 작업보다 빠른 속도로 쓰여지는(write) 작업이 대부분이라면 각각의 서비스 특성에 맞게 데이터베이스의 종류를 결정하고 설계할 수 있습니다.
Monolithic Architecture와 MSA의 장단점
구분 | 장점 | 단점 |
Monolithic | 개발 환경이 동일해서 복잡하지 않다. | 분산처리가 어렵다. |
Monolithic | 소수의 인원에서 빠르게 개발하기에 적합하다. | 프로젝트가 커질수록 코드가 길어지고 배포시간이 길어진다. |
Monolithic | 테스트 환경구성이 쉽고 용이하다. | 기능별로 효율적인 데이터베이스 선택및 개발언어 선택이 불가능하다. |
MSA | 각 기능별로 모듈이 독립적이기 때문에 해당 모듈에 가장 효율적인 프로그래밍 언어 선택이 가능하다. | 작은 여러 서비스로 분리되어 있기때문에 관리및 모니터링이 어렵다. |
MSA | 각 부서별로 기능별로 해야 할일을 나눠서 효율적으로 처리할 수 있다. | 서로간의 통신에러가 잦을수 있다. |
MSA | 중앙 집중적인 데이터 베이스가 없고 각 서비스에 알맞은 데이터 베이스를 선택할수 있다. | 테스트가 불편하다. End to End 테스트를 위해서 UI, API Gateway등등 여러개의 서비스를 구동 시켜야 한다. |
MSA | 새로 추가되거나 수정사항이 있는 마이크로서비스만 빠르게 빌드, 배포가 가능하다. | 서비스간의 장애가 발생하는 경우 장애 추적이 어렵다. |
MSA | 일부분의 오류가 있으면 해당 기능에만 오류가 발생하고 그 부분만 빠르게 고쳐서 정상화가 가능하다. | 각 마이크로서비스들은 독립된 데이터 저장소를 가지기 때문에 마이크로서비스들끼리 자원을 공유하고 그 공유 자원에 접근하는 것을 구현하기 어렵고, 제약 조건도 있다. |
결론
개인적으로는 마이크로 서비스 아키텍처는 이미 기존 서비스 운영을 잘하고 있고, 장애 처리나 모니터링 등을 잘하고 있는 조직이 다음 단계로 진화하는 아키텍처로 선정하는 것이 좋다고 생각합니다. 처음부터 마이크로서비스 아키텍처를 선택하면 운영 및 관리의 헬에서 빠져 나오기 어렵고 그런 오버헤드가 마이크로서비스 아키텍처의 장점을 상쇄시킬 정도로 충분히 클 가능성이 높기 때문입니다. 그리고 초기 단일체 구조 아키텍처로 시작된 작은 서비스가 서비스가 복잡해지고, 조직도 커지고, 팀원의 역량은 충분히 높아졌으면 마이크로서비스 아키텍처로의 진화를 고려하는 것이 좋을 것 같습니다.