์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

[์€ผ] ์•„ ๊ทธ๋ž˜์„œ CORS๊ฐ€ ๋ญ์—์š” : ๊ฐœ๋… + ์„ค์ •์˜ˆ์‹œ

CS/๋„คํŠธ์›Œํฌ๐Ÿ•Š

by :ํ•ดํ”ผ๋ž˜๋น—๐Ÿพ 2025. 2. 14. 11:49

๋ณธ๋ฌธ

(๊ฐœ๋…๊ณผ ๋™์ž‘ ์›๋ฆฌ๋ฅผ ์ •ํ™•ํžˆ ๋ชฐ๋ผ์„œ) ์ˆ˜๋งŽ์€ ์–ต๊นŒ๋ฅผ ๋‹นํ–ˆ๊ณ 
๊ตฌ๊ธ€๋ง์œผ๋กœ Mdn ๋ฌธ์„œ๋ฅผ ์ฐพ์•„ ์ดํ•ดํ•œ ํ›„ ํ•ด๊ฒฐํ•จ (์—ญ์‹œ ์ •์‹๋Œ€๋กœ ๊ฐ€์•ผ ํ•จ)
๋ฐœ๊ฒฌํ–ˆ๋˜ cors ํ•ต์‹ฌ ๊ฐœ๋…์„ ์ ์–ด๋ณด๊ณ ์ž ํ•œ๋‹ค

 

CORS

CORS๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ž์‹ ์˜ ์ถœ์ฒ˜๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์–ด๋–ค ์ถœ์ฒ˜๋กœ๋ถ€ํ„ฐ ์ž์›์„ ๋กœ๋”ฉํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜๋„๋ก ์„œ๋ฒ„๊ฐ€ ํ—ˆ๊ฐ€ ํ•ด์ฃผ๋Š” HTTP ํ—ค๋” ๊ธฐ๋ฐ˜ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค. 

 

 

CORS๊ฐ€ ๋™์ž‘ํ•˜๋Š” ์„ธ๊ฐ€์ง€ ์‹œ๋‚˜๋ฆฌ์˜ค 

1. Simple Request

Preflight Request ์š”์ฒญ์—†์ด ์„œ๋ฒ„์— ์งํ–‰์œผ๋กœ ๋ณธ ์š”์ฒญ์„ ๋ณด๋‚ธ ํ›„, ์„œ๋ฒ„๊ฐ€ ์ด์— ๋Œ€ํ•œ ์‘๋‹ต์˜ ํ—ค๋”์— Access-Control-Allow-Origin ํ—ค๋”๋ฅผ ๋ณด๋‚ด์ฃผ๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ CORS ์ •์ฑ… ์œ„๋ฐ˜ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์‚ฌํ•œ๋‹ค. 

1) ์š”์ฒญ์˜ ๋ฉ”์†Œ๋“œ๋Š” GET, HEAD, POST ์ค‘ ํ•˜๋‚˜๋‹ค 

2) Accept, Accept--Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width ํ—ค๋”์ผ ๊ฒฝ์šฐ์—๋งŒ ์ ์šฉ๋œ๋‹ค

3) Content-Type ํ—ค๋”๊ฐ€ applicaiton/x-www-form-urlencoded, multipart/form-data, text/plain ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค. ์•„๋‹ ๊ฒฝ์šฐ ์˜ˆ๋น„ ์š”์ฒญ์œผ๋กœ ๋™์ž‘๋œ๋‹ค 

4) ์š”์ฒญ์— ReadableStream ๊ฐ์ฒด๊ฐ€ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค 

 

๋ธŒ๋ผ์šฐ์ € => ์„œ๋ฒ„ 
Origin : A 
์„œ๋ฒ„ => ๋ธŒ๋ผ์šฐ์ €
Access-Control-Allow-Origin : * 

 

 

2. Preflight Request

๋ธŒ๋ผ์šฐ์ €๋Š” ์„œ๋ฒ„์— ์˜ˆ๋น„ ์š”์ฒญ์„ ๋ณด๋‚ด ์ž˜ ํ†ต์‹ ๋˜๋Š”์ง€ ํ™•์ธํ•œ ํ›„ ๋ณธ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค 

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์„œ๋ฒ„์— ์˜ˆ๋น„ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์„ Preflight๋ผ๊ณ  ๋ถ€๋ฅด๋ฉฐ, ์ด ์˜ˆ๋น„ ์š”์ฒญ์˜ HTTP ๋ฉ”์†Œ๋“œ๋Š” OPTIONS ๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค. 

 

