[CORS] CORS 요청의 종류와 CURL로 CORS 간단 테스트하기

peace w·2026년 1월 27일

서버 옮기면서 CORS 에러가 또 발생했다..
https://velog.io/@peace_e/Spring-boot-CORS-해결하기
↑ 이전에 스프링부트 수정하여 해결했던 건은 여기 참고


CORS 요청의 종류와 테스트 방법에 대해 정리하고자 한다.

CORS 요청의 종류

1. Simple Request (단순 요청)

다음 조건을 모두 만족하면 preflight 없이 바로 실제 요청을 보낸다

메서드: GET, POST, HEAD 중 하나
헤더: Accept, Accept-Language, Content-Language, Content-Type 등 기본 헤더만
Content-Type: application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나

2. Preflight Request (사전 요청)

단순 요청에 해당하지 않으면 Preflight(OPTIONS) 요청을 먼저 보낸다.

메서드: PUT, DELETE, PATCH
커스텀 헤더: Authorization, X-Custom-Header
Content-Type: application/json

예비 요청으로 OPTIONS 메서드를 보내서 이 요청이 안전한지 판단한 후, 단순 요청을 요청한다.

Access-Control-Allow / Access-Control-Request 헤더

1. Access-Control-Allow-* 헤더

  • 서버가 응답할 때 포함하는 헤더
  • 모든 CORS 요청의 응답에 포함되어야 함

Simple Request(단순 요청)의 응답 ✅
Preflight Request(OPTIONS)의 응답 ✅
Preflight 이후 실제 요청의 응답 ✅

2. Access-Control-Request-* 헤더

  • 브라우저(클라이언트)가 요청할 때 포함하는 헤더

Preflight Request(OPTIONS)에만 포함됨 ✅
실제 요청(POST, GET 등)에는 포함 안 됨 ❌

CURL 명령어로 테스트하기

curl -i

curl -i "https://URL..." \
  -H "Content-Type: application/json" \
  -H "Origin: http://localhost:3000" \

CURL 요청은 메서드 지정하지 않을 시, 기본적으로 GET 요청이다.

※ 단, -d (또는 --data) 옵션을 사용하면 자동으로 POST 요청이 된다. 아래 두 요청은 동일한 POST 요청이다.

curl -i -X POST

curl -i "https://URL..." \
  -H "Content-Type: application/json" \
  -H "Origin: http://localhost:3000" \
  -d '{"test":"test1234"}'
  
curl -i -X POST "https://URL..." \
  -H "Content-Type: application/json" \
  -H "Origin: http://localhost:3000" \
  -d '{"test":"test1234"}'

curl -i -X OPTIONS

Preflight 요청을 테스트하고 싶다면 OPTIONS 메서드를 써야한다.

curl -i -X OPTIONS "https://144.24.86.170.nip.io/api/user/login" \
  -H "Origin: http://localhost:3000" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: content-type"

응답반환

성공적이라면 이런 응답을 받게 될 것이다.

HTTP/2 200
access-control-allow-credentials: true
access-control-allow-origin: http://localhost:3000
Date: Tue, 27 Jan 2026 15:01:02 GMT
...

여기서 Date의 경우 HTTP 프로토콜 표준(RFC 7231)에 따라서, Date 헤더는 반드시 GMT(UTC) 형식으로 표시된다. 이는 서버의 타임존 설정과 무관하다.


내가 겪은 상황

  • CURL로 테스트했을 때, response 가 호출되고 있어서 정상적으로 되는 줄 알았다.
  • 그러나 OPTIONS 요청에는 Access-Control-Allow-Origin 헤더http://localhost:3000이 있었지만
  • POST 요청에는 Access-Control-Allow-Origin 헤더가 없었다.

해결방법

  • setAllowedOrigins 대신 SetAllowedOriginPatterns 메서드로 바꿨다. (setAllowCredentials(true) 와 사용할 때 좀 더 안정적이라고 함.)
  • setAllowedHeaders(Arrays.asList("*") 로 단순화하였다.
profile
더 성장하자.

0개의 댓글