MSA ํ™˜๊ฒฝ์—์„œ ์ธ์ฆ, ์ธ๊ฐ€๋Š” ์–ด๋””์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒŒ ์˜ณ์„๊นŒ?

1. ๊ฐœ์š”

MSA๋ฅผ ๋„์ž…ํ•˜๋ฉด์„œ, ํ˜น์€ ๊ณ ๋ คํ•˜๋ฉด์„œ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด ์ธ์ฆ ์ธ๊ฐ€์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์„ ํ•˜๊ฒŒ ๋ ๊ฑฐ๋ผ ์ƒ๊ฐํ•œ๋‹ค.

 

 

๋‚˜๋„ Spring Cloud๋ฅผ ์‚ฌ์šฉํ•œ MSA ์•„ํ‚คํ…์ฒ˜ ๊ตฌ์กฐ๋กœ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์ธ์ฆ, ์ธ๊ฐ€์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์„ ํ•˜๊ฒŒ ๋๋‹ค. ๊ตฌ๊ธ€๋ง ํ•ด๋ณด๋ฉด ํฌ๊ฒŒ 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‚˜๋‰˜์—ˆ๋‹ค. 

 

1. Gateway์—์„œ ๋ชจ๋“  ์ธ์ฆ, ์ธ๊ฐ€ ์ฒ˜๋ฆฌ

 

2. ๊ฐ Micro Service ์—์„œ ์ธ์ฆ, ์ธ๊ฐ€ ์ฒ˜๋ฆฌ

 

 

 

 

์ด ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ• ์ค‘ ์–ด๋–ค๊ฑธ ์„ ํƒํ•ด์•ผ ํ•  ์ง€์— ๋Œ€ํ•ด ๋งŽ์€ ๊ณ ๋ฏผ์„ ํ–ˆ๋‹ค. ๊ฒฐ๋ก ๋ถ€ํ„ฐ ์–˜๊ธฐํ•˜๋ฉด ํ˜„์žฌ๋Š” Gateway์—์„œ ์ธ์ฆ ์ฒ˜๋ฆฌ, ๊ฐ Micro Service์—์„œ ์ธ๊ฐ€ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค.

 

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

 

 

 

 

 

 

 

 

 

 

 

2. Gateway์—์„œ ์ธ์ฆ, ์ธ๊ฐ€ ์ฒ˜๋ฆฌ

spring security ์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, spring api gateway๋„ ํ•„ํ„ฐ๊ฐ€ ๋งŽ์ด ํ™œ์šฉ๋œ๋‹ค. ์—ฌ๋Ÿฌ ํ•„ํ„ฐ๋“ค์„ ์„ ์–ธ ํ•ด๋‘๋ฉด, ํ•ด๋‹น ํ•„ํ„ฐ๋“ค์„ ๊ฑฐ์ณ์„œ ์‹ค์ œ ์„œ๋น„์Šค๋กœ ๋ผ์šฐํŒ…์ด ๋œ๋‹ค.

 

์—ฌ๋Ÿฌ Filter๋“ค์„ ๊ตฌํ˜„ํ•˜๊ณ  Bean์œผ๋กœ ๋“ฑ๋ก๋งŒ ํ•ด์ฃผ๋ฉด ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ˆœ์„œ ๋˜ํ•œ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

ํ•„ํ„ฐ๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๋ฐฉ์‹์€ ์ผ๋ฐ˜์ ์ธ ๋‹ค๋ฅธ ํ•„ํ„ฐ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค. ๋งŒ์•ฝ ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋งˆ์Œ๋Œ€๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค. 

 

 

 

Spring Cloud์—์„œ๋Š” ์ด๋Ÿฐ Filter๋“ค์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด AbstractGatewayFilterFactory ๋ผ๋Š” ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•ด์ค€๋‹ค. ์ด ํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›์•„ overriding์„ ํ†ตํ•ด JwtFilter๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

Gateway์—์„œ ์ธ์ฆ ์ฒ˜๋ฆฌ

