MSA 학습 - API Gateway

2025. 9. 25. 19:32·Back-End

이번에는 MSA 환경에서 클라이언트와 서비스 간의 통신을 관리하는 핵심 컴포넌트인 API Gateway에 대해 학습해보려 한다.

우리는 MSA를 구성하면서 여러 개의 포트로 여러 개의 서비스를 관리한다. 하지만 사용자는 auth, user, product, order 등 다양한 서비스에 접근할 수 있는데, 접근하기 위해서는 각각 서비스의 포트를 미리 알고 접근해야하는 상황이 생길 수 있다. AWS 환경에서 여러 개의 인스턴스를 로드 밸런서를 통해 사용하면 로드밸런서만 알고 있어도 여러 서비스를 이용할 수 있듯이, 중앙에서 이를 관리하고 클라이언트와 통신을 하는 역할을 하는 서버가 필요하다.

 

API Gateway

API Gateway는 마이크로서비스 아키텍처에서 모든 클라이언트 요청의 단일 진입점 역할을 하는 서버이다. 클라이언트가 각 마이크로서비스에 직접 접근하는 대신, API Gateway를 통해 적절한 서비스로 요청을 라우팅하는 방식이다.

 

API Gateway의 기능

  • 라우팅: 클라이언트 요청을 적절한 마이크로서비스로 전달
  • 로드 밸런싱: 여러 서비스 인스턴스 간 요청 분산
  • 인증/인가: 중앙집중화된 보안 처리
  • 요청/응답 변환: 프로토콜 변환, 데이터 포맷 변환
  • 모니터링: 로깅, 메트릭 수집, 추적

여기서 중요한 점은 API Gateway가 단순한 프록시가 아니라는 것이다. 각종 횡단 관심사를 처리하는 지능적인 라우터 역할을 한다.

이전에 FeingClient로 로드밸런서 역할을 할 수 있다고 하지 않았나요?
-> FeignClient는 서비스와 서비스간의 로드밸런서 역할을 하는 것이고, API Gateways는 클라이언트와 서비스 간의 로드밸런서 역할을 수행하는 것이다.

API Gateway가 왜 필요할까?

MSA 환경에서 클라이언트가 각 서비스에 직접 접근하게 되면 어떤 문제가 발생할까? 예를 들어 전자상거래 시스템에서 사용자 서비스, 상품 서비스, 주문 서비스, 결제 서비스가 각각 분리되어 있다고 가정해보자.

  1. 복잡한 클라이언트: 클라이언트가 여러 서비스의 엔드포인트를 모두 알아야 함
  2. 보안 중복: 각 서비스마다 인증/인가 로직을 구현해야 함
  3. CORS 문제: 각 서비스마다 CORS 설정을 해야 함
  4. 모니터링 분산: 로그와 메트릭이 여러 서비스에 분산됨
  5. 프로토콜 제약: 클라이언트가 여러 프로토콜을 지원해야 할 수도 있음

이런 문제들을 해결하기 위해 API Gateway가 필요한 것이다.

 

Spring Cloud Gateway 적용

의존성 추가

우리가 스프링에서 API Gateway를 구현하기 위한 주요 의존성들을 살펴보면 몇 가지 선택지가 있다.

`org.springframework.cloud:spring-cloud-starter-gateway`는 Spring Cloud에서 제공하는 리액티브 기반의 API Gateway이고, `org.springframework.cloud:spring-cloud-starter-netflix-zuul`은 Netflix에서 개발한 게이트웨이다. 하지만 Zuul은 현재 유지보수 모드에 있어서 새로운 프로젝트에는 Spring Cloud Gateway를 사용하는 것이 권장된다.

의존성 추가에서 gateway를 검색하게 되면 이렇게 2가지가 나온다.

 

두 개의 의존성은 차이가 존재하는데, 위에 그냥 Gateway의 경우에는 Spring MVC 기반으로 Servlet 기반으로 동작하는 Gateway이고, Reactive Gateway는 WebFlux 기반의 Gateway이다. Spring Reactive Programming에 대해서 알아야 둘의 차이점을 이해할 수 있는데, 현재는 동기(Gateway)와 비동기(Reactive Gateway)로 작동하며 성능상 이점 때문에 Reactive 버전을 많이 사용한다고 우선 이해하면 된다.

Gateway 또한 Eureka 서버에서 관리되어야 하므로 당연히 Eureka Client 의존성이 필요하다

application.yml 설정

의존성을 적용했다면, application.yml에 설정을 해주어야 한다.

 

이제 저번 글에서 테스트했었던, auth-service와 user-service의 통신을 gateway를 통해서 테스트해보자

Eureka 서버에 서비스들이 잘 잡히는 모습을 확인할 수 있으며

 

Gateway 포트인 8762번으로 보냈음에도 정상적으로 auth-service로 요청을 보내, user-service와 연동해서 결과를 가져오는 것을 확인할 수 있었다.

Filter

