๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŒท Spring/๊ฐœ๋…

[Spring] CORS์™€ SOP์˜ ์˜๋ฏธ, @CrossOrigin์™€ WebMvcConfigurer ์ฝ”๋“œ ์˜ˆ์‹œ

by ._.sori 2025. 8. 19.

 

 

 

ํ”„๋ก ํŠธ์™€ ๋ฐฑ์—”๋“œ๋ฅผ
๋”ฐ๋กœ ์ž‘์„ฑํ•  ๋•Œ,
@CrossOrigin์„ ๋ถ™์˜€๋‹ค.

 

 

 

 

@CrossOrigin

  • CORS๋ฅผ ์Šคํ”„๋ง์„ ํ†ตํ•ด ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
  • ๋ชจ๋“  ๋„๋ฉ”์ธ๊ณผ ๋ชจ๋“  ์š”์ฒญ๋ฐฉ์‹์— ๋Œ€ํ•ด ํ•˜์šฉํ•œ๋‹ค๋Š” ์˜๋ฏธ๋ฅผ ๊ฐ€์ง„๋‹ค.
  • ์Šคํ”„๋ง 4.2๋ถ€ํ„ฐ ์ง€์›ํ•œ๋‹ค.

 

 

CORS

  • ์„œ๋กœ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ณต์œ ํ•˜๋Š” ๋ฐฉ์‹
  • ์›น ํŽ˜์ด์ง€์˜ ์ œํ•œ๋œ ์ž์›์„ ์™ธ๋ถ€ ๋„๋ฉ”์ธ์—์„œ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•ด์ฃผ๋Š” ๋งค์ปค๋‹ˆ์ฆ˜
  • ์ฒ˜์Œ ์ „์†ก๋˜๋Š” ๋ฆฌ์†Œ์Šค์˜ ๋„๋ฉ”์ธ๊ณผ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์œผ๋กœ๋ถ€ํ„ฐ ๋ฆฌ์†Œ์Šค๊ฐ€ ์š”์ฒญ๋  ๊ฒฝ์šฐ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค๋Š” cross-origin HTTP ์š”์ฒญํ•œ๋‹ค.
  • Same Origin Policy์™€ ๋ฐ˜๋Œ€๋˜๋Š” ๊ฐœ๋…
  • ์˜ˆ์‹œ๋กœ, ๋‹ค๋ฅธ ์ง‘์—์„œ ๋‚ด ์ง‘์— ์žˆ๋Š” ๊ธˆ๊ณ (๋ฐ์ดํ„ฐ)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง‘์ฃผ์ธ(์„œ๋ฒ„)์ด ํ—ˆ๊ฐ€์ฆ(ํŠน์ • ์‘๋‹ต ํ—ค๋”)์„ ์จ์ฃผ๋ฉด ๊ฐ€๋Šฅํ•˜๋‹ค.

 

 

 

SOP

  • Same Origin Policy์˜ ์•ฝ์ž์ด๋ฉฐ ๋™์ผํ•œ ์ถœ์ฒ˜์˜ Origin๋งŒ ๋ฆฌ์†Œ์Šค(๋ฐ์ดํ„ฐ)๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋งŒ์•ฝ ๋™์ผํ•œ ์ถœ์ฒ˜๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด OPTIONS๋ฅผ ์ด์šฉํ•œ Preflight๋ฅผ ์ด์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ๊ฒ€์ฆ์„ ๊ฑฐ์นœ๋‹ค.
  • ์˜ˆ์‹œ๋กœ, ์šฐ๋ฆฌ ์ง‘(์˜ค๋ฆฌ์ง„)์— ๋“ค์–ด์™€์•ผ ์ง‘์— ์žˆ๋Š” ๊ธˆ๊ณ (๋ฐ์ดํ„ฐ)๋ฅผ ์—ด ์ˆ˜ ์žˆ๋‹ค.

 

 

 


 

 

 

 

@CrossOrigin ์ฝ”๋“œ ์˜ˆ์‹œ

vue์ฝ”๋“œ

const res = await axios.post("http://localhost:8080/api/register", {
          name: this.name,
          userId: this.userId,
          pwd: this.pwd,
          pwdConfirm: this.pwdConfirm,
          tel: this.tel,
          birth: this.birth,
          email: this.email,
        });