@Slf4j
@Component
public class JwtAuthenticationFilter extends AbstractGatewayFilterFactory<JwtAuthenticationFilter.Config> {

    private final JwtTokenProvider jwtProvider;

    public JwtAuthenticationFilter(JwtTokenProvider jwtProvider) {
        super(Config.class);
        this.jwtProvider = jwtProvider;
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            String authorizationHeader = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
            if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                String token = authorizationHeader.substring(7);

                // ๋งŒ๋ฃŒ ์ฒดํฌ & ํ† ํฐ ๊ฒ€์ฆ
                if (jwtProvider.isExpiration(token)) {
                    log.info("access token ๋งŒ๋ฃŒ");
                    throw new DelegationTokenExpiredException("ํ† ํฐ ๋งŒ๋ฃŒ");
                }

                String loginId = jwtProvider.getLoginId(token);
                String role = jwtProvider.getRoles(token);

                // ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ํ—ค๋”์— ์ถ”๊ฐ€
                ServerHttpRequest modifiedRequest = exchange.getRequest().mutate()
                        .header("X-User-Id", loginId)
                        .header("X-User-Roles", role)
                        .build();

                // ์ƒˆ ์š”์ฒญ์„ ํฌํ•จํ•œ Exchange ์ƒ์„ฑ
                exchange = exchange.mutate().request(modifiedRequest).build();
            }
            return chain.filter(exchange);
        };
    }

    public static class Config {
    }
}

 

๊ธฐ์กด ๋ชจ๋†€๋กœ์‹ ์•„ํ‚คํ…์ฒ˜์—์„œ JWT๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ OncePerRequestFilter๋ฅผ ์ƒ์†๋ฐ›์•„ ๊ตฌํ˜„ํ•œ JwtFilter์™€ ๊ต‰์žฅํžˆ ์œ ์‚ฌํ•˜๋‹ค. 

 

ํ—ค๋”์— ํ† ํฐ์ด ์žˆ๋‹ค๋ฉด ๊ฒ€์ฆํ•˜๊ณ , ๋‹ค์Œ ํ•„ํ„ฐ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ๋‚˜๋Š” ๋‹ค๋ฅธ micro service์—์„œ ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด header์— ๊ฐ’์„ ์ถ”๊ฐ€๋กœ ๋‹ด์•„์คฌ๋‹ค. 

 

์ด๋ ‡๊ฒŒ ์„ค์ •ํ•œ Filter๋Š” application.yml ์—์„œ ์ ์šฉ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

- api gateway ์˜ application.yml

