Spring Cloud Api GateWay Global Filter(전역 필터)를 삭제한 이유

2025. 8. 10. 22:47개발 고민

 

Spring Cloud를 이용한 프로젝트를 진행하며 Global Filter를 제외한 이유 4가지

 

  1. 전역 필터는 작은 변경에도 전체 트래픽에 영향을 줘 혼란을 준다.
  2. 예외 경로가 생길 수 록 if/else와 같이 분기 코드가 추가되어야 한다.
  3. 내부/외부 통신간의 보안 권한 분류가 깨진다.
  4. 모든 요청에 대한 같은 작업을 반복하는 문제
1) 전역 예외 리스트

 

특히 모듈 서버가 추가될 때 api 엔드포인트 별 예외 사항이 추가될 때 마다 라우트 별 필터에 해당 엔드 포인트 예외 사항을 일일히 추가해야 되었고 이 때문에 누락된 혹은 생각지 못한 오류가 계속 발생하였습니다.

 

회원가입/로그인/토큰 재발급 같은 공개 엔드포인트가 늘수록 전역 필터엔 path.startsWith(...) 예외가 누적되고 경로 하나만 틀려도 인증 401 문제가 발생하였습니다. 라우트별 필터로 빼면 공개 라우트는 require: false로 선언형으로 변경하면 예외 처리할 라우트와 아닌 라우트 구분이 쉽고 예외 사항에 대한 대응도 용의하게 됩니다.

 

- 레거시 코드

@Slf4j
@Component
public class AuthorizationHeaderFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String path = exchange.getRequest().getURI().getPath();

        if (path.startsWith("/eureka") || path.startsWith("/actuator/**") || path.startsWith("/auth/reissue") || path.startsWith("/auth/login") || path.startsWith("/users/login") || path.startsWith("/users/signup")) {
            return chain.filter(exchange);
        }
        ....
    }
}


- 개선된 코드

- id: users-public
  predicates: [ Path=/users/login, Path=/users/signup ]
  filters:
    - StripPrefix=1
    - name: AuthorizationHeaderFilter
      args: { require: false }
      
@Component
public class AuthorizationHeaderFilter extends AbstractGatewayFilterFactory<AuthorizationHeaderFilter.Config> {
    private final JwtUtil jwtUtil;

    public AuthorizationHeaderFilter(JwtUtil jwtUtil) {
        super(Config.class);
        this.jwtUtil = jwtUtil;
    }

    @Getter @Setter
    public static class Config {
        private boolean require = true;              // false면 인증 스킵 (공개 라우트)
        private boolean verifyDevice = true;         // UA 바인딩 검증
        private boolean verifyForwardedFor = true;   // X-Forwarded-For 바인딩 검증
        private String userIdHeader = "X-User-ID";
        private int order = -1;
    }

    @Override
    public GatewayFilter apply(Config config) {
    	...
    }

 

내부/외부 트래픽에 다른 보안 정책 적용

 

현재 프로젝트에서는 보안 강화를 위해 jwt 검사 시 초기 device 정보와 ip 정보를 기록해 동일한 사용자인지 비교하는 기능도 있는데 내부 <-> 내부 서버간의 통신 과정에서는 해당 보안 정책을 제외하여 내부 서비스 토큰만을 이용해 보안 검사를 통과할 수 있게 설정해 기존 Header에 대한 문제를 해결 하였습니다.

 

전역 필터를 사용할 때는 보안 정책 상 어쩔 수 없이 내부망 통신 내에서도 Header 값을 가져와 추가해주고 api 요청을 하는 방식을 진행 했지만 프로젝트 정책 상 내부망 통신끼리는 추가 검사 없이 진행하는 것이 DRY 원칙을 지킨다 생각하였습니다.
추가적으로 내부망 통신은 보안정책이 약화 되므로 철저히 내부망끼리 통신이 가능하게 만들어야 됩니다. 때문에 배포되는 도커 서버 내부 ip를 Config Server 설정을 통해 할당 받아 통신하는 방식으로 변경하였습니다.

 

- id: users-public
  filters:
    - name: AuthorizationHeaderFilter
      args: { require: false }

- id: users-internal
  filters:
    - RemoveRequestHeader=Cookie
    - name: AuthorizationHeaderFilter
      args:
        require: true
        verifyDevice: false
        verifyForwardedFor: false