마이크로서비스 아키텍처의 핵심 요소인 API 게이트웨이, 그중에서도 Spring Cloud Gateway에 대해 함께 알아보도록 하겠습니다. 비유를 통한 설명으로 최대한 알기 쉽도록 설명해보겠습니다. 많은 관심 부탁드려요!
여러분, 대형 쇼핑몰을 상상해보세요. 의류 매장, 식품 매장, 전자제품 매장 등 다양한 상점이 있습니다. 만약 이 쇼핑몰에 메인 입구가 없고 각 상점마다 별도의 입구가 있다면 어떨까요? 손님들은 어디로 들어가야 할지 헷갈리고, 각 상점은 자체적으로 보안 요원을 고용해야 하며, 쇼핑 경험이 매우 불편해질 것입니다.
마이크로서비스 아키텍처에서도 마찬가지입니다. 여러 독립적인 서비스가 존재할 때, 사용자나 클라이언트 애플리케이션이 각 서비스에 직접 접근하면 복잡성이 증가하고 관리가 어려워집니다. 이때 API 게이트웨이가 쇼핑몰의 메인 입구처럼 단일 진입점 역할을 하게 됩니다.
Spring Cloud Gateway는 Spring Framework에서 제공하는 오픈 소스 기반의 API 게이트웨이 서비스입니다. 이전에는 Spring Cloud Zuul이 이 역할을 했지만, 현재는 더 효율적인 Spring Cloud Gateway로 이전이 이뤄졌습니다.
가장 중요한 특징은 비동기 처리 방식을 사용한다는 점입니다. Netty 기반으로 동작하여 수많은 요청을 빠르게 처리할 수 있어요. 마치 여러 손님의 요청을 동시에 처리하는 능숙한 바텐더 같죠!
Spring Cloud Gateway는 세 가지 핵심 구성 요소로 이루어져 있습니다:
라우트는 고유 ID + 목적지 URI + Predicate + Filter로 구성됩니다. 쉽게 말해 "이런 조건의 요청이 오면 이 서비스로 보내줘"라는 규칙이라고 생각하면 됩니다.
Predicate는 주어진 요청이 특정 조건을 충족하는지 테스트하는 구성 요소입니다. "만약 이 경로로 요청이 들어오면", "만약 이 시간 이후에 요청이 들어오면" 같은 조건을 설정할 수 있습니다. 마치 클럽 입구의 보안 요원이 입장 조건을 확인하는 것과 같습니다!
Filter는 요청이나 응답을 변경하거나 부가 기능을 수행합니다. 인증 토큰 확인, 로깅, 요청 변환 등의 작업을 수행합니다. 마치 손님이 주문한 음료에 시럽을 추가하거나 얼음을 빼는 등의 커스터마이징을 하는 것과 비슷하죠!
요청의 특정 속성에 따라 요청을 다른 서비스로 전달할 수 있습니다. 예를 들어 API 버전이 헤더에 포함된 경우, 해당 버전의 서비스로 요청을 보낼 수 있어요. 마치 교통 경찰이 차량 종류에 따라 다른 도로로 안내하는 것처럼요!
spring:
cloud:
gateway:
routes:
- id: auth-app
uri: http://auth-service:8080
predicates:
- Path=/auth/**
Eureka와 같은 서비스 레지스트리와 통합하여 서비스 인스턴스를 동적으로 발견하고 라우팅할 수 있습니다.
1. 클라이언트로부터 요청이 들어오면 API Gateway는 Eureka 서버를 통해 해당 엔드포인트의 실제 주소값을 반환받습니다.
2. API Gateway는 반환받은 주소에 요청을 합니다.
3. 응답을 받고 클라이언트에게 전달합니다.
이는 마치 GPS가 실시간으로 목적지까지의 최적 경로를 찾아주는 것과 같습니다.
특정 서비스가 일정 시간 동안 실패하면, 해당 서비스로의 요청을 차단하여 시스템 전체가 장애로부터 보호되도록 합니다. 이는 전기 회로의 차단기와 같은 원리로, 과부하가 발생하면 회로를 끊어 시스템 전체의 손상을 방지합니다.
filters:
- CircuitBreaker=myCircuitBreaker
시스템에 대한 요청이 일정 속도를 초과할 때, 해당 요청을 제한하고 HTTP 429 상태 코드(Too Many Requests)를 반환합니다. 이것은 클럽에서 한 번에 입장할 수 있는 인원을 제한하는 것과 비슷한 원리입니다.
spring:
cloud:
gateway:
routes:
- id: loans-service
uri: lb://loans-service
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
전처리(Pre) 필터와 후처리(Post) 필터를 조합하여 요청과 응답을 세밀하게 제어할 수 있습니다. 마치 음료를 만들 때 재료를 넣는 순서와 방법을 정하는 것과 같습니다.
실제 쇼핑몰 시스템에서 Spring Cloud Gateway를 어떻게 활용할 수 있는지 예를 들어보겠습니다:
spring:
cloud:
gateway:
routes:
- id: product-service
uri: lb://PRODUCT-SERVICE
predicates:
- Path=/products/**
filters:
- RewritePath=/products/(?.*), /$\{segment}
- id: order-service
uri: lb://ORDER-SERVICE
predicates:
- Path=/orders/**
filters:
- RewritePath=/orders/(?.*), /$\{segment}
- id: payment-service
uri: lb://PAYMENT-SERVICE
predicates:
- Path=/payments/**
filters:
- RewritePath=/payments/(?.*), /$\{segment}
이 설정에서는:
1. /products/** 경로로 들어오는 요청은 상품 서비스로 라우팅
2. /orders/** 경로로 들어오는 요청은 주문 서비스로 라우팅
3. /payments/** 경로로 들어오는 요청은 결제 서비스로 라우팅
클라이언트는 단일 API 주소만 알면 되고, 내부적으로 각 서비스에 맞게 라우팅됩니다.
Spring Cloud Gateway는 Netflix Zuul의 후속작이라고 볼 수 있는데, 가장 큰 차이점은 다음과 같습니다:
마이크로서비스 아키텍처에서 API 게이트웨이는 단순한 라우팅 도구 이상입니다. 보안, 로깅, 모니터링, 장애 처리 등 다양한 공통 관심사를 중앙에서 처리함으로써 개발자가 비즈니스 로직에 더 집중할 수 있게 해줍니다.
Spring Cloud Gateway는 이러한 기능을 효율적으로 구현할 수 있는 강력한 도구입니다. 비동기 처리 방식을 통해 높은 성능을 제공하고, 다양한 필터와 조건자를 통해 유연한 라우팅이 가능하며, 다른 Spring Cloud 기술들과의 통합을 통해 완전한 마이크로서비스 환경을 구축할 수 있습니다.