[MSA] chapter 3_Spring Cloud Gateway :Custom Filter

Updated:

Categories:

Tags: ,

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

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

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

1. ์ปค์Šคํ…€ ํ•„ํ„ฐ ๊ตฌํ˜„ ๋ฐ ๋“ฑ๋ก

Spring Cloud Gateway์—์„œ ์‚ฌ์šฉ์ž ์ •์˜ ํ•„ํ„ฐ(Custom Filter)๋ฅผ ํ†ตํ•ด ํŠน์ • ์กฐ๊ฑด์— ๋งž๋Š” ์š”์ฒญ์„ ํ•„ํ„ฐ๋งํ•˜๊ณ , ๋กœ๊ทธ ๊ธฐ๋ก์ด๋‚˜ ์ธ์ฆ ์ฒ˜๋ฆฌ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. CustomFilter ํด๋ž˜์Šค๋Š” ๋ฐ˜๋“œ์‹œ AbstractGatewayFilterFactory๋ฅผ ์ƒ์†๋ฐ›์•„์•ผ ํ•˜๋ฉฐ, apply ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ์›ํ•˜๋Š” ์ž‘์—…์„ ์ •์˜ํ•œ๋‹ค.

apply๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•ด์„œ ๊ตฌํ˜„ โ†’ ์ž‘๋™ํ•˜๊ณ ์ž ํ•˜๋Š” ๋‚ด์šฉ์„ ๊ธฐ์ˆ ํ•˜๋ฉด ๋œ๋‹ค. ( GatewayFilter)๋ผ๋Š” ๊ฒƒ์„ ๋ฐ˜ํ™˜์‹œ์ผœ ์คŒ์œผ๋กœ์จ ์–ด๋–ค ์ž‘์—…์„ ํ•  ๊ฒƒ์ธ์ง€ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Component
@Slf4j
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {
    public CustomFilter() {
        super(Config.class);
        //Configuration ์ •๋ณด๊ฐ€ ์žˆ๋‹ค๋ฉด ์ž๊ธฐ ์ž์‹ ์˜ ํด๋ž˜์Šค ์•ˆ์—์„œ Config๋ผ๋Š” ๋‚ด๋ถ€ํด๋ž˜์Šค๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋“ฑ๋ก
    }

    @Override
    public GatewayFilter apply(CustomFilter.Config config) {
        // 1 Custom Pre Filter. Suppose we can extract JWT and perform Authentication
        return ((exchange, chain) -> {
            
            // 2
            // Netty๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„๋™๊ธฐ ๋ฐฉ์‹์ด๊ณ 
            // ๋น„๋™๊ธฐ ๋ฐฉ์‹์ผ๋•Œ๋Š” request, response ๋ฅผ ๋Œ€์‹ ํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.
            ServletHttpRequest request = exchange.getRequest();
            ServletHttpResponse response = exchange.getResponse();
            
            log.info("Custom PRE filter: request uri -> {}", request.getId());
            //Custom Post Filter.Suppose we can call error response handler based on error code.
            //์–ด๋–ค ํ•„ํ„ฐ๊ฐ€ ์ ์šฉ๋  ๊ฑด์ง€ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ
            // WebFlux๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด์„œ ์„œ๋ฒ„๊ตฌ์ถ•ํ•  ๋•Œ๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ MonoDataType์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 
            return chain.filter(exchange).then(Mono.fromRunnable() -> {
                log.info("Custom POST filter: response code -> {}", response.getStatusCode());
            }));
        }
    }
}
  • ํ”„๋ฆฌํ•„ํ„ฐ: apply ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ request ๊ฐ์ฒด์—์„œ URI๋ฅผ ๊ฐ€์ ธ์™€ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅ.
  • ํฌ์ŠคํŠธํ•„ํ„ฐ: chain.filter(exchange).then์„ ์‚ฌ์šฉํ•ด, ์‘๋‹ต์ด ๋ฐ˜ํ™˜๋  ๋•Œ ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅ.

2. Configuration ์„ค์ •

ํ•„์š”์— ๋”ฐ๋ผ Configuration ์ •๋ณด๊ฐ€ ์žˆ์œผ๋ฉด Config๋ผ๋Š” ๋‚ด๋ถ€ ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์„ค์ •์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

3. ํ•„ํ„ฐ ์„ค์ •๊ณผ ํ™œ์šฉ

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

4. ์„œ๋ฒ„ ์„ค์ •: Netty

