0. 개요
CloudPlatform이 새로운 시작을 맞이했습니다. 세미나 이후 지진부진할 수밖에 없던 지난 날을 자각하고, 문제가 되었던 요소를 재정비 하기로 했습니다. 그 중 가장 시급한 MSA 환경 구축을 우선적으로 작업하려 합니다.
하지만 MSA를 이븐~하게 구축하기 위해 먼저 그 요소들에 대해 이해하고, 팀원들 간의 개념정리 미숙으로 인한 소통문제를 최소화하고자 합니다.
현 시점 MSA 설계 표준은 Gatner에서 제시한 Inner & Outer Archtecture 를 따라갑니다. 우리는 이 두가지 관점에서의 Microservice Archtecture의 관심사를 한번에 정리하려 했으나 Inner Architecture에서 중점적으로 다루는 설계 방법론과 같은 내용은 다소 심도가 깊은 부분이라 따로 정리하는 편이 좋을 것 같다고 생각했습니다.
이에 따라 이번 포스팅에서는 Outer Archtecture 에서의 용어에 대한 정리와 우리 Cloud Platform이 Spring Cloud 기반으로 구축해야 하는 기술들에 대해 아주 간략하게 정리하겠습니다.
간단하게 말하자면 MSA 환경에서 자주 사용되는 용어를 제가 이해하기 쉬운 언어로 정리해보겠습니다.
1. Outer Architecture
CI/CD
- 코드 변경 사항을 자동으로 빌드, 테스트, 배포하는 프로세스로 CI는 코드 통합과 테스트를 CD는 배포 자동화를 담당합니다.
- 모놀리식 애플리케이션에서도 애자일한 환경을 위해 빠르고 효율적인 배포 파이프라인은 필수였습니다. MSA환경에서는 각 서비스가 개별적으로 배포되어 CI/CD 자동화를 필수적으로 구축해야 합니다.
Config 서버 (Configuration Management)
- 애플리케이션 설정을 중앙에서 관리하는 시스템입니다.
- 마이크로 서비스의 설정을 일일이 관리하기 어려워지면서 Config Server라는 중앙에서 통합적으로 관리합니다.
- 단적인 이점으로 중복되는 설정에 대한 통합관리로 인한 유지보수성 증가, Config 설정과 마이크로서비스의 독립적인 배포 등의 이점이 있습니다.
- Config Server의 장애가 애플리케이션으로 전파될 수 있기 때문에 이 점을 주의해야 할 것 같습니다.
Service Discovery
- DNS 서비스
- 기존 모놀리식 아키텍처에서는 모든 서비스가 같은 서버 내에서 동작했기 때문에, 서비스 위치(IP, 포트)가 변하지 않았습니다. 하지만 MSA에서의 컨테이너 기반 환경에서는 서비스의 위치가 동적으로 변경됩니다.
- 이 지점에서 현재 우리의 단기목표는 docker compose를 통해 서비스를 올리는 것이기 때문에 Docker Compose의 기본 네트워크 DNS 기능으로 서비스 검색이 가능하지 않을까 생각했습니다.
- 하지만 Docker Compose 환경에서는 서비스 추가, 삭제, 변경이 발생할 때마다 수동으로 네트워크 설정을 수정해야 하며, 컨테이너를 스케일 아웃하면 DNS 기반 라우팅만으로는 부하 분산이 제대로 이루어지지 않는다는 단점이 있습니다.
- 이 외에도, 장기적으로 Kubernetes와 같은 컨테이너 오케스트레이션 환경으로 확장할 가능성을 열어둔 우리의 시스템에서는 원활한 서비스 검색과 부하 분산을 유지할 수 있도록 초기부터 서비스 디스커버리를 구축하는 것이 바람직합니다.
API Gateway
- 클라이언트가 각각의 마이크로서비스에 직접 요청을 보내면, 인증, 보안, 로깅, 트래픽 제어가 어려워집니다. 이에 따라 여러 개의 API를 통합하고 관리하는 단일 진입점이 필요합니다.
- 우리 서비스의 경우 Blood가 이 역할을 담당합니다.
Load Balancer
- 여러 서버로 트래픽을 균등하게 분산하여 부하를 조절
Service Mesh
- 서비스메쉬도 게이트웨이처럼 통신에 대한 관측가능성, 보안 등을 추구한다 하지만 다른 점은 게이트웨이가 외부로부터 시작된 요청에 대한 처리를 담당한다면 서비스메쉬는 내부 서비스들 간의 통신을 담당한다
- 트래픽 제어, 보안, 모니터링을 강화
- 즉 service to service communication 의 책임을 갖는다
- 게이트웨이의 관심사는 애플리케이션의 헬스체크에 강점이있다
- 응답하는데 얼마나 걸리는지 혹은 어떤 api가 down인지 등
- 서비스메쉬는 내부적인 마이크로서비스의 특정한 서비스의 장애와 같이 세부적인 트러블슈팅을 가능케한다
- https://www.solo.io/topics/service-mesh/service-mesh-vs-api-gateway
Telemetry
- 로그 + 메트릭 + 트레이싱 수집하고 분석하여 실시간 모니터링하는 기술.
- 서비스의 성능, 오류, 트래픽 패턴을 종합적으로 분석할 수 있습니다.
Logging
- 애플리케이션과 시스템의 이벤트를 기록하여 문제를 진단하고 분석합니다. MSA환경에서는 중앙집중식으로 로그를 관리하는 것이 필요합니다.
Metrics
- CPU, 메모리, 요청 수, 응답 시간 등 시스템 성능을 수치로 측정합니다. 전체적인 리소스 사용량, 단일 서비스의 리소스 사용량 등 모니터링할 수 있습니다.
Tracing
- 마이크로서비스 환경에서 서비스 간 요청 흐름을 추적하여 성능을 분석하는 기술입니다. 마이크로 서비스 환경에서 하나의 트랜잭션이는 클라이언트의 하나의 요청이 여러 서비스를 거쳐갈 수 있습니다.
- 이에 따라 서비스 간 요청(Request) 이 어떻게 전달되는지 추적하는 기술이 필요합니다.
- 각 서비스의 응답 시간과 병목 지점을 분석할 수 있고, 분산 트랜잭션을 시각화할 수 있습니다.
APM (Application Performance Monitoring)
- 애플리케이션의 성능을 실시간으로 분석하고 장애 원인을 파악하는 모니터링 도구
Health Check
- 서비스가 정상적으로 동작하는지 주기적으로 확인하는 기능입니다. Spring Boot Actuator 같은 기능으로 상태를 감지할 수 있음.
회복성 패턴
- MSA 환경에서 문제가 발생했을 때 특정 서비스가 죽어버릴 수 있습니다.
- 그럼 이 서비스에 문제가 생겼다는 것을 빠르게 알아차리고 복구해야 피해를 최소화할 수 있는 것은 자명합니다.
- 이를 위해 회복성 패턴(Resilience Patterns)을 사용하여 시스템이 장애를 효과적으로 처리하고 정상적으로 복구될 수 있도록 합니다.
Circuit Breaker
- 실패가 반복되는 서비스에 대한 호출을 자동으로 차단하여 전체 시스템 장애를 방지합니다. 장애가 지속되는 서비스에 요청이 계속해서 가면 시스템 과부하가 발생합니다. 이에 따라 문제가 발생했을 때 바로 차단시키는 시스템이 필요합니다.
Bulkhead
- 서비스 또는 스레드를 격리하여 특정 기능의 장애가 전체 시스템에 영향을 주지 않도록 함.
- 하나의 서비스 장애가 전체 시스템을 방지하기 위해 스레드 풀을 분리하고, 컨테이너를 격리할 수 있습니다.
- Circuit Breaker와 Bulkhead 패턴의 차이에 대해 모호한 점이 있기에 차후에 자세하게 다뤄보도록 하겠습니다.
Retry
- 일시적인 네트워크 오류나 서비스 불안정이 발생했을 때 재시도하여 요청이 성공할 가능성을 높이는 패턴입니다.
- MSA 환경에서는 일시적인 장애(네트워크 지연, 순간적인 서비스 다운 등)가 자주 발생할 수 있습니다.
- 이에 따라 즉각적으로 실패를 반환하지 않고 일정 횟수 동안 재시도하는 패턴입니다.
Timeout
- 서비스 응답이 지연될 경우 일정 시간이 지나면 요청을 취소하여 과부하를 방지합니다.
Fallback
- 서비스 호출이 실패했을 때 대체 응답을 제공하여 시스템이 정상적으로 동작하도록 하게 합니다.
- 예를 들어 결제 서비스가 다운되면, "결제 대기 상태로 변경" 후, 나중에 다시 시도하는 등으로 활용할 수 있습니다.
Message Queue
Message Queue(MQ)는 비동기적인 메시지 기반 통신을 지원하는 시스템으로, 마이크로서비스 아키텍처(MSA)에서 서비스 간 decoupling(느슨한 결합)을 가능하게 합니다.
2. 애플리케이션 주 관심사 및 기술 스택
[최우선사항]
- Kafka (이벤트 스트리밍 및 메시징)
[Spring Cloud 주요 구현 포인트]
- Config Server (Spring Cloud Config)
- Service Discovery (Eureka)
- API Gateway (Spring Cloud Gateway)
- Circuit Breaker (Resilience4j)
- Distributed Tracing (Spring Cloud Sleuth, zipkin)
- CI/CD (Github Actions, Jenkins, ArgoCD 등)
[비즈니스 로직 중심]
- DDD (Domain Driven Design)
- Layered Architecture / Hexagonal Architecture
- CQRS
- Event Sourcing
- SAGA Pattern
- Eventual Consistency
- Database per Service
3. 구축계획
우리 팀에서 앞으로 구축할 순서를 정리해보았습니다.
1단계: 기본 인프라 구성
- Config Server (Spring Cloud Config) 구축
- 각 서비스의 설정 중앙화
- Git 저장소 연동
- 환경별 설정 관리 구성
- Service Discovery (Eureka Server) 구축
- 서비스 등록/발견 기능 활성화
- 서비스 헬스체크 설정
- API Gateway (Spring Cloud Gateway) 구축
- 라우팅 설정
- CORS 설정
- 기본 필터 구성
2단계: Event-Driven 기반 구성
- Message Broker 설정 (Kafka/RabbitMQ)
- 토픽/큐 설계
- 컨슈머 그룹 정의
- 파티션 전략 수립
- Spring Cloud Stream 구성
- 바인더 설정
- 채널 구성
- 메시지 컨버터 설정
3단계: 회복성/모니터링 구성
- Circuit Breaker (Resilience4j) 구현
- 서킷 브레이커 설정
- 폴백 메서드 구현
- 타임아웃 정책 설정
- Distributed Tracing 구성
- Spring Cloud Sleuth 설정
- Zipkin 연동
- 트레이스 ID 전파 설정
4단계: 보안/인증 구성
- Spring Security 구성
- OAuth2/JWT 설정
- 인증/인가 필터 구현
- Gateway 보안 통합
5단계: 운영 환경 구성
- Actuator 엔드포인트 설정
- 헬스체크 커스터마이징
- 메트릭 수집 설정
- 로깅 레벨 동적 조정
- Backing Service
모니터링 통합