본문 바로가기

개발자 강화/백엔드

[매일메일] CORS란? (BE.250116) + (FE.250205)

내가 제일 좋아하는 CORS 에러 짤

CORS(Cross Origin Resource Sharing) 개념

- 출처 교차(Cross Origin): 리소스를 주고받는 곳의 출처가 다른 경우에 발생함 (*출처: 도메인, 프로토콜, 포트 등)

- 출처 교차인 경우 접근 권한을 부여하는 메커니즘이 필요함

- CORS는 서로 다른 출처에서 제공되는 리소스에 접근할 수 있도록 허용하는 정책

 

CORS의 필요성?

- 위조 요청 문제를 해결하기 위함(CSRF, Cross-Site Request Forgery, 크로스사이트 요청 위조)

- 피해자가 공격자의 웹 사이트에 접속했을 때, 해당 사용자의 요청인 것처럼 타 사이트에 GET 요청을 보냄

- 위와 같이 의도치 않은 요청을 서버에 보내서, 사용자의 개인정보 등을 탈취할 수 있음.

 

SOP란?

- Same-origin policy: 동일 출처 정책. 클라이언트와 동일한 출처의 리소스로만 요청을 보낼 수 있음

- 다른 출처의 요청을 보낼 경우, 해당 요청에 대한 응답에 접근할 수 없도록 막음. CSRF 공격 효과 줄이고 보안을 강화함.

- But! 합법적인 요청까지 차단될 수 있음. 현대의 웹 어플리케이션은 다른 출처의 리소스를 사용하는 경우가 많음.

 

CORS 작동 과정?

 

1. Simple Request

🔹 방법: 브라우저 요청 메시지에 Origin 헤더와 응답 메시지의 Access-Controll-Allow-Origin 헤더를 비교함

  • Origin: 현재 요청하는 클라이언트의 출처
  • Access-Control-Allow-Origin: 리소스 요청 허용하는 출처

🔹  해당하는 경우

  • 요청 메서드
    GET, POST HEAD인 경우만
  • 수동으로 설정한 요청 헤더
    Accept, Accept-Language, Content-Language, Content-Type, Range인 경우만
  • Content-Type 헤더
    application/x-www-form-urlencoded, multipart/form-data, text/plain인 경우만(헤더가 단순해야 함)

 

🔹  예시

  • 요청
    GET /api/data HTTP/1.1
    Host: example.com
    Origin: http://my-client.com
  • 응답
    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: http://my-client.com
    Content-Type: application/json
 

http://my-client.com

 

my-client.com

 

 

2. Preflight Request: 브라우저가 사전 요청을 보내는 경우

 

🔹  방법:

브라우저 본 요청을 보내기 전에 Preflight Request를 OPTIONS 메서드로 요청. 실제 요청이 안전한지 검토

 

🔹  해당하는 경우

  • 요청 메서드(Access-Control-Request-Method)
    PUT, DELET, PATCH 등(요청 메서드가 GET, POST, HEAD 아닌 경우)
  • Custom Header를 사용하는 경우 (Access-Control-Reques-Headers)
    Authorization, X-Custom-Header 등 사용자가 추가한 헤더가 요청에 포함될 때
  • Content-Type 헤더가 단순하지 않은 경우
    application/json, text/xml 등 단순하지 않은 MIME 타입을 사용할 때

🔹  예시

  • 요청
    OPTIONS /api/resource HTTP/1.1
    Host: example.com
    Origin: http://my-client.com (허용된 Origin)
    Access-Control-Request-Method: DELETE (허용된 메서드)
    Access-Control-Request-Headers: X-Custom-Header(허용된 요청 헤더)
    Access-Control-Max-Age: 
  • 응답
    HTTP/1.1 204 No Content
    Access-Control-Allow-Origin: http://my-client.com (허용된 Origin)
    Access-Control-Allow-Method: GET, POST, DELETE (허용된 Method)
    Access-Control-Allow-Header: X-Custom-Header (허용된 사용자 정의 헤더)
    Access-Control-Max-Age: 86400(결과 캐싱 기간)

    서버 요청이 성공했지만, Preflight는 서버/브라우저 간의 협상 단계라서 실제 데이터 반환하지 않음.

3. Credential Request: 인증된 요청을 사용(쿠키, 인증 토큰 등)

 

🔹 방법: 클라이언트가 서버에 요청을 보낼 때 쿠키나 인증 토큰 같은 사용자 인증 정보를 포함

🔹  해당하는 경우

  • 클라이언트->
    서버 요청 시 credentials 옵션을 설정함
  • 서버->
    클라이언트 응답 시 Access-Control-Allow-Credentials:true 헤더 포함.
    Access-Control-Allow-Origin에 특정 Origin 명시
    (와일드 카드 * 사용 불가. 모든 Origin 허용같은 설정이 불가능하다는 뜻)

🔹 예시

  • 요청
    fetch("https://example.com/api", { method:"GET", credentials:"include",});
  • 응답
    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: http://my-client.com
    Access-Control-Allow-Credentials: true

  Simple Request Preflight Request Credential Request
방법 요청 헤더 출처와 응답 헤더 허용 출처를 비교함 본 요청 전에 OPTIONS 메서드로 요청해서 허용된 출처인지 확인함 인증된 요청을 사용함(쿠키, 토큰 등)
메서드 GET, POST, HEAD PUT, DELETE, PATCH  
헤더 Accept
Accept-Language
Content-Language
Content-Type
Range
커스텀 헤더 사용
Authorization, X-Custom-Header
credentials 옵션 설정
Content-Type 헤더 application/x-www-form-urlencoded
multipart/form-data
text/plain
복잡한 헤더
application/json
text/xml
 
기타 가장 간단한 방법 본 요청 전 사전 요청이라
콘텐츠 미포함
와일드 카드 안됨. 정확한 Origin 명시.

 

 

 


출처

[1] 매일메일 250118 CORS란 무엇인가요? https://maeil-mail.kr 96번

 

매일메일 - 기술 면접 질문 구독 서비스

기술 면접 질문을 매일매일 메일로 보내드릴게요!

www.maeil-mail.kr

[2] gpt에게 preflight request, credential request, simple request에 대해 묻다

[3] 매일메일. 250205. CORS는 무엇이며 왜 필요한가요? 78번 https://maeil-mail.kr 

[4] 토스 페이먼츠. CORS(교차 출처 리소스 공유) https://docs.tosspayments.com/resources/glossary/cors