[MSA] Spring Cloud Gateway를 활용한 API Gateway 구현

2024. 5. 31. 23:14·MSA

Spring Cloud Gateway(SCG)란?

Spring Cloud Gateway는 Spring 기반의 API Gateway이며 클라이언트와 마이크로서비스 사이의 중계기 역할을 한다.

 

API 게이트웨이는 마이크로서비스의 앞에서 클라이언트로부터 모든 요청을 일괄적으로 전달받아 처리하기 때문에 엔드포인트를 단일화할 수 있다는 장점이 있다.

 

API Gateway 적용 전

 

위 이미지를 보면 마이크서비스가 현재는 3개가 있지만 새로운 마이크로서비스가 추가되거나 어떤 마이크로서비스에 주소가 변경되었다고 하면  클라이언트 애플리케이션 측에서도 수정하고 배포하는 과정이 추가적으로 필요하다.

이렇다 보니 단일 진입점 형태의 개발이 필요해서 API Gateway를 사용하게 되었다고 한다.

 

API Gateway 적용 후

 

 API 게이트웨이를 사용하면 각각의 마이크로서비스로 요청되는 모든 정보에 대해서 API Gateway가 일괄적으로 처리할 수 있고 인증 및 권한부여, 응답 캐싱, 마이크로서비스 통합 검색, 부하 분산, 요청 흐름 추적 등의 장점이 있다.

 

Spring Cloud Gateway(SCG) 구성

API 게이트웨이 구현체로 오픈소스인 Spring Cloud Netflix의 Zuul이 있었으나 Spring Boot 2.4부터 Maintenance mode(패치 보류)가 되었다.

Spring.io는 Zuul이 중단되고 Spring Cloud Gateway 권장하는데 지금 생각해 보면 그럴 수밖에 없었을 것 같다.

 

Spring Cloud Gateway

  • 비동기, 논블로킹 방식의 Netty 서버
  • Spring WebFlux 기반

Spring Cloud Neflix Zuul

  • 동기 방식의 Tomcat 서버
  • Spring Web MVC 기반

API 게이트웨이는 수많은 요청을 받지만 어려운 일은 하지 않으므로 비동기 방식이 더 적합한 방식이라고 생각된다.

 


Spring Cloud Gateway 구현

1. API Gateway 프로젝트 생성

나는 프로젝트 이름을 apigateway-service로 생성하였다.

dependency 목록

 

프로젝트 생성 시 위 이미지처럼 아래 3개의 디펜던시를 추가한다.

  1. Eureka Discovery Client
  2. Lombok
  3. Gateway

이번 프로젝트는 Maven 빌드 도구를 사용했는데 intellij에서 Gateway 디펜던시 추가 시 gateway-mvc가 추가되니 직접 수정해야 한다.

 

<!-- 주의! intellij에서 gateway dependencies 추가 시 gateway-mvc가 추가된다. -->
<!--<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway-mvc</artifactId>
</dependency>-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

 

2. API Gateway Filter 설정 

2.1. API Gateway Filter 설정 - yml

spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      routes:
        - id: first-service
          uri: http://localhost:8081/
          predicates:
            - Path=/first-service/**
          filters:
            - AddRequestHeader=first-request, first-request-header2
            - AddResponseHeader=first-response, first-response-header2
        - id: second-service
          uri: http://localhost:8082/
          predicates:
            - Path=/second-service/**
          filters:
            - AddRequestHeader=second-request, second-request-header2
            - AddResponseHeader=second-response, second-response-header2

 

  • spring.cloud.gateway.routes 속성 설명
- id: microservice 이름
- uri: 라우팅 목적지
- predicates: 요청을 처리하기 전 설정한 정보와 HTTP 요청이 부합하는지 체크함(조건절)
  - Path=/first-service/**: first-service 하위로 들어온 모든 요청을 수용함
- filters: API Gateway에서 받은 요청과 응답을 수정할 수 있음

 

 

2.2. API Gateway Filter 설정 - java bean

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * spring cloud gateway 프로퍼티 설정
 */
@Configuration
public class FilterConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route(predicateSpec -> predicateSpec.path("/first-service/**")
                        .filters(gatewayFilterSpec -> gatewayFilterSpec.addRequestHeader("first-request", "first-request-header")
                                .addResponseHeader("first-response", "first-response-header"))
                        .uri("http://localhost:8081/"))
                .route(predicateSpec -> predicateSpec.path("/second-service/**")
                        .filters(gatewayFilterSpec -> gatewayFilterSpec.addRequestHeader("second-request", "second-request-header")
                                .addResponseHeader("second-response", "second-response-header"))
                        .uri("http://localhost:8082/"))
                .build();
    }
}

 

