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