spring ์ฝ”๋“œ - ํด๋ž˜์Šค ๋‹จ์œ„

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:5173")
public class RegisterController {

...

}
spring ์ฝ”๋“œ - ๋ฉ”์„œ๋“œ ๋‹จ์œ„

    @CrossOrigin(origins = "http://localhost:5173")
    @PostMapping("/register")
    public ResponseEntity<String> register(@RequestBody RegisterRequest request) {
    
    ...
  
    }
ํ”„๋ก ํŠธ๋Š” http://localhost:5173๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ๋ฐฑ์—”๋“œ๋Š” http://localhost:8080๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ ํฌํŠธ๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋กœ ๋‹ค๋ฅธ ์˜ค๋ฆฌ์ง„์œผ๋กœ ๊ฐ„์ฃผ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฅผ ์˜ˆ์™ธ์ ์œผ๋กœ ํ—ˆ์šฉํ•˜๊ธฐ ์œ„ํ•ด CORS๋ฅผ ์“ด๋‹ค. @CrossOrigin์€ SpringMVC์—์„œ CORS ํ—ˆ์šฉ ํ—ค๋”๋ฅผ ์ž๋™์œผ๋กœ ๋‹ฌ์•„์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ์•„์ฃผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ˜„์žฌ ์ฝ”๋“œ์—์„œ๋Š” ํด๋ž˜์Šค์— @CrossOrigin์„ ๋ถ™์˜€๋‹ค. ์ด๋ ‡๊ฒŒ ํ•ด๋„ ๋˜์ง€๋งŒ, ๋ฉ”์„œ๋“œ ๋‹จ์œ„๋กœ ์ ์šฉ์‹œํ‚ฌ์ˆ˜๋„ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ   exposedHeaders, allowCredentials ๋“ฑ ๋‹ค์–‘ํ•œ ์†์„ฑ์ด ์žˆ์–ด์„œ ๋” ๊ตฌ์ฒด์ ์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

 


 

 

 

 

๋‹ค๋ฅธ๋ฐฉ๋ฒ•_ WebMvcConfigurer ์ฝ”๋“œ ์˜ˆ์‹œ

