Spring Cloud Gateway: 기본 예제

발행: (2025년 12월 31일 오전 03:03 GMT+9)
8 min read
원문: Dev.to

Source: Dev.to

Spring Cloud Gateway: 기본 예제 커버 이미지

Eduardo

Spring Cloud Gateway(게이트웨이 또는 Edge Service라고도 함)는 동적 라우팅 서버입니다. 즉, 마이크로서비스에 대한 중앙 집중식 접근 지점을 제공할 수 있습니다. 또한 필터나 프레디케이트 등을 추가하여 기능을 확장할 수 있습니다.

1. Spring Cloud Gateway 구성

Spring Initializr(또는 선호하는 IDE)를 사용하여 프로젝트를 생성하고 다음 의존성을 선택하십시오:

  • Eureka Discovery Client
  • Gateway

프로젝트는 Eureka Server에도 등록되므로 다음 구성을 추가하십시오:

@EnableEurekaClient
@SpringBootApplication
public class EurekaClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class, args);
    }
}

Application properties (YAML)

spring:
  application:
    name: gateway-server-service
server:
  port: 8090
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

2. Routes

Edge/Gateway에 대한 최소 필수 구성은 routes 입니다. 이 라우트들은 게이트웨이에서 요청을 받아 응답을 제공할 서비스로 리다이렉트합니다.

기본 라우트 구성 (YAML)