yml 또는 java object로 API Gateway Filter 정보를 설정할 수 있으며 여기까지 진행하였다면 간단한 API Gateway Filter 세팅이 완료된 것이다. 

 

 

이후 apigateway-service의 서버를 기동하면 Netty 서버가 기동 된 것을 확인할 수 있다.

 

2.3. API Gateway 테스트

현재까지 만들어진 서비스는 4개이며 위에서 만든 API Gateway service가 apigateway-service이다.

  1. discovery-service     (port: 8761)
  2. first-service              (port: 8081)
  3. second-service        (port: 8082)
  4. apigateway-service (port: 8000)

 

API Gateway 테스트를 진행하기 위해 first-service와 second-service에 컨트롤러를 생성한다.

  • first-service controller
@Slf4j
@RestController
@RequestMapping("/first-service")
public class FirstServiceController {

    @GetMapping("/welcome")
    public String welcome() {
        return "Welcome to the first service. ";
    }

    @GetMapping("/message")
    public String message(@RequestHeader("first-request") String header) {
        log.info("header value = {}", header);
        return "Hello World in First Service";
    }
}

 

  • second-service controller
@Slf4j
@RestController
@RequestMapping("/second-service")
public class SecondServiceController {

    @GetMapping("/welcome")
    public String welcome() {
        return "Welcome to the second service. ";
    }

    @GetMapping("/message")
    public String message(@RequestHeader("second-request") String header) {
        log.info("header value = {}", header);
        return "Hello World in Second Service";
    }
}

 

 

위와 같이 controller를 생성한 후 각 서비스의 부트 앱을 기동 시키고 크롬에서 아래와 같이 요청을 해보겠다. 

  1. http://127.0.0.1:8000/first-service/message
  2. http://127.0.0.1:8000/second-service/message

 

http://127.0.0.1:8000/first-service/message 요청 결과

 

apigateway-service로 요청을 하였지만 first-service 서비스에 있는 API 응답이 반환된 것을 확인할 수 있다. 

 

first-service response header

 

크롬 관리자 도구에서 헤더 탭을 보면 apigateway-service에서 설정한 response header 값이 들어간 것을 확인할 수 있다.

 

http://127.0.0.1:8000/second-service/message 요청 결과

second-service response header

 

 

위 first-service에 대한 요청 결과와 동일하게 apigateway-service에서 설정한 response header 값이 들어간 것을 확인할 수 있다.

 

 

여기까지 간단한 API Gateway 구현 및 Filter 세팅이 완료된 것이다.  

 

저작자표시 비영리 변경금지 (새창열림)

'MSA' 카테고리의 다른 글

[MSA] Spring Cloud Gateway(SCG)에서 Rate Limiter 구현 (feat, redis & docker)  (1) 2024.12.07
[MSA] Cloud Native Architecture, Application란  (0) 2024.04.28
'MSA' 카테고리의 다른 글
  • [MSA] Spring Cloud Gateway(SCG)에서 Rate Limiter 구현 (feat, redis & docker)
  • [MSA] Cloud Native Architecture, Application란
masjeong
masjeong
교양이란 화를 내지 않으면서도 자신의 신념을 잃지 않은 채 어떤 얘기라도 들을 수 있는 능력을 말한다 - 로버트 프로스트
  • masjeong
    나자바바라쿠배
    masjeong
  • 전체
    오늘
    어제
    • 전체보기 (28)
      • Spring Boot (3)
      • Spring Batch (1)
      • MSA (3)
      • Docker (1)
      • 백준 (16)
      • 자료구조 (3)
      • Kafka (0)
      • DB (1)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    ExecutionContext
    알고리즘
    큐
    티스토리챌린지
    mariadb
    spring batch
    SpringCloud
    18110
    백준11723
    진법변환
    executortype
    2449
    백준
    ratelimiter
    cloud native application
    오블완
    spring cloud Gateway
    Java
    Queue
    15829
    11561
    Cloud Native Architecture
    백준3041
    이진탐색
    이분탐색
    springboot
    MSA
    18111
    정렬
    gradle 오류
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
masjeong
[MSA] Spring Cloud Gateway를 활용한 API Gateway 구현
상단으로

티스토리툴바