마이크로서비스 아키텍처(Microservices architecture; MSA)
개념
- 마이크로서비스 아키텍처는 하나의 큰 애플리케이션을 여러 개의 작은 애플리케이션으로 쪼개어 변경과 조합이 가능하도록 만든 아키텍처를 말합니다.
- 애플리케이션을 특화된 기능별로 나누게 되면 자연스럽게 애플리케이션의 추상화(abstraction)가 가능해집니다. 다시 말해, ‘인증’을 담당하는 서비스(예, auth.example.com)는 그 구체적인 구현 내용을 모르더라도 다른 서비스에서 약속된 인터페이스를 이용해 인증 과정을 수행할 수 있습니다. 또한, 검색창의 ‘자동완성’을 담당하는 서비스(예, autocomplete.example.com)는 사용자의 입력을 받아서 자동완성 결과만을 응답해주면 되기 때문에 해당 API를 유지한 상태에서 세부적인 구현내용을 언제든지 손쉽게 개선하고 변경할 수 있습니다.
- 모든 기술의 발전이 다 그렇듯이 마이크로서비스 역시 기존에 없다가 갑자기 등장한 개념은 아닙니다. 많은 기업들에서는 이미 이와 같은 방식으로 서비스를 분리하여 애플리케이션을 만들었으며 그때 그때 다양한 용어로 이름 붙여져 왔습니다. 그러나 최근 들어, REST API의 일반화, 도커(Docker)와 같은 컨테이너 기술, 클라우드 컴퓨팅 환경의 발전 등에 힘입어 마이크로서비스는 좀 더 손쉽게 구현될 수 있게 되었습니다.
- 마이크로서비스를 사용하면 서비스를 잘게 분리함으로써 애자일한 개발 환경과 점점 더 복잡해지는 애플리케이션에서 분명한 이점이 있습니다. 동시에, 서비스를 분리하면서 생기는 단점도 존재합니다.
마이크로 서비스 아키텍처를 사용하면 좋은 서비스
- 애플리케이션의 배포에 한 시간 이상 소요된다.
- 단순한 기능 하나를 수정해도 전체 기능에 대한 QA가 필요하다.
- 단순한 버그 수정이 더 중대한 버그를 생산하는 일이 많아졌다.
- 현재의 애플리케이션을 기능별로 나눈다고 가정했을 때 수십개의 마이크로서비스가 가능하다.
모놀리틱 아키텍처 (MONOLITHIC ARCHITECTURE) - 통 서버
마이크로서비스 아키텍처를 잘 이해하기 위해서는 먼저, 반대되는 개념인 모놀리틱(Monolithic) 아키텍처에 대해서 살펴볼 필요가 있습니다. 이해를 돕기 위해서, 아마존(Amazon.com)과 유사한 온라인 쇼핑몰을 만든다고 가정해 보겠습니다. 기본적으로 처음 설계되는 애플리케이션의 구조는 그림 1과 같이 비즈니스 로직을 담당하고 있는 애플리케이션이 존재하고, 해당 애플리케이션은 데이터베이스 등 외부 시스템과 특정 프로토콜로 통신을 하게 됩니다. 또한, 사용자에게 인터페이스를 제공하기 위해서 HTML을 렌더링하는 부분과 RESTful API를 제공하는 부분을 갖게 됩니다. 이렇게 구성된 애플리케이션의 소스코드는 하나의 프로젝트로 구성되어 있으며 단일한 패키지로 배포되게 됩니다.
그림 1. 모놀리틱 아키텍처
이러한 구성의 애플리케이션은 특별히 이상할 것도 없고 실제로 많은 서비스들이 이와 같은 구성으로 이루어져 있습니다. 이렇게 단순한 구성의 애플리케이션은 로컬 환경에서 개발하기에도 편리하고 통합 시나리오 테스트를 수행하기에도 가장 손쉬운 구성입니다. 또한, 모든 코드가 하나의 묶음으로 구성되어 있기 때문에 배포도 매우 간편해집니다.
하지만 이러한 단순한 애플리케이션의 아키텍처는 서비스가 지속적으로 성장하고 규모가 커질 때 한계에 부딪히게 됩니다. 예를 들어, 3명의 개발자가 몇 가지 핵심 기능을 개발할 때에는 이와 같은 모놀리틱 아키텍처가 최적의 효율성을 보장하지만 개발자의 규모가 수십에서 백명 이상이 되고 서비스의 복잡도가 증가되면 아주 간단한 기능을 하나 추가하기 위해서도 매우 많은 줄의 코드를 수정해야함은 물론, 코드의 변화가 영향을 미치는 범위가 증가되었기 때문에 간단한 변화 하나에도 통합 테스트가 필요하게 됩니다.
많은 회사에서는 이러한 문제를 해결하기 위해서 여러가지 프로세스를 도입하고 애자일 철학을 기반으로 둔 여러가지 방법론을 적용해보고자 노력합니다. 하지만 실제로 이러한 시도가 서비스 구조의 근본적인 원인을 해결하지는 못하기 때문에 좋은 성과를 거두지 못하게 됩니다. 대부분의 경우 근본적인 원인은 서비스의 구조 자체가 너무 복잡하다는 점입니다. 복잡한 구조는 서비스 초창기 부터 함께 개발을 하여 전체 히스토리를 알고 있는 소수의 개발자를 제외하고는 대부분의 개발자들이 전체적인 시스템의 구조를 알지 못하기 때문에 재활용 가능한 모듈을 무시하고 중복된 코드를 생산하게 되며 사용하지 않는 코드가 기술 부채로 계속 쌓이게 됩니다. 또한, 코드가 서로 다양한 방식으로 연관되어 있기 때문에 간단한 버그 수정이 더 큰 버그를 양산하게 되는 결과를 초래합니다.
서비스 복잡도가 증가하면서 모놀리틱 아키텍처가 가지는 문제점들은 배포 시간의 증가, 부분적 스케일 아웃의 어려움, 안정성의 감소 등 여러가지가 있습니다. 그 중에서도 굳이 한가지를 꼽자면 애플리케이션을 구성하는 프로그래밍 언어, 또는 프레임워크의 변경이 거의 불가능에 가까울 정도로 어렵다는 점 입니다. 예를 들어, 애플리케이션에서 사용자의 인증만을 담당하는 요소가 별도의 서비스로 구현되어 있다면 필요에 따라 성능과 안정성을 증가시킬 수 있는 새로운 프레임워크로 변경하는 것을 고려해볼 수 있습니다. 하지만 만약 전체 애플리케이션이 하나로 묶여 있다면 그 동안 개발된 방대한 양의 코드를 새로운 언어, 또는 프레임워크로 전환해야 하기 때문에 대부분 시도조차 할 수 없을 것 입니다.
장점
모놀리식 아키텍처의 장점은 ‘심플함’입니다. 모든 것이 하나의 프로젝트에 들어가있기 때문에 개발, 빌드, 배포, 테스트가 용이합니다.
- 개발 환경과 개발 방법이 통일되어 있으므로 복잡할 게 없습니다.
- 기존 IDE와 툴을 이용해 개발하기가 용이합니다(각종 툴이 싱글 애플리케이션 개발에 초점이 맞춰져 있음).
- End-to-End 테스트가 쉽습니다.
- 배포가 간편합니다(빌드 결과를 WAS에 올리기만 하면 됨).
- 같은 애플리케이션을 여러개 두고 로드 밸런서를 앞에 두는 방법으로 쉽게 확장(scale)할 수 있습니다.
단점
하지만 이러한 장점은 애플리케이션이 간단하거나 규모가 작을 때의 이야기입니다. 시간이 지나면서 애플리케이션은 크고 복잡해집니다. 추가 요구사항, 새로운 기능들을 구현하면서 코드 양은 점점 늘어가면서 문제점이 드러나기 시작합니다.
- 양이 늘어나고 복잡해지면서 대부분의 개발자가 전체를 이해하지 못하게 됩니다.
- 코드 전체를 이해하고 있지 못하기 때문에 버그를 수정하기 어렵고, 수정하더라도 의도하지 않은 새로운 버그를 만들어내곤 합니다.
- 애플리케이션 기동 시간도 늘어나고, 빌드 돌리는 시간도 한나절입니다. 이런 상태에서는 지속적인 통합(continuous integration;CI)과 지속적인 배포(continuous delivery;CD)는 불가능에 가깝습니다.
- 여러 모듈이 함께 존재하기 때문에 각 모듈별 특성에 맞는 하드웨어 확장(scale-out)을 하기 어렵습니다.
- 전체 프로세스가 하나의 프로세스에서 돌기 때문에 안정성에도 문제가 있습니다. 해당 프로세스에서 메모리 누수(memory leak)가 일어나거나 프로세스가 죽는 경우, 버그가 발생하는 경우 등 모든 영향을 한꺼번에 받습니다.
- 새로운 기술, 언어, 프레임워크 등을 적용하기 어렵습니다. 부분적으로 들어내는 것이 어렵기 때문에 기술 노후가 올 때까지 냅두게 되고, 한참 뒤에야 차세대 프로젝트로 전체를 갈아엎게 됩니다. 이렇게 전체를 갈아엎는 것 자체가 상당히 경제적으로도 리스크적으로도 비용이 큰 일입니다.
마이크로서비스 아키텍처 (MICROSERVICE ARCHITECTURE)
마이크로서비스 아키텍처 패턴은 그 이름에서도 유추할 수 있듯이 모놀리틱 아키텍처로 구성된 하나의 큰 서비스를 독립적인 역할을 수행하는 작은 단위의 서비스로 분리하여 설계하는 패턴을 말합니다. 여기에서 말하는 독립적인 역할이란 주로, ‘사용자 관리’, ‘주문 관리’, ‘결제 관리’, ‘알림 관리’와 같이 기능적인 요소를 의미합니다. 각각의 마이크로서비스는 그 크기만 작을 뿐, 자세히 살펴보면 각각이 하나의 모놀리틱 아키텍처와 유사한 구조를 갖습니다. 다만, 하나의 서비스에서 처리해야 하는 기능과 규모가 작기 때문에 이를 마이크로서비스라고 부릅니다.
그림 2 마이크로서비스 아키텍처
그림 2는 마이크로서비스 아키텍처의 개략적인 모습을 몇 가지 예시로 나타낸 그림이며 이 예시는 총 4개의 마이크로 서비스로 구성되어 있습니다. 사용자 서비스는 REST API를 이용해서 주문 서비스를 활용하며 API Gateway를 통해 정보를 웹브라우저 화면에 표시하거나 모바일 클라이언트에 데이터를 제공합니다. 또한, 사용자에게 알림이 필요한 경우 실제 알림이 어떤 과정을 통해서 처리되는지 신경쓸 필요없이 알림 서비스(Notification service)를 이용하여 원하는 요청을 호출할 수 있습니다. 그림에 표시된 API Gateway는 뒷쪽에서 자세히 설명하도록 하겠습니다.
마이크로서비스 아키텍처를 나타낸 그림에서 주목할 점은 사용자를 위한 데이터베이스와, 주문을 위한 데이터베이스가 따로 표시되어 있다는 점입니다. 이 부분은 실제로 마이크로서비스 아키텍처를 구현할 때 매우 중요한 부분인데, 전통적인 모놀리틱 아키텍처에서 주로 개발을 했던 경험에 비추어 보면 데이터의 트랜잭션 관리나 정규화 등의 관점에서 매우 비효율적으로 보일 수 있습니다. 물론, 하나의 데이터베이스를 각각의 개별 서비스가 공유해서 사용하는 방식도 가능하지만 마이크로서비스 아키텍처가 가지는 근본적인 장점을 최대한 활용하기 위해서는 이렇게 서비스별로 별도의 데이터베이스를 사용하는 것이 필요합니다. 또한, 데이터베이스(DBMS)의 종류 자체도 반드시 한가지 통일할 필요 없이 데이터의 특성과 서비스가 가지는 특수성에 따라 가장 효율적인 데이터베이스를 선택하여 사용하는 것도 가능합니다. 예를 들어, 어떤 서비스에서 사용하는 데이터는 변경이 적고 주로 읽기(read) 작업만 수행되는 반면, 또 다른 서비스의 데이터는 읽기 작업보다 빠른 속도로 쓰여지는(write) 작업이 대부분이라면 각각의 서비스 특성에 맞게 데이터베이스의 종류를 결정하고 설계할 수 있습니다.
장점
애플리케이션을 서비스 단위로 나눠서 얻게 되는 장점을 정리하면 다음과 같습니다.
- 서비스 별로 집중해서 독립적으로 개발할 수 있습니다.
- 서비스 별로 독립적이기 때문에 소스를 이해하고 수정 및 유지보수가 쉬워집니다.
- 서비스 별로 외부에는 API 만 노출되기 때문에 내부적으로는 어떻게 구성하든 상관없습니다. 따라서 각 서비스별 특성에 맞게 기술 스택을 결정할 수 있고, 새로운 기술을 적용할 수도 있습니다.
- 서비스 별로 독립적인 배포 및 확장이 가능합니다.
- 서비스 별로 특성에 맞는 리소스를 선택해 하드웨어를 구성할 수 있습니다.
단점
하지만 나누는 것이 무조건 좋은 것은 아닙니다. 보시면 아시겠지만 간단한 애플리케이션이라면 굳이 나눌 필요가 없습니다. 분산 환경이 되면서 서비스 간 통신, 분산 데이터 처리 등 없어도 될 일들을 만드는 꼴입니다.
- 서비스를 나눠서 서비스 간 통신 방법이 필요합니다.
- 서비스를 나눠서 서비스간 호출이 모놀리스보다 복잡합니다.
- 서비스를 나눠서 데이터 중복이 발생할 수 있고 정합성을 보장하기 어렵습니다.
- 서비스를 나눠서 테스트가 어렵습니다.
- 서비스를 나눠서 특정 서비스가 실패하더라도 나머지 서비스는 유지되기 때문에 서비스가 실패했을 때를 고려해서 개발해야 합니다.
- 서비스를 나눠서 배포하는 것이 복잡합니다. 서비스 디스커버리(Service discovery)[2]가 필요하고 배포를 자동화하기가 쉽지 않습니다.
Microservices vs. SOA
표면적으로 마이크로서비스 아키텍처 패턴과 SOA 와 유사하게 보입니다. SOA 또한 애플리케이션을 서비스로 나눈다는 점에서 비슷합니다. 여기서 관건은 나뉜 서비스들을 어떻게 연결할 것이냐는 겁니다.
먼저 SOA 는 애플리케이션을 서비스로 나눈 후 ESB(Enterprise Service Bus)라는 미들웨어에서 연결하고 조립해서 만들어내는 아키텍처입니다.
https://byline.network/2016/12/1-490/
SOA 의 실패에는 ESB 가 큰 역할을 했습니다. SOA 의 인기에 힘입어 벤더들이 파는 다양한 솔루션과 장비들로 인해 SOA 를 구성하는 것이 어려워지고, 인기가 식어감에 따라 SOA 는 더 이상 발전하지 못했습니다. 하지만 마이크로서비스는 중앙집중적인 ESB 대신 REST API 또는 경량화된 메시징을 이용해서 각 서비스 중심으로 처리합니다.
엔터프라이즈 IT 업계에서 시작된 SOA 의 개념은 근래의 대형 인터넷 업체들을 중심으로 이어져 서비스와 API 기반의 MSA 로 정립되었습니다. 구축된 API 는 외부로 오픈해서 다른 서비스와 함께 더 큰 가치를 만들거나 판매할 수도 있습니다.
참고
- https://futurecreator.github.io/2018/09/14/what-is-microservices-architecture/
- http://guruble.com/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4microservice-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B7%B8%EA%B2%83%EC%9D%B4-%EB%AD%A3%EC%9D%B4-%EC%A4%91%ED%97%8C%EB%94%94/