Custom Filter, GlobalFilter 적용

2025. 2. 26. 22:45·MSA 공부

1. 개요

현재 배울 CustomFilter 생성 및 등록을 통해서 PreFilter와 PostFilter를 GateWay 단에서 적용 시킬 수 있다.

 

 

2. CustomFilter

다음과 같은 CustomFilter를 생성한다.

참고로 다음과 같은 CustomFilter를 ApiGateWay에 적용하기 위해서는 yml에 등록해줘야 한다.

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {

    public CustomFilter() {
        super(Config.class);
    }
    
    public GatewayFilter apply(Config config) {
        return null;    // 당연히 수정해야겠지?
    }
    
    public static class Config {

    }

}

CustomFilter → Application.yml에 등록하기

내가 만든 CustomFilter를 어느 마이크로 서비스에 거치도록 할 지 정한다.

server:
  port: 8000

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: <http://localhost:8761/eureka>

spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      routes:
        - id: first-service
          uri: <http://localhost:8081>
          predicates:
            - Path=/first-service/*
          filters: # CustomFilter 적용
            - CustomFilter
        - id: second-service
          uri: <http://localhost:8082/>
          predicates:
            - Path=/second-service/**
          filters: # CustomFilter 적
            - CustomFilter

 

결과물

First-Service와 Second-Service를 ApiGateway를 통해 접속할 때 마다 다음과 같이 로그 출력!

package com.msa.apigatewayservice.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
@Slf4j
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {

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

    public GatewayFilter apply(Config config) {
        // Custom Pre Filter 부분

        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();

            log.info("Custom PRE Filter: request id -> {}", request.getId());

            // Custom Post Filter
            // 비동기 방식 + 단일값 반환에는 Mono 객체 사용
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("Custom POST Filter: response id -> {}", response.getStatusCode());
            }));
        };
    }

    public static class Config {

    }

}

 

 

3. GlobalFilter

어느 마이크로 서비스에 등록할지에 대한 CustomFIlter 대신, 전역적으로 등록하여 모든 요청의 처음와 모든 응답의 마지막에 적용되는 GlobalFilter를 적용해보자

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
@Slf4j
public class GlobalFilter extends AbstractGatewayFilterFactory<GlobalFilter.Config> {

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

    public GatewayFilter apply(Config config) {
        // Custom Pre Filter

        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();

            log.info("Global Filter baseMessage -> {}", config.getBaseMessage());

            if (config.isPreLogger()) {
                log.info("Global Filter Start: request id -> {}", request.getId());
            }

            // Custom Post Filter
            // 비동기 방식 + 단일값 반환에는 Mono 객체 사용
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                if (config.isPostLogger()) {
                    log.info("Global Filter End: response id -> {}", response.getStatusCode());
                }
            }));
        };
    }

    @Data
    public static class Config { // 필드 값은 yml 에서 주입받는다.
        private String baseMessage;
        private boolean preLogger;
        private boolean postLogger;
    }

}

application.yml (apigateway-serivce)

server:
  port: 8000

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: <http://localhost:8761/eureka>

spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      default-filters:
        - name: GlobalFilter # 전역 필터 등록
          args:
            baseMessage: Spring Cloud Gateway Global Filter baseMessage
            preLogger: true
            postLogger: true
      routes:
        - id: first-service
          uri: <http://localhost:8081>
          predicates:
            - Path=/first-service/**
          filters:
            - CustomFilte
        - id: second-service
          uri: <http://localhost:8082/>
          predicates:
            - Path=/second-service/**
          filters:
            - CustomFilter

적용 결과

default-filters에 등록된 GlobalFilter가 클라이언트 요청에 대해서 필터들 중 가장 먼저 작동되고 응답에 대해서는 가장 나중에 작동된다. 

  • request id 또한 같은 걸 확인할 수 있다. (하나의 요청에 대한 출력 콘솔)

 

 

4. 배운 것들

 

apigateway-service에서 Custom Filter와 Global Filter를 등록해 여러 마이크로 서비스에 등록하는 과정을 공부했다!

'MSA 공부' 카테고리의 다른 글

API Gateway Service - 1  (0) 2025.01.26
Service Discovery  (0) 2025.01.26
'MSA 공부' 카테고리의 다른 글
  • API Gateway Service - 1
  • Service Discovery
송우석입니다
송우석입니다
  • 송우석입니다
    송우석
    송우석입니다
  • 글쓰기 관리
  • 전체
    오늘
    어제
    • 분류 전체보기 (140) N
      • JAVA (1)
      • 알고리즘 (84) N
        • 백준 (8)
        • String(문자열) (12)
        • Array(1, 2차원 배열) (13) N
        • Two pointers, Sliding windo.. (6)
        • HashMap, TreeSet(해쉬, 정렬지원 S.. (5)
        • Stack, Queue(자료구조) (8)
        • Sorting and Searching(정렬, 이.. (10)
        • Recursive, Tree, Graph(DFS,.. (14)
        • DFS, BFS 활용 (6)
        • 다시 시작! (1)
        • 기초 수학 (1) N
      • 일상 (19)
      • Github (1)
      • MSA 공부 (3)
      • 경제, 금융, 디지털, 시사 (3)
      • 라즈베리파이 (10)
      • 프로젝트에서 일어난 일 (13)
      • FrontEnd 공부 (6) N
        • React (5) N
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
송우석입니다
Custom Filter, GlobalFilter 적용
상단으로

티스토리툴바