@Configuration
public class CorsConfig implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/api/**")
        // ํ—ˆ์šฉํ•  ์˜ค๋ฆฌ์ง„ ๋ชฉ๋ก
        .allowedOrigins("http://localhost:5173")
        // ํ—ˆ์šฉํ•  HTTP ๋ฉ”์„œ๋“œ
        .allowedMethods("GET","POST","PUT","DELETE","OPTIONS")
        // ์š”์ฒญ ํ—ค๋” ํ—ˆ์šฉ
        .allowedHeaders("*")
        // ํ”„๋ŸฐํŠธ์—์„œ ์ฝ์„ ์ˆ˜ ์žˆ๊ฒŒ ๋…ธ์ถœํ•  ์‘๋‹ต ํ—ค๋”
        .exposedHeaders("Location")
        // ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ์ฟ ํ‚ค/์„ธ์„  ์ „์†ก ํ—ˆ์šฉ
        .allowCredentials(true)  
        // Preflight(OPTIONS) ๊ฒฐ๊ณผ ์บ์‹œ
        .maxAge(3600);
  }
}
์ถœ์ฒ˜ - https://wonit.tistory.com/572

// ์Šคํ”„๋ง ๋ถ€ํŠธ ์•ฑ์˜ ์‹œ์ž‘์ 
@SpringBootApplication
public class RestServiceCorsApplication {

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

    // ๋นˆ ๋“ฑ๋ก
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            // ์ „์—ญ CORS ์ถ”๊ฐ€
            public void addCorsMappings(CorsRegistry registry) {
                // ๋ชจ๋“  ์—”ํŠธํฌ์ธํŠธ์— ๋Œ€ํ•ด CORS ์ ์šฉ, fornt-server์—์„œ ์˜ค๋Š” ์š”์ฒญ๋งŒ ํ—ˆ์šฉ
                registry.addMapping("/**").allowedOrigins("http://front-server.com");
            }
        };
    }

}
@CrossOrigin์€ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ปจํŠธ๋กค๋Ÿฌ์˜ ์ˆ˜๊ฐ€ ๋งŽ๊ณ  ๊ทธ ์•ˆ์— ์†์„ฑ๋„ ๋งŽ๋‹ค๋ฉด ๋งค๋ฒˆ ์ ์–ด์•ผํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ๊ฒฝ์šฐ๋Š” ์ „์—ญ์ ์œผ๋กœ ์„ค์ •ํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค. ์•„๋งˆ ์‹ค์ œ ์„œ๋ฒ„๋ฅผ ์šด์˜ํ•œ๋‹ค๋ฉด ์ „์—ญ์ ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๋ฐฉ์‹์ด ๋” ๋งž์ง€ ์•Š์„๊นŒ ์‹ถ๋‹ค.

์ฒซ๋ฒˆ์งธ ์ฝ”๋“œ๋Š” ์•„์˜ˆ CORS์˜ ์ „์—ญ ์„ค์ •์„ ์œ„ํ•œ ํด๋ž˜์Šค๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์—ˆ๋‹ค. ์—ฌ๋Ÿฌ ์†์„ฑ์„ ํฌํ•จ์‹œ์ผœ ๋ฉ”์„œ๋“œ, ํ—ค๋”, ์ฟ ํ‚ค ๋“ฑ์„ ์ง€์ •ํ•˜์—ฌ ๊ฐ’์„ ์„ธํŒ…ํ•ด์คฌ๋‹ค. ๋‘๋ฒˆ์งธ ์ฝ”๋“œ๋Š” main ํ•จ์ˆ˜์— Bean์œผ๋กœ Configurer๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค. ์†์„ฑ์„ ๋”ฐ๋กœ ์„ค์ •ํ•˜์ง€ ์•Š์•„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์„ธํŒ…๋œ๋‹ค.

 

 

 

 


 

 

 

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

 

๐Ÿชฝ

ํ‹€๋ฆฐ ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์„ธ์š”

 

 


 

- CrossOrigin

 

REST API CrossOrigin Annotation ๊ฐ„๋‹จ ์ •๋ฆฌ

Front์™€ Back ์œผ๋กœ ๋‚˜๋ˆ ์„œ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ ํ•˜๋Š” ์ˆ˜์—…์„ ํ•˜์˜€๋‹ค. ๊ทผ๋ฐ ๋ง์ž…๋‹ˆ๋‹ค? ์ฝ”๋“œ๊ฐ€ ํ‹€๋ฆฐ ๊ณณ์ด ์—†๋Š”๋ฐ ์ž๊พธ ์—๋Ÿฌ๊ฐ€ ๋œจ๋Š”๊ฑฐ์—์š”? ์ž๊พธ CORS๊ฐ€ ์–ด์ฉŒ๊ณ  ์ €์ฉŒ๊ณ , CrossOrigin์ด ์–ด์ฉŒ๊ณ  ์ €์ฉŒ๊ณ  ์ด๋Ÿฐ ๋ง์ด ๊ฐœ๋ฐœ

henniee.tistory.com

 

 

 

- CORS

 

[Spring Boot] CORS ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” 3๊ฐ€์ง€ ๋ฐฉ๋ฒ• (Filter, @CrossOrigin, WebMvcConfigurer)

Server Side Template ๋ฐฉ์‹์ด ์•„๋‹Œ Front์™€ Back ์œผ๋กœ ๋‚˜๋ˆ ์„œ ์ธํ”„๋ผ๋ฅผ ๊ตฌ์„ฑํ•ด๋ณธ ๊ฒฝํ—˜์ด ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ๋Š” Cors๊ฐ€ ๋งค์šฐ ์นœ์ˆ™ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ˜„์žฌ ๊ฐœ๋ฐœ ํ๋ฆ„์—์„œ ์›น ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค๊ฐ€ Cors ๋ฅผ ๋งŒ๋‚  ํ™•๋ฅ ์€

wonit.tistory.com

 

 

 

- Preflight

 

[HTTP] OPTIONS ํ—ค๋”์™€ Preflight ๊ทธ๋ฆฌ๊ณ  CORS

OPTIONS ๋Š” RFC 7231 ์— ๋ช…์‹œ๋œ HTTP์˜ ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. OPTIONS ๋Š” ์‹ค์ œ๋กœ ์šฐ๋ฆฌ๊ฐ€ ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ง์ ‘ ์‚ฌ์šฉํ•  ์ผ์€ ๋“œ๋ฌผ์ง€๋งŒ ํ˜„๋Œ€์˜ Front Back ์„ ๋‚˜๋ˆ„๋Š” ๊ฐœ๋ฐœ ํ๋ฆ„์—์„œ

wonit.tistory.com