스프링 클라우드 - API 게이트웨이

2024. 9. 13. 10:41스프링 클라우드

2024/09/13

 

여행을 가기 위해 공항에 도착하는 순간
여러분은 어떤 느낌이 드신가요?
마냥 설레고 기쁘신가요?

 

 

공항에 도착하자마자 바로
비행기를 탈 수 있으면 좋겠지만
실제로는 복잡한 여정이 여러분을 기다린답니다.
출발 3시간 전에 꼭 공항에
도착하라는 말엔 이유가 있는거죠.

 

 

탑승 수속을 마치기 위해
승객들은 먼저 체크인을 하고
수하물을 부칩니다.
그리고 탑승구로 이동하기 위해 보안 검색대를 거칩니다.
대기줄이 길면 시간이 많이 소요되는 구간이죠. 

 

 

 

이러한 과정들을 거쳐 탑승구역으로 진입하면
드디어 비행기를 탈 수 있게 됩니다.
공항 입구에서 탑승구역으로 이동하는 내내
어떤 일이 있었는지 짚어본 이유가 무엇이냐고요?
그건 오늘 포스팅의 주제인 게이트웨이의 역할 때문입니다.

 

 

 

 

※  API 게이트웨이(Spring Cloud Gateway)에 대해 알아보자.

 

 

출처: https://media.geeksforgeeks.org/wp-content/uploads/20230718004641/API-Gateway-in-Microservices-300.png

 

 

   ▶  API 게이트웨이 개요

       ●   API 게이트웨이?
            ○  API 게이트웨이는 클라이언트의 요청을 받아 백엔드 서비스로 라우팅하고, 다양한 부가 기능을 제공하는 중간 서버다.
              클라이언트와 서비스 간의 단일 진입점 역할을 하며, 보안, 로깅, 모니터링, 요청 필터링 등을 처리한다.


       ●   API 게이트웨이의 주요 기능
            ○  라우팅 : 클라이언트 요청을 적절한 서비스로 전달
            ○  인증 및 권한 부여 : 요청의 인증 및 권한을 검증
            ○  로드 밸런싱 : 여러 서비스 인스턴스 간의 부하 분산
              모니터링 및 로깅 : 요청 및 응답을 로깅하고 모니터링
            ○  요청 및 응답 변환 : 요청과 응답을 변환하거나 필터링

 

   ▶  Spring Cloud Gateway 개요

       ●   Spring Cloud Gateway?
            ○  Spring Cloud Gateway는 Spring 프로젝트의 일환으로 개발된 API 게이트웨이로, 클라이언트 요청을 적절한 서비스로 라우팅하고 다양한 필터링 기능을 제공한다.
              Spring Cloud Netflix 패키지의 일부로, 마이크로서비스 아키텍처에서 널리 사용된다.


       ●  Spring Cloud Gateway의 주요 특징
            ○  동적 라우팅 : 요청의 URL 패턴에 따라 동적으로 라우팅
              필터링 : 요청 전후에 다양한 작업을 수행할 수 있는 필터 체인 제공
            ○  모니터링 : 요청 로그 및 메트릭을 통해 서비스 상태 모니터링
              보안 : 요청의 인증 및 권한 검증

 

 

   ▶  Spring Cloud Gateway 설정

       ●   기본 설정
            ○  Spring Cloud Gateway를 사용하려면 Spring Boot 애플리케이션에 의존성을 추가해야 한다.
           📌  build.gradle  파일 예시 : 

Groovy

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
	  implementation 'org.springframework.boot:spring-boot-starter-actuator'
	  implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
	  implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}



       ●  라우팅 설정
            ○   application.yml 파일에서 라우팅 설정을 정의할 수 있다.
           📌 예시 설정 파일 : 