spring:
  application:
    name: apigateway
  cloud:
    gateway:
      routes:
        - id: todo-app
          uri: lb://TODO-APP
          predicates:
            - Path=/todo-app/**

        - id: temp-server
          uri: lb://TEMP-SERVER
          predicates:
            - Path=/temp-server/**

        - id: member-server
          uri: lb://MEMBER-SERVER
          predicates:
            - Path=/member-server/**

      default-filters:
        - JwtAuthenticationFilter # ๋ชจ๋“  ๋ผ์šฐํŠธ์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ ์šฉ

 

 

 

 

Gateway์—์„œ ์ธ๊ฐ€ ์ฒ˜๋ฆฌ

@Slf4j
@Component
public class JwtAuthenticationFilter extends AbstractGatewayFilterFactory<JwtAuthenticationFilter.Config> {

    private final JwtTokenProvider jwtProvider;

    public JwtAuthenticationFilter(JwtTokenProvider jwtProvider) {
        super(Config.class);
        this.jwtProvider = jwtProvider;
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            String authorizationHeader = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
            if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                String token = authorizationHeader.substring(7);

                // ๋งŒ๋ฃŒ ์ฒดํฌ
                if (jwtProvider.isExpiration(token)) {
                    log.info("access token ๋งŒ๋ฃŒ");
                    throw new DelegationTokenExpiredException("ํ† ํฐ ๋งŒ๋ฃŒ");
                }

                // ํ† ํฐ ๊ฒ€์ฆ
                String loginId = jwtProvider.getLoginId(token);
                String role = jwtProvider.getRoles(token);

				/* ์ถ”๊ฐ€ */
                // ๊ถŒํ•œ ์ฒดํฌ
                if (config.getRequiredRole() != null && !role.contains(config.getRequiredRole())) {
                    log.info("๊ถŒํ•œ ๋ถ€์กฑ: ํ•„์š”ํ•œ ์—ญํ•  = {}, ์‚ฌ์šฉ์ž์˜ ์—ญํ•  = {}", config.getRequiredRole(), role);
                    throw new ResponseStatusException(HttpStatus.FORBIDDEN, "ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.");
                }

                // ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ํ—ค๋”์— ์ถ”๊ฐ€
                ServerHttpRequest modifiedRequest = exchange.getRequest().mutate()
                        .header("X-User-Id", loginId)
                        .header("X-User-Roles", role)
                        .build();

                // ์ƒˆ ์š”์ฒญ์„ ํฌํ•จํ•œ Exchange ์ƒ์„ฑ
                exchange = exchange.mutate().request(modifiedRequest).build();
            }
            return chain.filter(exchange);
        };
    }

	/* ์ถ”๊ฐ€ */
    @Data
    public static class Config {
//         ํ•„ํ„ฐ ๊ตฌ์„ฑ์— ํ•„์š”ํ•œ ์„ค์ • ์ •๋ณด๋ฅผ ์ถ”๊ฐ€
        private String requiredRole;
    }
}

 

 