์ด์ „๊นŒ์ง€ tomcat์„ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ ์ง€๊ธˆ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ Netty๋ผ๋Š” ๋‚ด์žฅ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

  • Netty: ๋น„๋™๊ธฐ ๋ฐฉ์‹์˜ ๋‚ด์žฅ ์„œ๋ฒ„๋กœ, ์„œ๋ฒ„ ๋ฆฌ์†Œ์Šค ๊ด€๋ฆฌ๊ฐ€ ํšจ์œจ์ ์ด๋ฉฐ ๋น„๋™๊ธฐ HTTP ์š”์ฒญ์„ ์ง€์›ํ•œ๋‹ค. Tomcat๊ณผ ๊ฐ™์€ ๋™๊ธฐ ๋ฐฉ์‹์˜ ์„œ๋ฒ„์™€๋Š” ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ request์™€ response ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃฌ๋‹ค.
  • ์„œ๋ฒ„ response๊ฐ์ฒด ์‚ฌ์šฉ: Netty์—์„œ๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์„œ๋ธ”๋ฆฟ ์š”์ฒญ ๋ฐฉ์‹ ๋Œ€์‹  HTTP ๋ฆฌํ€˜์ŠคํŠธ์™€ ๋ฆฌ์ŠคํŒ์Šค๋ฅผ ๊ฐ์ฒด๋กœ ๋‹ค๋ฃฌ๋‹ค. ์ด๋กœ ์ธํ•ด ์„œ๋ฒ„์˜ ๋™์‹œ ์ฒ˜๋ฆฌ ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋  ์ˆ˜ ์žˆ๋‹ค.

5. JWT ์ธ์ฆ์„ ํ™œ์šฉํ•œ ์ธ์ฆ ์ฒ˜๋ฆฌ

  • JWT ํ† ํฐ ์ธ์ฆ: ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ•˜๋ฉด JWT(JSON Web Token)๋ฅผ ๋ฐœ๊ธ‰๋ฐ›์•„ ํ”„๋ฆฌํ•„ํ„ฐ์—์„œ ์ด๋ฅผ ํ™•์ธํ•œ๋‹ค. ์ดํ›„ ๊ฐ ์š”์ฒญ๋งˆ๋‹ค ์ด ํ† ํฐ์„ ํ†ตํ•ด ์ธ์ฆ ๋ฐ ์ธ๊ฐ€๊ฐ€ ์ด๋ฃจ์–ด์ง„๋‹ค.
  • ๊ฒŒ์ดํŠธ์›จ์ด ์—ฐ๋™: ๊ฒŒ์ดํŠธ์›จ์ด ์•ž๋‹จ์—์„œ ์ธ์ฆ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ๊ฐ ์„œ๋น„์Šค๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ํ•„์š”ํ•œ ๋ณด์•ˆ์„ฑ์„ ํ™•๋ณดํ•œ๋‹ค.

6. YAML ์„ค์ • ์ถ”๊ฐ€

yml ํŒŒ์ผ์—๋Š” filters์— CustomFilter ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: auth
          uri: http://localhost:8081
          predicates:
            - path=/auth-api/**
          filters:
            - CustomFilter
        - id: core
          uri: http://localhost:8082
          predicates:
            - path=/core-api/**
          filters:
            - CustomFilter

7. ํ…Œ์ŠคํŠธ์™€ ๊ฒ€์ฆ

  • ์„œ๋น„์Šค ์ปจํŠธ๋กค๋Ÿฌ์— ์ฒดํฌ ๋ฉ”์„œ๋“œ ๋“ฑ๋ก: ์ฒซ ๋ฒˆ์งธ์™€ ๋‘ ๋ฒˆ์งธ ์„œ๋น„์Šค ์ปจํŠธ๋กค๋Ÿฌ์— ์ฒดํฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด ํ•„ํ„ฐ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•œ๋‹ค.
  • ๋กœ๊ทธ ํ™•์ธ: ํ”„๋ฆฌํ•„ํ„ฐ์™€ ํฌ์ŠคํŠธํ•„ํ„ฐ๊ฐ€ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ˆœ์„œ๋ฅผ ๋กœ๊ทธ๋กœ ๋‚จ๊ฒจ, ํ•„ํ„ฐ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
    1
    2
    3
    4
    
    @GetMapping("/check")
    public String check() {
          return "Hi, there. This is a message from First Service";
    }
    
1
2
3
4
@GetMapping("/check")
public String check() {
		return "Hi, there. This is a message from Second Service";
}





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

Leave a comment