해당 포스트는 MSA에 대한 개념과 주요 기술에 대해 알아보고 실무에 적용했었던 내용을 정리하는 포스트입니다.
1. MSA란 무엇인가
개요
마이크로서비스 아키텍처(주로 마이크로서비스라고도 함)란 애플리케이션 개발을 위한 아키텍처 스타일을 의미합니다. 마이크로서비스를 사용하면 대규모 애플리케이션을 각각 담당 영역을 가진 소규모의 독립적인 구성요소로 구분할 수 있습니다. - Google Cloud
MSA(Microservice Architecture), 마이크로서비스라고도 불리는 접근 방법은 대규모 서비스 / 어플리케이션을 여러 개의 작은 규모의 서비스 / 어플리케이션으로 나누는 접근 방식을 의미합니다.
마틴 파울러는 마이크로서비스에 대해 다음과 같이 정의하였다고 하는데 요약하자면 다음과 같습니다.
- 마이크로서비스는 여러 개의 작은 서비스 집합으로 개발하는 접근 방법
- 각 서비스는 개별 프로세스에서 실행되고 HTTP 자원 API 같은 가벼운 수단을 사용해 통신
- 또한 서비스는 비즈니스 기능 단위로 구성되고 자동화된 배포 방식을 이용하여 독립적으로 배포됨
- 또한 서비스에 대한 중앙 집중적인 관리는 최소화하고 각 서비스는 서로 다른 언어와 데이터, 저장 기술을 사용할 수 있음
오늘날 클라우드 환경에서 많이 선택되고 있는 MSA는 전통적인 모놀리식 아키텍처와 어떠한 차이점이 있을까요?
모노리스(monolith) vs 마이크로서비스(microservice)
모노리스
- 하나의 단위로 개발되는 일체식 어플리케이션
- 스케일 아웃 시 모노리스 전체가 확장
- 단일 프로세스에서 실행됨
- 로드 밸런서를 앞에 두고 여러 인스턴스 위에 큰 덩어리를 복제해 수평으로 확장
- 여러 개의 모노리스 시스템 모두를 재빌드 / 재배포해야 함
- 어플리케이션의 병렬 확장은 가능하나 데이터베이스가 통합되어 있어 탄력적 대응이 어려움
마이크로서비스
- 서버 측이 여러 개의 조각으로 구성되어 각 서비스가 별개의 인스턴스로 로딩
- 여러 서비스 인스턴스가 모여 하나의 비즈니스 어플리케이션을 구성
- 각기 저장소가 달라 업무 단위로 모듈 경계가 명확하게 구분
- 각 서비스는 또한 다른 서비스 및 저장서와 격리되어 있으며 API를 통해서만 느슨하게 연계됨
- 각 서비스를 구축하는데 사용되는 언어 / 저장소를 자율적으로 선택할 수 있음 (폴리글랏, Polyglot)
- 각 서비스는 자동화된 개발 환경에서 독립적으로 배포됨
두 방식을 비교했을 때 MSA는 모놀리식 아키텍처보다 좀 더 유연한 확장 / 스케일 아웃 / 배포가 가능하다는 장점이 있으며 기술 선택 역시 독립적으로 가능하다는 매리트가 있습니다.
또한 MSA가 클라우드 인프라 환경을 가장 효율적으로 사용할 수 있고 가장 적합하다는 사실이 알려져 많은 서비스들이 클라우드 환경으로 옮기면서 모놀리식 아키텍처에서 MSA로 변화하고 있습니다.
MSA와 클라우드 인프라 환경
사실 MSA 이전에도 이러한 접근 방식 / 이론이 등장하였다지만(SOA 등) 구체적이지 않거나 비즈니스 성공 사례가 많지 않았다는데 MSA가 각광받기 시작한 것은 클라우드 기술의 발달과 함께 클라우드 인프라 환경이 구성되면서 시작되었다고 합니다. (Netflix와 AWS)
클라우드 인프라 환경 등장 이전에는 아키텍처의 구성 요소들이 각 기업 / 특정 벤더의 제품 / 프레임워크와 강 결합되어 있었으나 클라우드 인프라의 등장 및 클라우드 환경 내에 사용되는 오픈소스와 이를 기반으로 한 상용 제품들의 호환성 덕분에 각 레이어 별로 유연하고 호환성 있는 솔루션과 오픈소스를 선택할 수 있게 되었습니다.
이로 인해 클라우드 인프라가 제공하는 이러한 이점들을 최대한 살리는, 클라우드 인프라에 가장 어울리는 어플리케이션 구조에 대한 논의가 이루어졌고, 클라우드 인프라의 특성을 닮은 클라우드 네이티브한 어플리케이션 구조로 마이크로서비스가 등장하게 되면서 MSA가 본격적으로 각광을 받게 되었다고 합니다.
MSA의 단점
하지만 MSA가 장점만 있는 것은 아닙니다. 장점과 마찬가지로 단점 역시 뚜렷하다보니 많은 전문가들이 맹목적인 MSA 도입을 지양할 것을 권고하고 있는데요. 주요 단점은 다음과 같습니다.
- 기본적으로 복잡하고 러닝 커브가 있다
일단 모놀리식 아키텍처에 비해 구조가 복잡해질 수 밖에 없고 분산 환경이라면 더더욱 복잡도가 높아질 수 밖에 없음. 거기에 MSA와 관련된 다양한 기술들을 추가로 익혀야 해서 러닝 커브가 존재함
- 테스트 / 배포 복잡성
여러 마이크로서비스가 연결되어 있는 기능을 테스트하려면 테스트 복잡도가 높아질 수밖에 없으며, 배포 절차 역시 모놀리식 아키텍처에 비해 복잡하고 배포 시 소요되는 비용이 높아질 수밖에 없음
- 데이터 관리
데이터가 여러 마이크로서비스를 거치는 경우 데이터 무결성 / 정합성 유지가 상당히 어려워지며 이를 유지하기 위해 도입하는 기술의 러닝 커브가 높은 편
- 서비스 간 의존성
마이크로서비스는 API를 통해 연결되어 있는데 API 버전에 대한 의존성이 생기며 한 마이크로서비스의 장애가 다른 서비스의 장애로도 이어질 수 있음
- 리소스 사용량 증대
모놀리식 아키텍처에 비해 리소스 사용량이 증가되어 보다 많은 비용이 발생
이러한 단점들 역시 명확하기 때문에 대부분의 전문가들은 무작정 MSA를 도입하는 것보다는 모놀리식 아키텍처로 효율적으로 할 수 있는 경우 모놀리식 아키텍처를 유지하고 MSA 도입이 필요하다면 새로운 기능을 추가할 때 작은 마이크로서비스로 만들어서 조금씩 MSA로 전환하는 것을 권장하고 있습니다.
2. MSA 구성 요소와 패턴
외부 아키텍처와 내부 아키텍처
외부 아키텍처는 마이크로서비스가 운영되는 환경을 의미하며 크게 어플리케이션 영역과 플랫폼 영역, 인프라 영역으로 나뉘어집니다.
- 어플리케이션 영역 : 플랫폼 영역 위에서 구동되는 어플리케이션 서비스 영역
- 채널 (모바일 / 브라우저), 핵심 서비스 (프론트엔드 / 백엔드), 데이터 (DB) 등
- 플랫폼 영역 : 인프라 영역 위에 올라가는 어플리케이션을 운영 및 구동하기 위한 영역
- 플랫폼 서비스 : DevOps 파이프라인, 팀 업 환경, 메시지 버스, 로깅, 라이브러리 등
- MSA 기반 서비스 : API 게이트웨이, 모니터링, 구성 관리, 서비스 탐색 등
- 인프라 영역 : 하드웨어 인프라
내부 아키텍처는 실제 비즈니스가 실행되는 내부 구조를 의미하며 마이크로서비스에서 제공하는 API나 비즈니스 로직, 이벤트 발행, 데이터 저장 처리 등에 대해 구조화한 것입니다.
인프라 구성 요소
인프라 구성 요소는 마이크로서비스가 실행되는 하부 구조 인프라를 구축하는데 필요한 구성 요소를 의미하며 환경으로 나누면 크게 퍼블릭 클라우드 IaaS, PaaS나 베어메탈 + 프라이빗 클라우드 PaaS 환경으로 나뉩니다.
플랫폼 패턴
플랫폼 패턴은 인프라 위에서 마이크로서비스의 운영과 관리를 지원하는 플랫폼 차원의 패턴으로 크게 개발 지원 환경을 위한 플랫폼 패턴과 마이크로서비스 관리 / 운영을 위한 플랫폼 패턴으로 구분할 수 있습니다.
개발 지원 환경을 위한 DevOps 인프라
마이크로서비스를 빌드, 테스트, 배포할 수 있게 도와주는 개발 지원 환경이며 이러한 인프라에서 수행하는 자동화 배포 작업을 CI / CD라고도 부릅니다.
- CI(Continueous Integration) : 지속적 통합, 개발자들이 작성한 소스 코드, 테스트 코드를 통합해서 자동으로 빌드 및 테스트
- CD(Continueous Delievery / Deployment) : 지속적 제공 / 배포, CI 이후 빌드된 소스 코드를 실행 환경에 자동으로 배포
이러한 CI / CD를 위해 마이크로서비스별로 빌드/배포 파이프라인을 설계해야 하는데, 보통의 파이프라인 절차는 다음과 같습니다.
- 리포지토리 -> 빌드/유닛 테스트 -> 정적 분석 -> 통합 테스트 -> 배포 -> 마이크로서비스
마이크로서비스 관리 / 운영을 위한 패턴들
자동화 배포 말고도 마이크로서비스를 관리하고 운영하는데에 필요한 플랫폼 패턴들 역시 존재합니다. 대표적인 패턴들은 다음과 같습니다.
- 서비스 레지스트리 패턴 : 마이크로서비스의 관리, 운영을 위해 마이크로서비스의 주소와 유동적인 IP를 매핑하여 저장하는 패턴
- 서비스 디스커버리 패턴 : 클라이언트가 여러 개의 마이크로서비스를 호출하기 위해 최적 경로를 찾아주는 라우팅 기능과 적절한 부하 분산에 필요한 로드 밸런싱을 위한 패턴
- API 게이트웨이 패턴 : 서비스 단일 진입을 위한 패턴이며 서비스 레지스트리와 연계한 동적 라우팅, 로드 밸런싱 등 다양한 기능을 제공
- BFF 패턴 (Backend for Frontend) : API 게이트웨이와 같은 진입점을 하나로 두지 않고 프론트엔드의 유형에 따라 각각 두는 패턴, API 게이트웨이 앞에 위치하며 클라이언트 종류에 맞게 최적화된 처리를 수행할 수 있도록 구성
- 외부 구성 저장소 패턴 : 각 마이크로서비스의 외부 환경 설정 정보를 분리하여 외부 구성 저장소에 저장하고 일관되게 변경 가능하도록 관리하는 패턴
- 인증 / 인가 패턴 : 중앙 집중식 세션 관리 패턴과 API 게이트웨이와 클라이언트 토큰을 활용한 패턴으로 나뉨
- 서킷 브레이커 패턴 : 장애가 발생한 서비스를 격리하여 유연하게 처리하기 위한 패턴
- 모니터링과 추적 패턴 : 서비스 상태를 모니터링하고 서비스 간 트랜잭션의 호출을 추적하기 위한 패턴
- 중앙화된 로그 집계 패턴 : 로그를 스트림 형태로 처리하며 서비스는 스트림의 전달 / 저장에 관여하지 않게끔 하는 패턴, ELK(Elasticsearch-Logstash-Kibana) / EFK(Elasticsearch-Fluentd-Kibana) / PLG(Promtail-Loki-Grafana) 등이 있음
어플리케이션 패턴
어플리케이션 패턴은 마이크로서비스 어플리케이션을 구성하는데 필요한 패턴으로 마찬가지로 다양한 패턴들이 존재합니다.
- UI 컴포지트 패턴 또는 마이크로 프론트엔드(MFA) : 백엔드 마이크로서비스처럼 프론트엔드 역시 기능별로 분리, 이를 조합하기 위한 프레임 형태의 부모 창을 통해 프론트엔드를 조합해서 동작하게 하는 패턴
- 마이크로서비스 동기 통신 및 비동기 통신 : 마이크로서비스 간 호출 시 동기식 호출을 먼저 검토하며 비동기식 처리가 필요할 경우 메시지 브로커를 이용하여 처리
- 비동기 방식의 이벤트 기반 아키텍처 : 분산 시스템 간에 발신자 - 수신자가 이벤트 (상태의 변화 등) 를 주고 받으며 처리하는 시스템 아키텍처
- 저장소 분리 패턴 : 각 마이크로서비스가 각자의 비즈니스를 처리하기 위한 데이터를 직접 소유하는 패턴
- 분산 트랜잭션 처리 패턴 - Saga 패턴 : 각 서비스의 로컬 트랜잭션을 순차적으로 처리하며 여러 개의 분산된 서비스를 하나의 트랜잭션으로 묶지 않고 각 로컬 트랜잭션과 보상 태른잭션을 이용, 비즈니스 및 데이터의 정합성을 맞춤
- 읽기와 쓰기를 분리하는 CQRS(Command Query Responsibility Segregation, 명령 조회 책임 분리) 패턴 : 저장소에 쓰기 모델과 읽기 모델을 분리시키거나 물리적으로 저장소를 분리시킴
- 이벤트 소싱 패턴 : 쓰기에 최적화되어 있으며 트랜잭션 자체를 저장, 즉 상태 변경 이벤트를 계산해서 데이터 모델로 변경하지 않고 바로 이벤트 저장소에 그대로 저장하는 것
3. 정리
지금까지 MSA의 개념과 장단점, 주요 패턴에 대해 간단히 알아봤는데 중요한 내용을 요약하자면 다음과 같습니다.
- MSA는 대규모 서비스 / 어플리케이션을 여러 개의 작은 규모의 서비스 / 어플리케이션으로 나누는 접근 방식입니다.
- 각 서비스는 비즈니스 기능 단위로 구성되고 다양한 언어 / 기술을 사용해 개발되고 자동화된 배포 방식을 이용해 독립적으로 배포되며, 개별 프로세스에서 실행되고 API나 메시지 브로커 등의 가벼운 수단을 사용해 통신합니다.
- MSA의 구성 요소는 크게 외부 아키텍처와 내부 아키텍처로 나뉘며 외부 아키텍처에는 어플리케이션 영역 / 플랫폼 영역 / 인프라 영역으로 나뉘고 내부 아키텍처는 API나 비즈니스 로직, 이벤트 발행 및 데이터 저장 처리 등에 대해 구조화한 것입니다.
- MSA를 구성하거나 운영 / 관리하는데 필요한 외부 아키텍처와 내부 아키텍처와 관련된 다양한 패턴들이 존재합니다.
- 마이크로서비스는 클라우드 인프라 환경에서 클라우드 네이티브한 특성(독립적으로 분리되어 배포될 수 있는 조각으로 구성)을 가지고 있으며 좀 더 유연한 확장 / 스케일 아웃 / 독립적인 개발 / 배포가 가능하다는 장점이 있습니다.
- 다만 단점 역시 뚜렷한데 기본적으로 아키텍처 자체가 복잡할 수 밖에 없고 러닝 커브가 있으며 테스트 및 배포 복잡성이 존재하고 데이터 관리가 어려워지며 서비스 간 의존성이 높아지는 단점이 있습니다.
- 따라서 많은 전문가들이 MSA는 모놀리식 아키텍처로 효율적으로 서비스를 운영할 수 있다면 무리하게 도입하는 것보다는 새로운 기능을 추가할 때 작은 마이크로서비스를 만들어 시범적으로 운영해보고 전환하는 것을 권장하고 있습니다.
여담 - 필자는 MSA에 대해 어떻게 알게 되었는지?
저는 독학을 할 때만 해도 MSA에 대해서는 잘 알지 못하고 다만 멀티 모듈 프로젝트 정도만 알고 있었는데요.
제가 입사한 회사에서 모놀리식 아키텍처로 구성된 서비스를 MSA로 전환하게 되면서 자연스럽게 공부를 하게 되었습니다.
저희 회사 내부 사정에 대해서는 전부 이야기 할 수는 없으나, MSA로 전환하게 된 가장 큰 이유를 설명드리자면 유연한 확장 / 탄력성 및 고가용성 때문이었습니다.
평상시에 트래픽이 꾸준히 많이 들어오는 것은 아니지만 일정 시즌 대규모의 트래픽 (1만명에서 10만명 수준)이 몰리는 경우가 많고 이러한 시즌 외에도 비정기적으로 대규모의 트래픽이 발생하는 상황이 몇 년 간 자주 있었다고 하는데
스케일 업만으로는 대규모 트래픽으로 발생하는 부하를 막을 수 없었고 Cafe24에 올라가 있는 서비스 특성 상 스케일 아웃도 자유롭게 할 수 없는 상황이었던지라 결국 유연한 스케일 아웃과 고가용성을 위해 클라우드 인프라 환경으로의 이전 및 MSA로의 전환을 결심하게 되었습니다.
그렇게 공부를 시작하면서 MSA로 서비스를 이전하는 프로젝트를 현재 3개월 넘게 진행하고 있는 상황인데 여기서 알게 된 지식이나 고민, 문제 해결 사례 등을 이 포스트 시리즈에 조금씩 지속적으로 녹여볼 생각입니다.
Appendix. 출처
도메인 주도 설계로 시작하는 마이크로서비스
마이크로서비스 패턴