Home > Code Review > ๐Ÿ’ป[Code Review] WebConfig ํด๋ž˜์Šค ์ฝ”๋“œ ๋ฆฌ๋ทฐ.

๐Ÿ’ป[Code Review] WebConfig ํด๋ž˜์Šค ์ฝ”๋“œ ๋ฆฌ๋ทฐ.
Code review

๐Ÿ’ป[Code Review] WebConfig ํด๋ž˜์Šค ์ฝ”๋“œ ๋ฆฌ๋ทฐ.

1๏ธโƒฃ ์ „์ฒด ์ฝ”๋“œ.

import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Controller
public class WebConfig implements WebMvcConfigurer {

	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**") // ๋ชจ๋“  ๊ฒฝ๋กœ ํ—ˆ์šฉ
			.allowedOriginPatterns("http://localhost:*")
			.allowedMethods("GET", "POST", "PUT", "DELETE")
			.allowedHeaders("*")
			.allowCredentials(true) // ์ž๊ฒฉ ์ฆ๋ช… ํ—ˆ์šฉ
			.maxAge(3600);
	}
}
  • ์œ„ ์ฝ”๋“œ๋Š” Spring Framework์—์„œ CORS(Cross-Origin Resource Sharing) ์„ค์ •์„ ์ •์˜ํ•œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
  • WebMvcConfigurer ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ CORS ์ •์ฑ…์„ ๊ตฌ์„ฑํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ(์˜ˆ: ํ”„๋ก ํŠธ์—”๋“œ)์—์„œ ๋ฐฑ์—”ํŠธ API์— ์š”์ฒญํ•  ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” CORS ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

2๏ธโƒฃ CORS๋ž€? ๐Ÿค”

  • CORS(Cross-Origin Resource Sharing)๋Š” ๋ธŒ๋ผ์šฐ์ € ๋ณด์•ˆ ์ •์ฑ… ์ค‘ ํ•˜๋‚˜๋กœ, ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ž์‹ ๊ณผ ๋‹ค๋ฅธ ์ถœ์ฒ˜(origin)์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•  ๋•Œ ์ด๋ฅผ ํ—ˆ์šฉํ•˜๊ฑฐ๋‚˜ ์ œํ•œํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด:
      • ํด๋ผ์ด์–ธํŠธ๊ฐ€ http://localhost:3000์—์„œ ๋™์ž‘ํ•˜๊ณ , ์„œ๋ฒ„๊ฐ€ http://localhost:8080์—์„œ ๋™์ž‘ํ•˜๋ฉด ๋‘ ๋„๋ฉ”์ธ์€ ์„œ๋กœ ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.
      • ๋ธŒ๋ผ์šฐ์ €๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๋Ÿฐ ๊ต์ฐจ ์ถœ์ฒ˜ ์š”์ฒญ์„ ์ฐจ๋‹จํ•˜๋ฏ€๋กœ, ์„œ๋ฒ„์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ด๋ฅผ ํ—ˆ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

3๏ธโƒฃ ์ฝ”๋“œ ๋ถ„์„.

1๏ธโƒฃ ํด๋ž˜์Šค ์„ ์–ธ.

@Controller
public class WebConfig implements WebMvcConfigurer {...}
  • WebMvcConfigurer๋Š” Spring MVC ์„ค์ •์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•˜๊ธฐ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค.
  • WebConfig ํด๋ž˜์Šค๋Š” WebMvcConfigurer๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ Spring MVC ์„ค์ •์„ ์‚ฌ์šฉ์ž ์ •์˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ addCorsMappings ๋ฉ”์„œ๋“œ.

@Override
public void addCorsMappings(CorsRegistry registry) {...}
  • Spring MVC์—์„œ CORS ๋งคํ•‘์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด CorsRegistry๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์ด ๋ฉ”์„œ๋“œ๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ ํŠน์ • ๊ฒฝ๋กœ๋กœ์˜ ์š”์ฒญ์„ ํ—ˆ์šฉํ•˜๊ฑฐ๋‚˜ ์ œํ•œํ•˜๋Š” ๊ทœ์น™์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

3๏ธโƒฃ CORS ์„ค์ •.

