jjuya 개발 기록 2024. 8. 18. 18:42

API Gateway란?

MSA 아키텍처에서 외부(클라이언트)로부터 각각의 마이크로 서비스로 진입하는 진입점입니다. API Gateway를 공통적으로 사용하여 외부에서는 각 마이크로 서비스를 몰라도 API Gateway의 라우팅을 통해 호출할 수 있습니다.

또한 추가적으로 요청에대한 공통 관심사를 API Gateway에서 처리할 수 있습니다.

 


현재 e-commerce프로젝트에서는 인증 까지  API Gateway 가 해줄수 있게 작업할 예정이다.

spring security를 설치하냐 마냐에 대해서도 계속 고민이 되는 지점인 거 같다.

하지만 일단 지금시점에서는  API Gateway 에 너무 많은 역할을 부여하지 말아야 한다는 생각으로 시큐리티는 user-service에만 설치할 예정이다.

 

API Gateway 라이브러리

 API Gateway를 구현하기 위한 라이브러리로는 대표적으로 두 가지가 있습니다.

  • Netflix Zuul
  • Spring Cloud Gateway

Netfilx Zuul은 Servlet 기반의 동기 방식 이고, Spring Cloud Gateway는 Netty 기반의 비동기/Non-blocking 방식입니다.

Spring Cloud Gateway는 Spring webFlux 위에서 동작, Spring Cloud Gateway는 Spring Reactive 환경에서 구현된 API Gateway입니다.

 

Spring 측에서 Netflix Zuul에 관한 지원(개발 및 유지보수)을 중지하고 Spring Cloud Gateway를 권장하고 있다고합니다.

그래서 Spring Cloud Gateway를 이용해 프로젝트에 적용해 볼 예정이다!

 

 Spring Cloud Gateway 적용

1. 의존성 추가

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.3.2'
    id 'io.spring.dependency-management' version '1.1.6'
}
...
ext {
    set('springCloudVersion', "2023.0.3")
}

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

	...
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

Eureka-service와 함께 연동할것이기 때문에 같이 추가해준다!

여담을 하자면 Spring cloud와 Spring boot의 버전을 맞춰주지 않아서 꽤 고생을 했다^^

 

2. Eureka Client 활성화

@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayApplication {

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

}

 

2. application.yml 설정

server:
  port: 8080

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    serviceUrl:
      defaultZone: http://localhost:8761/eureka

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/api/member/**
        - id : product-service
          uri : lb://PRODUCT-SERVICE
          predicates:
            - Path=/api/products/**
        - id: order-service
          uri: lb://ORDER-SERVICE
          predicates:
            - Path=/api/orders/**
  • spring.cloud.gateway.routes.id : 라우팅을 구분하기 위한 route id를 지정
  • spring.cloud.gateway.routes.uri : 요청이 라우팅되는 경로 URI
    • lb -> load balancer
    • 프로토콜(lb://)의 경로를 지정하면 기본적으로 Eureka Server에서 호스트에 해당하는 서비스를 찾고 로드밸런싱을 수행합니다.
  • spring.cloud.gateway.routes.predicates : 해당 라우팅을 진행할 URI 조건으로, Gateway로 들어오는 요청 URI를 지정

 

API Gateway에 설정한 :8080의 포트로 url요청을 보내면 연결된 각각의 서비스에 라우팅을 해준다.

 

ex) user-service : http://localhost:8081/  (8081포트)

user-service 의 회원가입 url -> /api/member/sign-up

"http://localhost:8081/api/member/sign-up" 로 요청해야했지만,

API Gateway가 진입점에서 라우팅을해주기 때문에

"http://localhost:8080/api/member/sign-up " 으로 요청하면된다.

 

4. 인증 처리 필터 구현

인증처리 필터를 구현하고, yml파일에서 인증 하고 싶은곳에 filter를 걸어주면된다!

...
- id: order-service
  uri: lb://ORDER-SERVICE
  predicates:
    - Path=/api/orders/**
  filters:
    - AuthorizationHeaderFilter #인증을 해주는 필터