Spring Gateway로 구현하는 API 게이트웨이

Netflix OSS와 Spring Cloud의 관계

2020년 이전 마이크로서비스 생태계에서는 Netflix가 오픈소스로 공개한 다양한 컴포넌트가 표준처럼 사용되었다. 현재는 Spring Cloud Alibaba가 대체재로 자리 잡았지만, 여전히 레거시 시스템에서 Netflix 스택을 접할 수 있다.

Spring Cloud AlibabaNetflix OSS역할
NacosEureka서비스 디스커버리
DubboRibbon + FeignRPC 기반 서비스 호출
SentinelHystrix서킷 브레이커 및流量 제어
Spring GatewayZuul엣지 게이트웨이

특히 Gateway는 Netflix가 아닌 Spring 팀 자체에서 개발한 컴포넌트로, Spring Cloud 생태계의 핵심 구성원이다.

게이트웨이의 개념과 역할

네트워크 용어에서 게이트웨이는 서로 다른 네트워크를 연결하는 관문을 의미한다. 마이크로서비스 아키텍처에서 게이트웨이는 외부 클라이언트와 내부 서비스 사이의 단일 진입점(Single Entry Point) 역할을 수행한다.

모든 외부 요청은 반드시 게이트웨이를 거쳐야 하며, 이를 통해 다음 효과를 얻을 수 있다:

  • 인증 및 권한 검증의 중앙화
  • 요청/응답 로깅 및 모니터링
  • 서비스별 적절한 라우팅
  • 공통 관심사(Cross-cutting Concerns)의 일원화

정적 라우팅 구성

Spring Gateway는 YAML 또는 Java DSL로 라우트 규칙을 정의할 수 있다. 다음은 두 개의 하위 서비스로 트래픽을 분배하는 설정 예시이다.

server:
  port: 9000

spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      routes:
        - id: route-seoul
          uri: lb://seoul-service
          predicates:
            - Path=/kr/**
          filters:
            - StripPrefix=1
        
        - id: route-tokyo
          uri: lb://tokyo-service
          predicates:
            - Path=/jp/**
          filters:
            - StripPrefix=1

위 설정의 동작 방식을 분석하면:

  • lb:// 접두사는 LoadBalancer를 통해 서비스 인스턴스를 선택함을 의미
  • Path 조건은 Ant 스타일 패턴 매칭을 지원
  • StripPrefix 필터는 매칭된 경로 세그먼트를 제거 후 하위 서비스로 전달

실제 요청 흐름:

클라이언트 → GET http://localhost:9000/kr/users/123
         ↓
게이트웨이: Path=/kr/** 매칭 확인
         ↓
StripPrefix(1) 적용: /users/123
         ↓
LoadBalancer가 seoul-service 인스턴스 선택
         ↓
최종 요청: GET http://{seoul-instance}/users/123

동적 라우팅 활성화

서비스 수가 증가할수록 정적 라우팅 설정은 관리 부담을 야기한다. Spring Gateway는 서비스 레지스트리(Nacos, Eureka 등)를 기반으로 자동 라우트를 생성하는 기능을 제공한다.

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true

활성화 후의 URL 패턴:

http://게이트웨이:포트/{서비스ID}/{엔드포인트}

예를 들어 inventory-service라는 이름으로 Nacos에 등록된 서비스는 다음과 같이 접근 가능하다:

# 직접 호출
GET http://inventory-service:8081/api/stocks

# 게이트웨이 경유
GET http://localhost:9000/inventory-service/api/stocks

lower-case-service-idtrue로 설정하면 대문자가 포함된 서비스명도 소문자로 변환되어 일관된 URL 패턴을 유지할 수 있다.

고급 라우팅 패턴

단순 경로 매칭 외에도 다양한 조건을 조합할 수 있다.

predicates:
  # 시간대 기반 라우팅
  - Between=2024-01-01T00:00:00.000+09:00,2024-12-31T23:59:59.999+09:00
  
  # HTTP 메서드 제한
  - Method=GET,POST
  
  # 요청 헤더 기반
  - Header=X-Api-Version,v2
  
  # 쿼리 파라미터 기반
  - Query=region,ap-northeast

복수의 predicates는 AND 조건으로 결합되며, 모든 조건을 만족해야 해당 라우트가 선택된다.

태그: Spring Gateway Spring Cloud nacos microservices Load Balancing

6월 13일 23:07에 게시됨