registry.addMapping("/**") // ๋ชจ๋“  ๊ฒฝ๋กœ ํ—ˆ์šฉ
        .allowedOriginPatterns("http://localhost:*") // localhost์˜ ๋ชจ๋“  ํฌํŠธ ํ—ˆ์šฉ
        .allowedMethods("GET", "POST", "PUT", "DELETE") // ํ—ˆ์šฉํ•  HTTP ๋ฉ”์„œ๋“œ
        .allowedHeaders("*") // ๋ชจ๋“  ํ—ค๋” ํ—ˆ์šฉ
        .alloweCredentials(true) // ์ฟ ํ‚ค์™€ ๊ฐ™์€ ์ž๊ฒฉ ์ฆ๋ช… ํ—ˆ์šฉ
        .maxAge(3600) // ์บ์‹œ ์‹œ๊ฐ„ (์ดˆ ๋‹จ์œ„)
  • addMapping("/**")
    • ๋ชจ๋“  URL ํŒจํ„ด(/**)์— ๋Œ€ํ•ด CORS ์ •์ฑ…์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • ์˜ˆ: /api/*, /resources/* ๋“ฑ ๋ชจ๋“  ๊ฒฝ๋กœ ํ—ˆ์šฉ.
  • allowedOriginPatterns("http://localhost:*)"
    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ http://localhost์—์„œ ์‹œ์ž‘๋˜๋Š” ๋ชจ๋“  ํฌํŠธ(์˜ˆ: http://localhost:3000, http://localhost:8080)์— ๋Œ€ํ•ด ์š”์ฒญ์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • Spring Boot 2.4+์—์„œ๋Š” allowedOrigin ๋Œ€์‹  allowedOriginPatterns ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
  • allowedMethods("GET", "POST", "PUT", "DELETE")
    • ํ—ˆ์šฉํ•  HTTP ๋ฉ”์„œ๋“œ(GET, POST, PUT, DELETE)๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, OPTIONS์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋Š” ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • allowedHeaders("*")
    • ๋ชจ๋“  ์š”์ฒญ์˜ ํ—ค๋”๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • ์˜ˆ: Content-Type, Authorization ๋“ฑ์ด ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • allowCredentials(true)
    • ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•œ ์š”์ฒญ์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • ์˜ˆ: ์ธ์ฆ์ด ํ•„์š”ํ•œ ์š”์ฒญ์—์„œ ์ฟ ํ‚ค๋ฅผ ํ†ตํ•ด ์„ธ์…˜ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • maxAge(3600)
    • ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ(OPTIONS ์š”์ฒญ)์˜ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹ฑํ•˜๋Š” ์‹œ๊ฐ„์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
    • ์—ฌ๊ธฐ์„œ๋Š” 3600์ดˆ(1์‹œ๊ฐ„) ๋™์•ˆ ์บ์‹ฑํ•ฉ๋‹ˆ๋‹ค.

4๏ธโƒฃ ์‚ฌ์šฉ ์‚ฌ๋ก€.

  • 1. ํ”„๋ก ํŠธ์—”๋“œ-๋ฐฑ์—”๋“œ ๋ถ„๋ฆฌ๋œ ํ™˜๊ฒฝ.
    • ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๋™์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ:
      • ํ”„๋ก ํŠธ์—”๋“œ: http://localhost:3000
      • ๋ฐฑ์—”๋“œ: http:// localhost:8080
        • ์ด ๊ฒฝ์šฐ, ๋ธŒ๋ผ์šฐ์ €๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ต์ฐจ ์ถœ์ฒ˜ ์š”์ฒญ์„ ์ฐจ๋‹จํ•˜๋ฏ€๋กœ ์œ„์™€ ๊ฐ™์ด CORS ์„ค์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

5๏ธโƒฃ ์ฃผ์˜์‚ฌํ•ญ.

  • ๋ณด์•ˆ ๊ณ ๋ ค
    • ์‹ค์ œ ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ๋Š” allowedOriginPatterns์— ์™€์ผ๋“œ์นด๋“œ("*")๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ณ , ํŠน์ • ์ถœ์ฒ˜๋งŒ ํ—ˆ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์˜ˆ: .allowedOriginPatterns("https://example.com)"
  • allowCredentials์™€ *์˜ ์ถฉ๋Œ
    • allowCredentials(true)์™€ allowedOriginPatterns("*")๋Š” ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
    • ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•œ ์š”์ฒญ์„ ํ—ˆ์šฉํ•˜๋ ค๋ฉด ํŠน์ • ์ถœ์ฒ˜๋ฅผ ๋ช…์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.