>> Access-Control-Max-Age ํ—ค๋”์— ์บ์‹œ๋  ์‹œ๊ฐ„์„ ๋ช…์‹œํ•˜์—ฌ Preflight ์š”์ฒญ์„ ์บ์‹ฑํ•˜์—ฌ ์ตœ์ ํ™”๋ฅผ ์‹œ์ผœ์ค„ ์ˆ˜ ์žˆ๋‹ค 

 

3. Credentialed Request (์ž๊ฒฉ ์ฆ๋ช…์„ ํฌํ•จํ•œ ์š”์ฒญ)

ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„์—๊ฒŒ ์ž๊ฒฉ ์ธ์ฆ ์ •๋ณด(Credential)์„ ์‹ค์–ด ์š”์ฒญํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ์š”์ฒญ์ด๋‹ค

 

same-origin : ๊ฐ™์€ ์ถœ์ฒ˜ ๊ฐ„ ์š”์ฒญ์—๋งŒ ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค

include : ๋ชจ๋“  ์š”์ฒญ์— ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค 

omit : ๋ชจ๋“  ์š”์ฒญ์— ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด์ง€ ์•Š๋Š”๋‹ค 

 

Access-Control-Allow-Credentials๋ฅผ true๋กœ ์„ค์ •ํ•˜๊ฒŒ ๋˜๋ฉด, 

Access-Control-Allow-Origin 

Access-Control-Allow-Methods 

Access-Control-Allow-Headers ๊ฐ’์— * ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค 

 

 

 

[๋ฌธ์„œ] CORS ๊ฐœ๋…๊ณผ ์ ‘๊ทผ ์ œ์–ด ์‹œ๋‚˜๋ฆฌ์˜ค 

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS

 

๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ  (CORS) - HTTP | MDN

๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ (Cross-Origin Resource Sharing, CORS)๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ž์‹ ์˜ ์ถœ์ฒ˜๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์–ด๋–ค ์ถœ์ฒ˜(๋„๋ฉ”์ธ, ์Šคํ‚ด ํ˜น์€ ํฌํŠธ)๋กœ๋ถ€ํ„ฐ ์ž์›์„ ๋กœ๋”ฉํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜๋„๋ก ์„œ๋ฒ„๊ฐ€ ํ—ˆ๊ฐ€ ํ•ด์ฃผ๋Š” HTTP

developer.mozilla.org

 

 


CORS ๊ด€๋ จ ํ—ค๋” 

 

Access-Control-Allow-Origin : ์„œ๋ฒ„๊ฐ€ ํ—ˆ์šฉํ•˜๋Š” ์ถœ์ฒ˜(origin)์„ ์ •์˜ํ•œ๋‹ค 

Access-Control-Allow-Methods : ์„œ๋ฒ„๊ฐ€ ํ—ˆ์šฉํ•˜๋Š” HTTP ๋ฉ”์†Œ๋“œ๋ฅผ ์ •์˜ํ•œ๋‹ค (GET, POST, PUT ๋“ฑ)

Access-Control-Allow-Headers : ์„œ๋ฒ„๊ฐ€ ํ—ˆ์šฉํ•˜๋Š” ์š”์ฒญ ํ—ค๋”๋ฅผ ์ •์˜ํ•œ๋‹ค (Authorization, Content-Type)

Access-Control-Allow-Credentials : cross-origin์—๊ฒŒ ์ž๊ฒฉ ์ฆ๋ช…(์ฟ ํ‚ค, ์ธ์ฆ ํ—ค๋” ๋“ฑ)์„ ํฌํ•จํ•˜๋Š” ์š”์ฒญ์„ ํ—ˆ์šฉํ• ์ง€ ์„ค์ •ํ•œ๋‹ค 

 

 

Access-Control-Expose-Headers : ์‘๋‹ต์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ถ”๊ฐ€์ ์ธ ํ—ค๋”๋ฅผ ์ •์˜ํ•œ๋‹ค 