Gateway는 기능에서 적어놨듯이 단순히 요청을 서비스로만 분배하는 역할만 하지 않는다. MSA 환경에서 각 서비스 간에 공통적으로 처리하면 좋은 작업들이 있다. 예를 들어 인증/인가의 경우는 필요로 하는 서비스가 많다. 예를 들어 user, auth, order, review, file-upload 등의 서비스들이 존재한다고 할 때 이 모든 서비스들마다 인증/인가를 구축하게 되면 코드 중복이 많아지고 불필요한 시간이 많이 필요하다. 이 때 Gateway Filter을 이용해서 공통적인 부분들을 처리할 수 있다.(로깅, 인증, 요청/응답 헤더 변경 등)

 

Gateway Filter의 종류는 두 가지로 나뉜다.

  • Global Filter: 모든 요청에 적용되는 필터
  • Gateway Filter: 특정 Route에만 적용되는 필터

Global Filter 작성

Global Filter의 예시이다. GlobalFilter와 Ordered를 implement하게 되는데 반환값인 Mono<Void>는 우선 아무 데이터도 반환하지 않는다는 것을 의미한다고 알고 가자.

  • ServerWebExchange: 요청과 응답에 대한 모든 정보를 담고 있는 객체다. 여기서 요청 정보를 가져오거나 응답을 조작할 수 있다.
    • Servlet과 다르게 ServerHttpRequest, ServerHttpResponse 객체를 사용한다
  • GatewayFilterChain: 필터 체인을 나타내며, chain.filter(exchange)를 호출해야 다음 필터로 요청이 전달된다. 만약 이를 호출하지 않으면 요청이 여기서 끝나버린다.
  • getOrder(): 필터의 우선순위를 정한다. 지금은 모든 요청 이전에 작동하는 필터이기 때문에 HIGHEST_PRECEDENCE로 지정했다.

이번에는 모든 요청이 끝난 후 동작하는 필터도 작성해보자.

Post 필터와 차이점을 보자면 .then(Mono.fromRunnable(...)) 이라는 메소드가 사용되었는데, 이는 리액티브 프로그래밍에서는 비동기 작업으로 진행되기 때문에, 비동기 작업이 완료된 후에 실행되는 작업을 정의하기 위함이다.

 

Custom Filter 구현

이전에 작성한 Global Filter는 모든 요청에 대해서 동작하는 필터이다. 하지만 인증처럼 특정 Route에서만 동작하는 필터를 작성하고 싶다면 `AbstractGatewayFilterFactory`를 상속받아 구현할 수 있다.

이 때, `AbstractGatewayFilterFactory`는 제네릭 타입을 요구하기 때문에 따로 설정하지 않아도 static class인 Config를 그냥 정의해놓거나,

이렇게 Void로 해도 된다. 그런데 큰 이유가 없다면 설정을 추가할 수 있는 Config 클래스를 정의해놓는 것이 좋지 않을까 생각이 든다.

이렇게 만든 커스텀 필터는 application.yml에 적용해 설정할 수 있다.

이런식으로 id와 path를 세분화해서 필요한 부분에 filters 옵션을 통해 적용할 수 있다.

 

우선 나는 이후 연습프로젝트를 진행하며 jwt토큰 인증 관련한 부분을 Custom Filter로 작성하면 좋을 것 같다는 생각을 가지고 있다.

'Back-End' 카테고리의 다른 글

재고 관리 문제 해결(동시성 및 DB 동기화 전략에 대해)  (0) 2026.01.07
MSA 학습 - 서킷 브레이커  (0) 2025.09.24
MSA 학습 - 로드밸런싱(FeignClient, Ribbon)  (0) 2025.09.23
MSA 학습 - Spring Cloud와 Eureka  (0) 2025.09.22
비동기 메시징 방식(RabbitMQ vs Kafka)  (0) 2025.09.19
'Back-End' 카테고리의 다른 글
  • 재고 관리 문제 해결(동시성 및 DB 동기화 전략에 대해)
  • MSA 학습 - 서킷 브레이커
  • MSA 학습 - 로드밸런싱(FeignClient, Ribbon)
  • MSA 학습 - Spring Cloud와 Eureka
dev_Mins
dev_Mins
  • dev_Mins
    천천히 빠르게!
    dev_Mins
  • 전체
    오늘
    어제
    • 분류 전체보기 (49)
      • 42Seoul (2)
      • Back-End (20)
        • Spring (8)
      • Project (14)
        • PickLab (3)
      • 끄적끄적 (3)
      • Algorithm (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    MSA Gateway
    Spring Boot
    주문 서비스
    42seoul
    Kafka
    AWS
    Spring Cloud
    Spring
    스프링 jwt
    Servcie Discovery
    로드밸런서
    MSA
    Spring Security
    42서울
    Spring Data JPA
    로드밸런싱
    재고 서비스
    스프링
    스프링 게이트웨이
    JWT
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
dev_Mins
MSA 학습 - API Gateway
상단으로

티스토리툴바