[MSA] chapter 3_Spring Cloud gateway ์„ค์ •

Updated:

Categories:

Tags: ,

๐Ÿ“Œ ๊ฐœ์ธ์ ์ธ ๊ณต๊ฐ„์œผ๋กœ ๊ณต๋ถ€๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ๋ณต์Šตํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ธ”๋กœ๊ทธ์ž…๋‹ˆ๋‹ค.
์ •ํ™•ํ•˜์ง€ ์•Š์€ ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ ๋ฐ”๋ž๋‹ˆ๋‹ค :๐Ÿ˜ธ
[ํ‹€๋ฆฐ ๋‚ด์šฉ์€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๋ณต๋ฐ›์œผ์‹ค๊ฑฐ์—์š”]

์ธํ”„๋Ÿฐ Dowon Lee๋‹˜์˜ Spring Cloud๋กœ ๊ฐœ๋ฐœํ•˜๋Š” ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(MSA) ๊ฐ•์˜๋ฅผ ๋“ฃ๊ณ  ์ •๋ฆฌํ•œ ํ•„๊ธฐ์ž…๋‹ˆ๋‹ค.๐Ÿ˜Š
Spring Cloud๋กœ ๊ฐœ๋ฐœํ•˜๋Š” ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(MSA) ๊ฐ•์˜ ๋“ค์œผ๋Ÿฌ ๊ฐ€๊ธฐ๐Ÿ‘ฉโ€๐Ÿซ