Access-Control-Max-Age : ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์˜ ์บ์‹œ ์‹œ๊ฐ„์„ ์„ค์ •ํ•œ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋Š” ์ด ์‹œ๊ฐ„ ๋™์•ˆ ๋™์ผํ•œ CORS ์š”์ฒญ์— ๋Œ€ํ•ด ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ๋ณด๋‚ด์ง€ ์•Š๋Š”๋‹ค

 

 

Access-Control-Expose-Headers ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ

๊ธฐ๋ณธ์ ์œผ๋กœ CORS-safelisted ์‘๋‹ต ํ—ค๋”(Cache-Control, Content-Type, ... )๋งŒ ๋…ธ์ถœ๋œ๋‹ค 

 

[๋ฌธ์„œ] Access-Control-Expose-Headers

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

 

Access-Control-Expose-Headers - HTTP | MDN

The HTTP Access-Control-Expose-Headers response header allows a server to indicate which response headers should be made available to scripts running in the browser in response to a cross-origin request.

developer.mozilla.org

[๋ฌธ์„œ] CORS-safelisted ์‘๋‹ต ํ—ค๋”

https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header

 

CORS-safelisted response header - MDN Web Docs Glossary: Definitions of Web-related terms | MDN

A CORS-safelisted response header (also known as "simple response header") is an HTTP header in a CORS response that it is considered safe to expose to client scripts. Only safelisted response headers are made available to web pages.

developer.mozilla.org

 

 

Access-Control-Allow-Credentials ์™€ Request.credentials

Access-Control-Allow-Credentials : true ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์œผ๋ฉด, credentials : include๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค

 

[๋ฌธ์„œ] Access-Control-Allow-Credentials

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials

 

Access-Control-Allow-Credentials - HTTP | MDN

The HTTP Access-Control-Allow-Credentials response header tells browsers whether the server allows credentials to be included in cross-origin HTTP requests.

developer.mozilla.org


CORS ๊ด€๋ จ ์—๋Ÿฌ

Reason: CORS header 'Access-Control-Allow-Origin' does not match 'xyz'

Access-Control-Allow-Origin 'xyz' ์ถ”๊ฐ€ 

 

Reason: Credential is not supported if the CORS header 'Access-Control-Allow-Origin' is '*'

๋™์‹œ ์„ค์ • ๋ถˆ๊ฐ€ 

 

Reason: expected 'true' in CORS header 'Access-Control-Allow-Credentials'

Access-Control-Allow-Credentials true ์„ค์ •

 

Reason: invalid token 'xyz' in CORS header 'Access-Control-Allow-Headers'

preflight ์š”์ฒญ์œผ๋กœ Access-Control-Allow-Headers ํ—ค๋”๊ฐ€ ์„œ๋ฒ„์˜ ์‘๋‹ต์œผ๋กœ ์ œ๊ณต๋œ๋‹ค. ์ด๋•Œ, ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฐ’์ด Access-Controll-Allow-Headers์— ํฌํ•จ๋˜๋ฉด ํ•ด๋‹น ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค 

 


>> Preflight ์š”์ฒญ, ์™€์ผ๋“œ ์นด๋“œ ์‚ฌ์šฉ ๋ถˆ๊ฐ€ ๋‚ด์šฉ์„ ๋ชฐ๋ผ ๊ณ ์ƒ์„ ํ–ˆ์—ˆ๋‹ค 

 

Nginx ์„ค์ • ์˜ˆ์‹œ

location / {
    if ($request_method = 'OPTIONS') { // preflight ์š”์ฒญ ์ฒ˜๋ฆฌ 
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain';
        return 204;
    }

    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
}

 

Spring Boot ์„ค์ • ์˜ˆ์‹œ

@Configuration
@EnableWebMvc
public class WebMvcConfiguration implements WebMvcConfigurer {
	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**")
			.allowedOriginPatterns("https://www.vvue.site", "http://localhost:3000") // Development environment
			.exposedHeaders("Authorization", "refresh-token")
			.allowCredentials(true); // true๋กœ ์„ค์ •ํ–ˆ์œผ๋ฏ€๋กœ origin, method, headers ๋ฅผ * ๋กœ ์„ค์ • ๋ชปํ•จ
	}
}

 

 

allowedMethods๋ฅผ ์„ค์ • ์•ˆํ•˜๋ฉด GET, HEAD ๋งŒ ํ—ˆ์šฉ๋œ๋‹ค 

728x90

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