spring:
  cloud:
    gateway:
      routes:
        - id: todo-app
          uri: lb://TODO-APP
          predicates:
            - Path=/todo-app/**
          filters:
            - name: JwtAuthenticationFilter
              args:
                requiredRole: MEMBER

        - id: temp-server
          uri: lb://TEMP-SERVER
          predicates:
            - Path=/temp-server/**
          filters:
            - name: JwtAuthenticationFilter
              args:
                requiredRole: ADMIN

        - id: member-server
          uri: lb://MEMBER-SERVER
          predicates:
            - Path=/member-server/**
          filters:
            - name: JwtAuthenticationFilter
              args:
                requiredRole: MEMBER

 

Config ํด๋ž˜์Šค์—์„œ ํ•„ํ„ฐ์— ํ•„์š”ํ•œ ์„ค์ • ์ •๋ณด๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. application yml๋กœ ๋ถ€ํ„ฐ ์–ด๋–ค ๊ถŒํ•œ์ด ํ•„์š”ํ•œ์ง€ requiredRole ์ •๋ณด๋ฅผ ๋ฐ›๊ณ  ํ† ํฐ์˜ ๊ถŒํ•œ ์ •๋ณด์™€ ๋น„๊ตํ•˜์—ฌ ๊ถŒํ•œ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ์—ˆ๋‹ค. 

 

 

 

 

 

 

 

 

 

 

 

 

 

3. ๊ฐ Micro Service์—์„œ ์ธ์ฆ, ์ธ๊ฐ€ ์ฒ˜๋ฆฌ

๋‚œ Multi Module์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ณตํ†ต ๋ชจ๋“ˆ์„ ๋งŒ๋“ค์–ด ๊ฐ Micro Service์— ์ ์šฉ๋  Security ์„ค์ •์„ ํ•ด์ฃผ์—ˆ๋‹ค.

 

 

Common ๋ชจ๋“ˆ์—์„œ Security ๊ด€๋ จ ์„ค์ •

Security Context์— ์œ ์ € ์ •๋ณด๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— jwtFilter๋งŒ ํ•„ํ„ฐ๋กœ ๋“ฑ๋ก์‹œ์ผœ์ฃผ์—ˆ๋‹ค. 

 

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    private final JwtFilter jwtFilter;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable)
                .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-resources/**").permitAll()
                        .anyRequest().permitAll()
                )
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

 

 

@Slf4j
@Component
@RequiredArgsConstructor
public class JwtFilter extends OncePerRequestFilter {

    private final JwtTokenProvider jwtProvider;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        try {
            String authorizationHeader = request.getHeader("Authorization");
            String token;
            // ํ—ค๋”๊ฐ€ null ์ด ์•„๋‹ˆ๊ณ  ์˜ฌ๋ฐ”๋ฅธ ํ† ํฐ์ด๋ผ๋ฉด
            if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                // ํ† ํฐ ์ถ”์ถœ
                token = authorizationHeader.substring(7);
                // ๋งŒ๋ฃŒ ์ฒดํฌ
                if (jwtProvider.isExpiration(token)) {
                    log.info("access token ๋งŒ๋ฃŒ");
                    throw new DelegationTokenExpiredException("token ๋งŒ๋ฃŒ");
                }

                String loginId = jwtProvider.getLoginId(token);
                Role role = jwtProvider.getRoles(token);

                PrincipalDetails principalDetails = new PrincipalDetails(new MemberDto(loginId, role));

                // ์ธ์ฆ ์ •๋ณด ์ƒ์„ฑ
                Authentication authentication = new UsernamePasswordAuthenticationToken(principalDetails, null,
                        principalDetails.getAuthorities());

                // SecurityContextHolder์— ์ธ์ฆ ์ •๋ณด ์„ค์ •
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }

            filterChain.doFilter(request, response);
        } catch (Exception e) {
            // response ์„ธํŒ…
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=UTF-8"); // JSON ์‘๋‹ต์„ UTF-8๋กœ ์„ค์ •
            response.setContentType(APPLICATION_JSON_VALUE);

            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            response.getWriter()
                    .write(e.getMessage());
        }
    }
}

 

 

๊ถŒํ•œ ์„ค์ •์€ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ํ•  ์ƒ๊ฐ์ด๊ธฐ ๋•Œ๋ฌธ์— Security Config์—” ๋”ฐ๋กœ ๋„ฃ์ง€ ์•Š์•˜๋‹ค. 

 

์–ด๋…ธํ…Œ์ด์…˜ ๊ถŒํ•œ ์„ค์ •์€ ์—ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ 

 

 

 

 

์ธ์ฆ, ์ธ๊ฐ€๊ฐ€ ํ•„์š”ํ•œ ๋ชจ๋“ˆ์—์„œ Common ๋ชจ๋“ˆ ์˜์กด์„ฑ ์„ค์ •

dependencies {
    implementation project(':common')
}

 

 

 

 

 

 

 

 

 

 

 

4. ๊ฐ ๋ฐฉ๋ฒ•์˜ ์žฅ๋‹จ์ 

Gateway

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

 

๊ฐ Micro Service

  • ์žฅ์ 
    • ๊ฐ ์„œ๋น„์Šค๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ์ธ์ฆ, ์ธ๊ฐ€๋ฅผ ์ง„ํ–‰ํ•˜๋ฏ€๋กœ, ๊ฐœ๋ณ„ ์„œ๋น„์Šค์˜ ๊ถŒํ•œ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถฐ ์„ธ๋ถ€์ ์ธ ์ธ๊ฐ€ ์ •์ฑ…์„ ์„ธ์šธ ์ˆ˜ ์žˆ๋‹ค.
    • ์„œ๋น„์Šค ๊ฐ„ ๊ฒฐํ•ฉ๋„๋ฅผ ์ค„์—ฌ MSA์˜ ์žฅ์ ์„ ์‚ด๋ฆด ์ˆ˜ ์žˆ๋‹ค.
    • ์„ธ๋ถ€์ ์ธ ๊ถŒํ•œ ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๋‹จ์ 
    • ์ธ์ฆ, ์ธ๊ฐ€์— ํ•„์š”ํ•œ ํ•„ํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ํƒ€๊ฒŒ ๋œ๋‹ค. 
    • ๊ฐ ์„œ๋น„์Šค์— ๋”ฐ๋ผ ๋ณด์•ˆ ์ •์ฑ…์„ ์ผ๊ด€๋˜๊ฒŒ ๊ฐ€์ ธ๊ฐ€์ง€ ๋ชปํ•  ์ˆ˜๋„ ์žˆ๋‹ค. 
    • ์ธ์ฆ, ์ธ๊ฐ€ ์ฝ”๋“œ๊ฐ€ ์ค‘๋ณต๋œ๋‹ค. 

 

 

๋‘ ๋ฐฉ๋ฒ•์˜ ์žฅ๋‹จ์ ์„ ๋น„๊ตํ•ด๋ณด๋ฉด ์œ„์™€ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. 

 

 

 

 

 

 

 

 

 

 

 

 

5. ์ตœ์ข… ๊ฒฐ๋ก 

์ตœ์ข…์ ์œผ๋กœ ์ธ์ฆ(ํ† ํฐ ๊ฒ€์ฆ)์€ Gateway์—์„œ ํ•˜๊ณ , ์ธ๊ฐ€(๊ถŒํ•œ ์ œ์–ด)๋Š” ๊ฐ ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค์—์„œ ์ง„ํ–‰ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค. 

 

API Gateway์—์„œ ์ธ๊ฐ€๋ฅผ ์ง„ํ–‰ํ–ˆ์„ ๊ฒฝ์šฐ ๊ฐ€์žฅ ๋‹จ์ ์ด ์ธ๊ฐ€์— ๋Œ€ํ•œ ์„ค์ •์„ ์„ธ์„ธํ•˜๊ฒŒ ํ•  ์ˆ˜ ์—†๊ณ  ๊ฐœ๋ฐœ์„ ํ•˜๋Š” ์‚ฌ๋žŒ ์ž…์žฅ์—์„œ ๊ฐ€๋…์„ฑ ๋˜ํ•œ ์ข‹์ง€ ๋ชปํ•˜๋‹ค ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

URI ๊ทœ์น™์— ๋”ฐ๋ผ ๊ถŒํ•œ์„ ์„ค์ •ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์—ฌ๋Ÿฌ ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค์˜ API๋“ค์ด ์ ์ ˆํžˆ ๊ถŒํ•œ ์„ค์ •์ด ๋๋Š”์ง€ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•ด์„  ํ•˜๋‚˜ํ•˜๋‚˜ ๋น„๊ตํ•ด๋ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค. 

 

๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, service -> service์˜ ์š”์ฒญ์—์„  ๊ฒ€์ฆ์ด ๋˜์ง€ ์•Š์œผ๋‹ˆ ๋ณด์•ˆ์ ์œผ๋กœ๋„ ์ข‹์ง€ ๋ชปํ•˜๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. 

 

 

๋ฌผ๋ก  ๊ฐ ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค์—์„œ ์ธ์ฆ, ์ธ๊ฐ€ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋ฉด ์ค‘๋ณต๋œ ์ฝ”๋“œ, ์ค‘๋ณต ๊ฒ€์ฆ์œผ๋กœ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ๋„ ํ•œ๋‹ค. 

 

์ฝ”๋“œ ์ค‘๋ณต์€ ๊ณตํ†ต ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•˜๊ณ ,

 

์ค‘๋ณต ๊ฒ€์ฆ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” ์„ฑ๋Šฅ ์ €ํ•˜๋Š” ๋ฏธ๋ฏธํ•œ ์ˆ˜์ค€์ด๋ผ ํŒ๋‹จํ–ˆ๋‹ค. ๋งŒ์•ฝ ์ˆ˜์‹ญ๋ฒˆ์˜ ์ค‘๋ณต ๊ฒ€์ฆ์œผ๋กœ ์„ฑ๋Šฅ ์ €ํ•˜๊ฐ€ ์ผ์–ด๋‚œ๋‹ค๋ฉด ํ•ด๋‹น ์„œ๋น„์Šค๋Š” ์„ค๊ณ„๊ฐ€ ์ž˜๋ชป๋์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.