gateway ์‹ค์Šต 1 : application.yml์—์„œ ์„ค์ •

  1. build.gradle

    spring-cloud-starter-gateway๋Š” Gateway ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ, WebFlux๋ฅผ ํ†ตํ•ด Netty ์„œ๋ฒ„์—์„œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ง€์›ํ•œ๋‹ค.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
     plugins {
     	id 'org.springframework.boot' version '2.7.0'
     	id 'io.spring.dependency-management' version '1.0.13.RELEASE'
     	id 'java'
     }
     ext {
     	set('springCloudVersion', "2021.0.3")
     }
     dependencies {
     	implementation 'org.springframework.boot:spring-boot-starter-webflux'
     	implementation 'org.springframework.boot:spring-boot-starter-data-redis'
     	implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
     	compileOnly 'org.projectlombok:lombok'
     	annotationProcessor 'org.projectlombok:lombok'
     }
        
     dependencyManagement {
     	imports {
     		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
     	}
     }
    
  2. application.yml

    Gateway ์„ค์ • ํŒŒ์ผ์—์„œ Gateway์˜ ํฌํŠธ, Eureka์™€์˜ ์—ฐ๋™, ๊ทธ๋ฆฌ๊ณ  ๊ฐ ๋ผ์šฐํŠธ(route)๋ฅผ ์ •์˜ํ•œ๋‹ค.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
     server:
       port: 8000  # API Gateway๋Š” 8000 ํฌํŠธ์—์„œ ์‹คํ–‰
        
     eureka:
       client:
         register-with-eureka: true
         fetch-registry: true
         service-url:
           defaultZone: http://127.0.0.1:8761/eureka  # Eureka ์„œ๋ฒ„ URL ์„ค์ •
        
     spring:
       application:
         name: api-gateway
       cloud:
         gateway:
           routes:
             - id: auth-api
               uri: http://localhost:8081
               predicates:
                 - path=/auth-api/**
             - id: core-api
               uri: http://localhost:8082
               predicates:
                 - path=/core-api/**
    
    • Eureka ์„ค์ •: Gateway๊ฐ€ Eureka ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜์—ฌ ๊ฐ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์˜ ์œ„์น˜๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•œ๋‹ค.
    • Route ์„ค์ •:
      • /auth-api/** ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์€ http://localhost:8081์— ๋ฐฐ์น˜๋œ auth-api๋กœ ๋ผ์šฐํŒ…๋œ๋‹ค.
      • /core-api/** ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์€ http://localhost:8082์— ๋ฐฐ์น˜๋œ core-api๋กœ ๋ผ์šฐํŒ…๋œ๋‹ค.

    ์ด๋กœ์จ Gateway๋Š” /auth-api/** ๋ฐ /core-api/** ๊ฒฝ๋กœ์˜ ์š”์ฒญ์„ ๊ฐ๊ฐ์˜ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋ถ„๋ฐฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

  3. Netty ์‹คํ–‰ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ

    ๊ธฐ์กด์˜ ํ†ฐ์บฃ ์„œ๋ฒ„๊ฐ€ ์•„๋‹Œ Netty ์„œ๋ฒ„๊ฐ€ Spring Cloud Gateway์—์„œ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” Spring WebFlux๊ฐ€ ๋น„๋™๊ธฐ ํ™˜๊ฒฝ์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด Netty ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋ฉฐ, Spring Cloud Gateway๋Š” ์ด๋Ÿฌํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์— ์ตœ์ ํ™”๋˜์–ด ์žˆ๋‹ค.

  4. ๊ทผ๋ฐ 404?๊ฐ€ ๋‚˜์˜ด

    ์™œ๋ƒ๋ฉด http://localhost:8082/core-api/** ์ด๋ ‡๊ฒŒ ์š”์ฒญ์ด ๊ฐ€๊ธฐ๋•Œ๋ฌธ์ด๋‹ค.

    ํ•˜์ง€๋งŒ ์‹ค์ œ ์„œ๋น„์Šค๋Š” ์•„๋ž˜ ์ฃผ์„๊ณผ ๊ฐ™์ด localhost:8082/documents ๋กœ ๋˜์–ด์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋”ฐ๋กœ ์ฒ˜๋ฆฌํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

  • Spring Cloud Gateway์˜ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฝ๋กœ๋ฅผ ์žฌ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ํ”„๋ฆฌํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด ๊ฒฝ๋กœ๋ฅผ /documents๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Gateway๊ฐ€ ์š”์ฒญ ๊ฒฝ๋กœ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • 404 ๋‚˜์˜จ ์—๋Ÿฌ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ yml์—์„œ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ java code๋กœ ํ•„ํ„ฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

    1
    2
    3
    4
    5
    6
    7
    
        routes:
              - id: core-api
                uri: http://localhost:8082   # ์‹ค์ œ core-api ์„œ๋น„์Šค URL
                predicates:
                  - Path=/core-api/**
                filters:
                  - RewritePath=/core-api/(?<segment>.*), /documents/${segment}  # ๊ฒฝ๋กœ ๋ณ€๊ฒฝ ํ•„ํ„ฐ
    

yml์—์„œ ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ• ์™ธ์— java code๋กœ ํ•„ํ„ฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

gateway ์‹ค์Šต 1 : java code ๋กœ ์„ค์ • (Spring Cloud Gateway์™€ ํ•„ํ„ฐ ๊ตฌ์„ฑ ์š”์†Œ)

Spring Cloud Gateway๋Š” ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์—์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ๊ฐ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋ผ์šฐํŒ…ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ์ด ๊ณผ์ •์—์„œ ์š”์ฒญ์„ ์ „์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ ํ›„์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ํ•„ํ„ฐ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด, ์š”์ฒญ์˜ ํ๋ฆ„์„ ์œ ์—ฐํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฃผ์š” ํ•„ํ„ฐ ๊ตฌ์„ฑ ์š”์†Œ

  • ํ”„๋ ˆ๋””์ผ€์ดํŠธ(Predicate): ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์ด ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ํŒ๋‹จํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋ฉฐ, ์กฐ๊ฑด์— ๋”ฐ๋ผ ์š”์ฒญ์„ ๋ผ์šฐํŒ…ํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, URL ๊ฒฝ๋กœ๋‚˜ ํ—ค๋” ๊ฐ’์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์„œ๋น„์Šค๋กœ ๋ผ์šฐํŒ…ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ”„๋ฆฌํ•„ํ„ฐ(Pre-Filter): ์š”์ฒญ์ด ๊ฐ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ์ „๋‹ฌ๋˜๊ธฐ ์ „์— ์‹คํ–‰๋˜๋Š” ํ•„ํ„ฐ๋กœ, ์š”์ฒญ ํ—ค๋” ์ถ”๊ฐ€๋‚˜ ์š”์ฒญ ๋ฐ์ดํ„ฐ ์ˆ˜์ • ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ํฌ์ŠคํŠธํ•„ํ„ฐ(Post-Filter): ์š”์ฒญ์ด ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์—์„œ ์ฒ˜๋ฆฌ๋œ ํ›„์— ์‹คํ–‰๋˜๋Š” ํ•„ํ„ฐ๋กœ, ์‘๋‹ต ํ—ค๋” ์ถ”๊ฐ€๋‚˜ ์‘๋‹ต ๋ฐ์ดํ„ฐ ์ˆ˜์ • ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

์š”์ฒญ ์ •๋ณด๊ฐ€ ๋“ค์–ด์˜ค๊ฒŒ ๋˜๋ฉด ๊ทธ๊ฒŒ ์–ด๋–ค ๊ฒƒ์ธ์ง€ ํŒ๋‹จํ•˜๋Š” ๊ฒŒ ํ”„๋ฆฌํ‹ฐ์ผ€์ดํŠธ๊ณ  ํ”„๋ฆฌํ•„ํ„ฐ๋Š” ์–ด๋–ค์ž‘์—…์ด ์ผ์–ด๋‚˜๊ธฐ ์‚ฌ์ „ ํ•„ํ„ฐ, ์–ด๋–ค ์ฒ˜๋ฆฌ๊ฐ€ ๋๋‚œ ๋‹ค์Œ์— ํ˜ธ์ถœ๋˜๋Š” ํฌ์ŠคํŠธํ•„ํ„ฐ๊ฐ€ ๋‚˜๋ˆ ์ง„๋‹ค.

์ฝ”๋“œ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•œ Spring Cloud Gateway ์„ค์ •

Spring Cloud Gateway์—์„œ ๊ฒฝ๋กœ์™€ ํ•„ํ„ฐ๋ฅผ ์„ค์ •ํ•˜๋Š” ์ฝ”๋“œ๋กœ, ๊ฐ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ์˜ ์š”์ฒญ์„ ํŠน์ • ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ๋ผ์šฐํŒ…ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, /auth-api/** ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜จ ์š”์ฒญ์€ auth-api ์„œ๋น„์Šค๋กœ, /core-api/** ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜จ ์š”์ฒญ์€ core-api ์„œ๋น„์Šค๋กœ ๋ผ์šฐํŒ…๋œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
public class RouteLocatorConfig {
  @Bean
  public RouteLocator routeLocator(RouteLocatorBuilder builder, JwtFilter jwtFilter) {
      return builder.routes()
          .route("auth-api", r -> r.path("/auth-api/**")
                          .filters(f -> f.addRequestHeader("first-request", "first-request-header")
                                         .addResponseHeader("first-response", "first-response-header"))
                          .uri("http://localhost:8081/"))
          .route("core-api", r -> r.path("/core-api/**")
                          .filters(f -> f.addRequestHeader("second-request", "second-request-header")
                                         .addResponseHeader("second-response", "second-response-header"))
                          .uri("http://localhost:8082/"))
          .build();
  }
}

  1. ํ•„ํ„ฐ ์„ค์ •
    • addRequestHeader: ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ์š”์ฒญ์— ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, โ€œfirst-requestโ€ ํ—ค๋”๋ฅผ โ€œfirst-request-headerโ€ ๊ฐ’์œผ๋กœ ์ถ”๊ฐ€ํ•˜์—ฌ ํ”„๋ฆฌํ•„ํ„ฐ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
    • addResponseHeader: ์š”์ฒญ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋œ ํ›„ ์‘๋‹ต์— ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, โ€œfirst-responseโ€ ํ—ค๋”๋ฅผ ์‘๋‹ต์— ํฌํ•จํ•ด ํฌ์ŠคํŠธํ•„ํ„ฐ์—์„œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ๋ผ์šฐํŒ… ํ๋ฆ„
    1. ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ: ํด๋ผ์ด์–ธํŠธ๋Š” API Gateway๋ฅผ ํ†ตํ•ด /auth-api/** ๋˜๋Š” /core-api/** ๊ฒฝ๋กœ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
    2. Spring Cloud Gateway ์ฒ˜๋ฆฌ: Gateway๋Š” ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ์š”์ฒญ์„ ๋ผ์šฐํŒ…ํ•˜๊ณ , ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ•ด ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
    3. ํผ์ŠคํŠธ ์„œ๋น„์Šค์™€ ์„ธ์ปจ๋“œ ์„œ๋น„์Šค: ๊ฐ๊ฐ์˜ ๊ฒฝ๋กœ์— ๋”ฐ๋ผ 8081 ํฌํŠธ์—์„œ ๋™์ž‘ํ•˜๋Š” auth-api์™€ 8082 ํฌํŠธ์—์„œ ๋™์ž‘ํ•˜๋Š” core-api ์„œ๋น„์Šค๋กœ ์š”์ฒญ์ด ์ „๋‹ฌ๋œ๋‹ค.
    4. ์‘๋‹ต ๋ฐ˜ํ™˜: ๊ฐ ์„œ๋น„์Šค์—์„œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•œ ํ›„ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ํฌ์ŠคํŠธํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด ์‘๋‹ต ํ—ค๋”๊ฐ€ ์ถ”๊ฐ€๋œ๋‹ค.

ํ…Œ์ŠคํŠธ ๋ฐ ์ž‘๋™ ๊ณผ์ •

  • ํ…Œ์ŠคํŠธ ํฌํŠธ: Gateway๊ฐ€ 8000 ํฌํŠธ์—์„œ ์ž‘๋™ํ•˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๋Š” ์ด ํฌํŠธ๋ฅผ ํ†ตํ•ด ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, http://localhost:8000/auth-api/...๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด, Spring Cloud Gateway๊ฐ€ ์š”์ฒญ์„ 8081 ํฌํŠธ์˜ auth-api๋กœ ๋ผ์šฐํŒ…ํ•œ๋‹ค.
  • ํ—ค๋” ํ™•์ธ: Spring Cloud Gateway์—์„œ ์ถ”๊ฐ€ํ•œ ์š”์ฒญ ๋ฐ ์‘๋‹ต ํ—ค๋” ๊ฐ’(first-request-header ๋ฐ first-response-header ๋“ฑ)์„ ํผ์ŠคํŠธ ์„œ๋น„์Šค์™€ ์„ธ์ปจ๋“œ ์„œ๋น„์Šค์—์„œ ํ™•์ธํ•˜๊ณ , ์ฒ˜๋ฆฌ ํ›„ ์‘๋‹ต์œผ๋กœ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

์š”์•ฝ๐Ÿ‘ฉโ€๐Ÿซ

Spring Cloud Gateway๋Š” ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์„ ํŠน์ • ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋ผ์šฐํŒ…ํ•˜๋ฉฐ, ํ”„๋ฆฌํ•„ํ„ฐ์™€ ํฌ์ŠคํŠธํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด ์š”์ฒญ ๋ฐ ์‘๋‹ต์„ ์œ ์—ฐํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด API Gateway๋Š” ๋ผ์šฐํŒ… ์™ธ์—๋„, ๋ณด์•ˆ, ๋กœ๊น…, ์‘๋‹ต ์บ์‹ฑ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, MSA ํ™˜๊ฒฝ์—์„œ์˜ ์œ ์—ฐํ•œ ์„œ๋น„์Šค ํ†ต์‹ ์„ ์ง€์›ํ•œ๋‹ค.

MSA ์นดํ…Œ๊ณ ๋ฆฌ ๋‚ด ๋‹ค๋ฅธ ๊ธ€ ๋ณด๋Ÿฌ๊ฐ€๊ธฐ

Leave a comment