spring:
  cloud:
    gateway:
      routes:
        - id: employees
          uri: lb://employees
          predicates:
            - Path=/api/employees/**
          filters:
            - StripPrefix=2

설명

ElementDescription
id라우트의 고유 식별자입니다.
uri게이트웨이가 리다이렉트할 서비스를 찾을 주소입니다. Eureka와 같은 서비스 디스커버리를 사용할 경우 lb(Load Balancer)로 시작해야 합니다.
predicates리다이렉션이 성립하기 위해 만족해야 하는 규칙들입니다.
filters선언된 라우트를 통과하는 요청/응답을 조작하는 작업들입니다.

위 예시에서는 게이트웨이가 employees 라는 마이크로서비스로 라우팅합니다. 해당 마이크로서비스의 포트에 직접 접근하는 대신, 게이트웨이 포트(8090)에서 Spring Cloud Gateway를 호출하면 응답을 받을 수 있습니다.

2.1 Predicates

Predicates는 리다이렉션이 성공하기 위해 만족해야 하는 규칙들의 목록입니다. 경로, 헤더, HTTP 메서드, 쿼리 파라미터, 쿠키 등을 기반으로 할 수 있습니다.

예시

predicates:
  - Path=/api/products/**
  - Header=token, \d+
  - Method=GET, POST
  - Query=color
  - Cookie=color, blue

의미

PredicateDescription
Path선언된 경로와 일치하는 요청을 리다이렉트합니다.
Header지정된 헤더가 존재하고, 값이 주어진 정규식과 일치하는지 확인합니다.
Method나열된 HTTP 메서드만 허용합니다.
QueryURL에 해당 쿼리 파라미터가 존재해야 합니다.
Cookie지정된 쿠키가 존재하는지(그리고 선택적으로 값이 일치하는지) 확인합니다.

2.2 Spring Cloud Gateway Factory Filters

Factory filters는 요청 및 응답을 조작할 수 있게 해줍니다(예: 헤더 추가, 요청 파라미터 추가).

구성 (YAML)

filters:
  - AddRequestHeader=token-request, 123456
  - AddResponseHeader=token-response, 12345678
  - SetResponseHeader=Content-Type, text/plain
  - AddRequestParameter=name, andres

이 필터들은 선언된 라우트에만 적용됩니다.

2.3 Spring Cloud Gateway Global Filters

Global filters는 라우트별로 선언할 필요 없이 모든 요청에 적용됩니다.

구현 예시

package com.funcionaenmimaquina.springboot.app.gateway.filters;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class ExampleGlobalFilter implements GlobalFilter, Ordered {

    private final Logger logger = LoggerFactory.getLogger(ExampleGlobalFilter.class);

    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        logger.info("Executing request filter");

        // Modifying the request
        exchange.getRequest()
                .mutate()
                .header("environment", "dev")
                .build();

        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            logger.info("Executing response filter");
            // Adding a cookie to the response
            exchange.getResponse()
                    .addCookie(ResponseCookie.from("myCookie", "myValue")
                            .path("/")
                            .maxAge(3600)
                            .build());
        }));
    }

    @Override
    public int getOrder() {
        // Lower values have higher precedence
        return -1;
}
}

이 예제에서 필터는 모든 들어오는 요청에 environment 헤더를 추가하고, 모든 응답에 myCookie이라는 쿠키를 추가합니다.

Global Filter Example (continued)

o("Executing response filter");

// Modifying the response
Optional.ofNullable(exchange.getRequest().getHeaders().getFirst("environment"))
        .ifPresent(value -> {
            exchange.getResponse().getHeaders().add("env", value);
        });

exchange.getResponse().getHeaders().setContentType(MediaType.TEXT_PLAIN);
}))
;

@Override
public int getOrder() {
    return 1;
}
}

예제 작동 방식

  • **GlobalFilter**와 Ordered 인터페이스를 구현합니다.
  • getOrder는 여러 글로벌 필터가 존재할 때 실행 순서를 정의합니다.
  • filter 메서드에 요청과 응답을 다루는 모든 로직이 들어갑니다.
  • 24 줄에서는 요청을 조작할 수 있는 위치(예: 헤더 추가)를 보여줍니다.
  • 27 줄에서는 .then(Mono.fromRunnable(...))을 사용해 응답을 조작하는 방법을 보여줍니다.
  • 31 줄은 특정 요청 헤더가 존재할 경우 응답에 헤더를 추가합니다.
  • 34 줄은 응답의 미디어 타입을 평문(text/plain)으로 강제합니다.

2.4 Filter Factory (Custom Gateway Filter)

특정 라우트에만 필터를 적용하고 싶다면, 커스텀 필터 팩토리를 생성합니다:

@Component
public class ExampleGatewayFilterFactory
        extends AbstractGatewayFilterFactory {

    private final Logger logger = LoggerFactory.getLogger(ExampleGatewayFilterFactory.class);

    public ExampleGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            logger.info("Zone to modify the request");

            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                logger.info("Zone to modify the response");

                Optional.ofNullable(config.cookieValue).ifPresent(cookieVal -> {
                    exchange.getResponse()
                            .addCookie(ResponseCookie.from(config.cookieName, cookieVal).build());
                });
            }));
        };
    }

    @Override
    public String name() {
        return "ExampleCookie";
    }

    @Override
    public List shortcutFieldOrder() {
        return Arrays.asList("cookieName", "cookieValue");
    }

    public static class Config {
        private String cookieName;
        private String cookieValue;

        // Getters and Setters
        public String getCookieValue() { return cookieValue; }
        public void setCookieValue(String cookieValue) { this.cookieValue = cookieValue; }
        public String getCookieName() { return cookieName; }
        public void setCookieName(String cookieName) { this.cookieName = cookieName; }
    }
}

application.yml에서 사용 예시

filters:
  - StripPrefix=2
  - ExampleCookie=user, myName

코드가 수행하는 작업

  • YAML 파일에 정의된 값을 사용해 응답에 쿠키를 추가합니다.

관례 및 요구 사항

  1. 클래스 이름은 FilterFactory 로 끝나야 합니다.
  2. AbstractGatewayFilterFactory 를 상속합니다.
  3. 내부 Config 클래스는 YAML 파일에서 전달된 값을 저장합니다.
  4. 필터 로직은 apply 메서드에 위치합니다.
  5. name() 메서드가 반환하는 값은 YAML에서 사용되는 키와 일치해야 합니다(또는 기본적으로 클래스명 접두어와 일치).
  6. shortcutFieldOrder 는 짧은 표기법 값이 설정 필드에 매핑되는 순서를 정의합니다.

application.yml에서 이 필터를 참조한 라우트에만 적용됩니다.

결론

이제 다음을 이해했습니다:

  • Spring Cloud Gateway가 무엇이며 어떤 문제를 해결하는지.
  • 기능을 확장하기 위해 predicatesfilters를 구성하는 방법.
  • 세밀한 제어를 위해 global filterscustom filter factories를 만드는 방법.

실제 프로젝트에서 게이트웨이를 구축하고 맞춤화하여 편하게 사용할 수 있도록 연습하세요.

관련 링크

Back to Blog

관련 글

더 보기 »