1. 마이크로 서비스 아키텍처 (Micro Service Architecture)란?
마이크로 서비스 아키텍처는 대용량 웹 서비스가 많아짐에 따라 정의된 아키텍처인데, SOA (Service Oriented Architecture)에 근간을 두고 대용량 웹 서비스 개발에 맞는 구조로 사상이 경량화되고 대규모 개발팀의 조직 구조에 맞도록 변형된 아키텍처이다.
2. 마이크로 서비스 아키텍처의 구조
아래의 그림처럼 각 컴포넌트는 서비스라는 형태로 구현되고 API를 이용하여 타 서비스와 통신을 한다.
배포 구조 관점에서도 각 서비스는 독립된 서버로 타 컴포넌트와의 의존성 없이 독립적으로 배포된다. 아래 그림처럼 앞 단에 로드 밸런서를 배치하여 서비스 간의 로드를 분산시킨다.
데이터의 저장 관점에서도 중앙 집중화된 하나의 통 데이터베이스를 사용하는 것이 아니라 서비스 별로 데이터베이스를 사용한다. 보통 모노리틱 아키텍처 서비스는 하나의 전체 데이터베이스를 사용하는 경우가 일반적이지만, 마이크로 서비스 아키텍처의 경우 서비스가 API에서 데이터베이스까지 분리되는 수직적 분할 원칙에 따라서 독립된 데이터베이스를 가진다.
이렇게 독립된 데이터베이스를 가지게 되면 각 서비스에 따라 데이터베이스의 종류 자체를 다르게 사용할 수도 있다. 허나 데이터의 분산으로인해 트랜잭션 문제가 발생할 수 있다.
3. API Gateway
API Gateway는 마치 프락시 서버처럼 API들 앞에서 모든 API에 대한 엔드 포인트를 통합하고 몇 가지 추가적인 기능을 제공하는 미들웨어로, SOA의 ESB(Enterprise Service Bus)의 경량화 버전이다.
API Gateway가 수행하는 기능
- 엔드포인트 통합 및 토폴로지 정리
마이크로 서비스 아키텍처의 문제점 중 하나는 각 서비스가 다른 서버에 분리, 배포되기 때문에 API의 엔드포인트, 즉 서버의 URL이 각기 다르다는 것이다. 이는 API 사용자 관점에서도 사용하기가 불편하고, API를 사용하는 클라이언트에서 서버 간의 통신이나 API 통신은 P2P(Point to Point)형태로 토폴로지가 복잡해져 향후 관리의 문제를 일으킬 수 있다.
이러한 토폴로지의 문제점을 해결하기 위해 중앙에 서비스 버스와 같은 역할을 하는 채널을 배치 시켜서 전체 토폴로지를 P2P에서 Hub & Spoke 방식으로 변환시켜 서비스 간 호출을 단순화 할 수 있다.
- 오케스트레이션 (Orchestration)
여러 개의 서비스를 묶어서 하나의 새로운 서비스를 만드는 개념이다. 예를 들어, 포인트 적립과 물품 구매라는 서비스가 있을 때 이 두 개의 서비스를 묶어 '물품 구매 시 포인트 적립' 이라는 새로운 서비스를 만들어 낼 수 있다. 오케스트레이션의 활용은 API Gateway 계층에서 부담되는 일이다. 그래서 마이크로 서비스 아키텍처에 대한 높은 이해와 API Gateway 자체에 대한 높은 수준의 기술적인 이해가 필요하다.
- 공통 기능 처리
API에 대한 인증이나 로깅과 같은 공통 기능에 대해 API Gateway에서 처리하게 되면, API 자체는 비즈니스 로직에만 집중하여 개발 중에 발생할 수 있는 중복을 방지할 수 있다.
- 중재 (Mediation)
XML이나 네이티브 메시지 포맷을 JSON 등으로 상호 변환해주는 메시지 변환 기능이나 프로토콜 변환 기능, 서비스 간의 메시지를 라우팅해주는 기능 등 여러 가지 고급 중재 기능을 제공하지만, API Gateway를 최대한 가볍게 가져간다는 설계 원칙 아래에서 될 수 있으면 고급 중재 기능을 사용할 때에는 높은 수준의 설계와 기술적인 노하우를 동반해야 한다.
4. 마이크로 서비스 아키텍처의 문제점
A. 성능
마이크로 서비스 아키텍처는 서비스 간의 호출을 API 통신을 이용하기 때문에 값을 JSON이나 XML에서 프로그래밍에서 사용하는 데이터 모델로 변환하는 마샬링 오버헤드가 발생하고 호출을 위해서 메시지들이 네트워크를 통해서 전송하기 때문에 그만큼 시간이 추가로 소요된다.
B. 메모리
마이크로 서비스 아키텍처는 각 서비스를 독립된 서버에 분할 배치하기 때문에 중복되는 모듈에 대해서 그만큼 메모리 사용량이 늘어난다. (TOMCAT 운영의 메모리, 스프링 프레임워크 등) 허나, 요즘에 들어서는 컴퓨터 파워 자체(하드웨어 기술력)가 워낙 발달하여 크게 문제 되지 않는 부분이다.
C. 테스팅의 어려움
각각의 서비스들이 분리되어 있어 특정 사용자 시나리오나 기능을 테스트하고자 할 경우 여러 서비스에 걸쳐서 테스트를 진행해야하는 점에 있어 테스팅의 복잡도가 올라간다.
D. 운영 관점의 문제
시스템이 아주 잘게 서비스 단위로 쪼개지기 때문에 운영해야 할 대상 시스템의 개수가 늘어나고 필요한 기술의 수도 늘어나게 된다.
E. 서비스 간 트랜잭션 처리
모노리틱 아키텍처에서는 애플리케이션 내에서 트랜잭션이 문제가 있으면 쉽게 데이터베이스의 기능을 이용해서 롤백할 수 있었다. 허나 마이크로 서비스 아키텍처에서 API 기반의 여러 서비스를 하나의 트랜잭션으로 묶는 것은 거의 불가능하다.
이러한 문제를 해결하기 위해서 몇 가지 방안이 있는데, 첫 번째 방법으로는 아예 애플리케이션 디자인 단계에서 여러 개의 API를 하나의 트랜잭션으로 묶어 분산 트랜잭션 시나리오 자체를 없애는 것이다. 또는 트랜잭션 처리가 필요한 경우, 트랜잭션 실패 시 이를 애플리케이션으로 처리해 줘야 하는데, 이를 보상 트랜잭션(Compensation Transaction)이라고 한다.에러가 발생할 경우 명시적으로 에러 처리 로직을 구현해야 한다.
참조 저서 : 조병욱(조대협), 대용량 아키텍처와 성능 튜닝, 프리렉 출판, 95쪽