YAML

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  # 서비스 디스커버리를 통해 동적으로 라우트를 생성하도록 설정
      routes:
        - id: users-service  # 라우트 식별자
          uri: lb://users-service # 'users-service'라는 이름으로 로드 밸런싱된 서비스로 라우팅
          predicates:
            - Path=/users/** # /users/** 경로로 들어오는 요청을 이 라우트로 처리
        - id: orders-service  # 라우트 식별자
          uri: lb://orders-service  # 'orders-service'라는 이름으로 로드 밸런싱된 서비스로 라우팅
          predicates:
            - Path=/orders/** #/orders/** 경로로 들어오는 요청을 이 라우트로 처리

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

 

   ▶  Spring Cloud Gateway 필터링

       ●   필터 종류
            ○  Global Filter : 모든 요청에 대해 작동하는 필터
              Gateway Filter : 특정 라우트에만 적용되는 필터


       ●  필터 구현
            ○  필터를 구현하려면  GlobalFilter  또는  GatewayFilter  인터페이스를 구현하고,  filter  메서드를 오버라이드해야한다.


       ●   필터 주요 객체
            ○  Mono
               ▪   Mono 는 리액티브 프로그래밍에서 0 또는 1개의 데이터를 비동기적으로 처리한다.
               ▪   Mono<Void> 는 아무 데이터도 반환하지 않음을 의미한다.
              ServerWebExchange
               ▪   ServerWebExchange 는 HTTP 요청과 응답을 캡슐화한 객체다.
               ▪   exchange.getRequest() 로 HTTP 요청을 가져온다.
               ▪   exchange.getResponse() 로 HTTP 응답을 가져온다.

              GatewayFilterChain
               ▪   GatewayFilterChain 여러 필터를 체인처럼 연결한다.
               ▪   chain.filter(exchange) 는 다음 필터로 요청을 전달한다.


       ●   필터 시점별 종류
            ○  Pre 필터
               ▪  Pre 필터는 요청이 처리되기 전에 실행된다.
               ▪  따라서 Pre 필터에서는 요청을 가로채고 필요한 작업을 수행한 다음, 체인의 다음 필터로 요청을 전달한다.
               ▪  이때, 추가적인 비동기 작업을 수행할 필요가 없기 때문에  then 메서드를 사용할 필요가 없다.

@Component
public class PreFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 요청 로깅
        System.out.println("Request: " + exchange.getRequest().getPath());
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {  // 필터의 순서를 지정합니다.
        return -1;  // 필터 순서를 가장 높은 우선 순위로 설정합니다.
    }
}

              Post 필터
               ▪  Post 필터는 요청이 처리된 후, 응답이 반환되기 전에 실행된다.
               ▪  Post 필터에서는 체인의 다음 필터가 완료된 후에 실행되어야 하는 추가적인 작업을 수행해야 한다.
               ▪  따라서  chain.filter(exchange) 를 호출하여 다음 필터를 실행한 후,  then 메서드를 사용하여 응답이 완료된 후에 실행할 작업을 정의한다.

@Component
public class PostFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // 응답 로깅
            System.out.println("Response Status: " + exchange.getResponse().getStatusCode());
        }));
    }

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

 

 

   ▶  Spring Cloud와의 통합

       ●  Spring Cloud와의 통합
            ○  Spring Cloud Gateway는 Spring Cloud Netflix 패키지의 일부로, Eureka와 쉽게 통합할 수 있다.
              Eureka를 통해 동적으로 서비스 인스턴스를 조회하여 로드 밸런싱과 라우팅을 수행할 수 있다.

 

 

   ▶ Zuul(Spring Boot 2)

⚠️  대부분의 회사에서 이미 만들어진 시스템은 스프링 부트 2를 사용하고 있을 가능성이 크다. 이 섹션에서는 Zuul의 기능에 집중하자. ”클라우드 게이트웨이와 같은 기능을 제공하고 있구나”라고 생각하고 넘어가면 된다.


       ●   Zuul 설정
            ○  Spring Boot 2에서는 Zuul을 사용하여 API 게이트웨이를 설정할 수 있다.
           📌  build.gradle  파일 예시 : 

dependencies {
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-zuul'
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}


            ⚙️ Spring Boot 애플리케이션 설정:

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

 

       ●  라우팅 설정
              application.yml   파일에서 라우팅 설정을 정의할 수 있다.
           📌 예시 설정 파일 : 

zuul:
  routes:
    users-service:
      path: /users/**
      serviceId: users-service
    orders-service:
      path: /orders/**
      serviceId: orders-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

 

       ●  필터 설정
              Zuul 필터를 사용하여 요청 전후에 다양한 작업을 수행할 수 있다.
           📌 예시 코드 : 

@Component
public class PreFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre";
    }

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

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        // 요청 로깅
        System.out.println(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
        return null;
    }
}