본문 바로가기

Backend/MSA

241122 API 게이트웨이 실습 TIL

API 게이트웨이란?

API 게이트웨이란 클라이언트의 요청을 받아 백엔드 서비스로 라우팅하고, 다양한 부가 기능을 제공하는 중간 서버이다.

- 라우팅 : 클라이언트의 요청을 적절한 서비스로 전달한다.

- 인증 및 권한 부여 : 요청의 인증 및 권한을 검증한다.

- 로드 밸런싱 : 여러 서비스 인스턴스 간의 부하를 분산한다.

- 모니터링 및 로깅 : 요청 및 응답을 로깅하고 모니터링한다.

- 요청 및 응답 변환 : 요청과 응답을 변환하거나 필터링한다.

 

API 게이트웨이란?

 

예를 들면 order 애플리케이션, product 애플리케이션, user 애플리케이션의 정보를 원할 때 각각의 서비스를 각각 호출해야한다. 그럼 엔드포인트 앞에 붙는 호스트가 다 다를텐데, 우리는 API 게이트웨이를 통해 하나의 호스트로 요청을 보낼 수 있다.

 

즉, 사용자는 각 애플리케이션의 엔드포인트를 개별적으로 호출할 필요 없이, API 게이트웨이를 통해 동일한 호스트로 요청을 보낼 수 있다. API 게이트웨이는 이러한 요청을 수신한 후, 내부적으로 적절한 애플리케이션으로 라우팅하여 처리한다.  

Spring Cloud Gateway 란?

Spring 프로젝트의 일환으로 개발된 API 게이트웨이로, 클라이언트 요청을 적절한 서비스로 라우팅하고, 다양한 필터링 기능을 제공한다.

 

Spring Cloud 게이트웨이 설정

1) 의존성을 추가하고 application.yml 파일에서 Spring Cloud Gateway의 라우팅을 설정한다.

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

 

Spring Cloud 게이트웨이 필터링

2) 필터를 추가한다.

 

필터 종류

- Global Filter : 모든 요청에 대해 작동하는 필터

- Gateway Filter : 특정 라우트에만 적용되는 필터

 

필터 구현

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

 

- Pre 필터 : 요청이 처리되기 전에 실행되는 필터.

Pre 필터에서는 요청을 가로채고 필요한 작업을 수행한 다음, 체인의 다음 필터로 요청을 전달한다.

@Component
public class CustomPreFilter implements GlobalFilter, Ordered {

    private static final Logger logger = Logger.getLogger(CustomPreFilter.class.getName());

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        logger.info("Pre Filter: Request URI" + request.getURI());
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

 

- Post 필터 : 요청이 처리된 후, 응답이 반환되기 전에 실행되는 필터. 

chain.filter(exhange)를 호출하여 다음 필터를 실행한 후, then 메서드를 사용하여 응답이 완료된 후에 실행할 작업을 정의해야한다. 

@Component
public class CustomPostFilter implements GlobalFilter, Ordered {

    private static final Logger logger = Logger.getLogger(CustomPreFilter.class.getName());

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            ServerHttpResponse response = exchange.getResponse();
            logger.info("Post Filter : Response status code is "+ response.getStatusCode());
        }));
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

 

 

+) Zuul(Spring Boot 2) 에서 API 게이트 웨이 설정하는 법 교안 참고

 


Spring Cloud Gateway 실습해보기

클라우드 게이트 웨이 + 유레카 + Order 인스턴스 1개 + Product 인스턴스 2개로 실습해보자.

 

+) 사용중인 포트 강제로 죽이는 법

- 윈도우

1. 정지시키고자 하는 포트 찾기

netstat -a -o | findstr 19093

 

2. 해당 포트를 사용중인 프로세스 리스트가 나오면 리스트의 마지막 PID 기억하기

3. 명령어를 통해 PID 프로세스 정지하기.

taskkill /f /pid PID

 

- 맥

1. 정지시키고자 하는 포트 찾기

lsof -i :19090

 

2. 조회된 PID를 통해 포트의 프로세스 종료하기

kill -9 PID

 

Eureka 서버에 위에서 설정한 Gateway와 order, product를 띄운다.

 

order를 호출할 때 게이트웨이에서 pre 필터와 post 필터를 거치는 걸 볼 수 있다.
마찬가지로 게이트 웨이 포트에서 product를 호출했을 때 pre 필터와 post 필터를 거치며 로드밸런싱으로 받아오는 걸 확인할 수 있다.

 

즉, 이렇게 API 게이트 웨이를 설정해주니 product와 order 서비스 등을 호출할 때 마다 포트를 변경할 필요없이, 게이트 웨이 포트 19091에 요청하면 된다. 게이트 웨이는 요청을 적절한 서비스로 라우팅하여 처리해준다.

또한 게이트 웨이 안에 설정된 필터를 반드시 거치게 되므로, 공통적으로 필요한 인증, 로깅, 요청 변환 등의 작업을 중앙에서 처리할 수 있다.