1. CORS 개요

​

CORS (교차 출처 자원 공유)는 보안 상의 이유로

JavaScript에서 보내는 교차 출처(자신과 다른 출처) HTTP 요청을 제한하기 위한 정책입니다.

​

대다수 브라우저에는 CORS가 적용되어 있는데

이는 자신의 출처와 동일한 리소스만 불러올 수 있도록 하여, 악의적인 자원 접근과 탈취를 막기 위함입니다.

 

cors01.jpg

[그림 1] CORS 개요

​

2. CORS 에러

​

웹을 개발하면서 아래와 같은 에러 메시지를 한번쯤 보셨을 것 같습니다.

CORS 에러가 발생하는 이유는 [CORS 개요]에서 소개했듯이

JavaScript 코드 상에서 동일한 출처가 아닌 곳에서 요청을 하였기 때문입니다.

​

아래의 에러 내용을 살펴보면

"http://localhost:3000 출처에서 보낸 https://www.example.com 의 자원 접근 요청을 CORS 정책에 의해 차단되었습니다."

라는 문구를 확인할 수 있습니다.

​

Access to fetch at ‘http://www.example.com’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
/* * main.js * local에서 main.js가 http://www.example.com에 데이터를 요청함 * 출처가 다르기 때문에 CORS 에러 발생 */ $.get('http://www.example.com', function (data) { alert('Data Loaded: ' + data); });

​

3. CORS 동작 과정

​

CORS는 브라우저에서 이루어집니다. 때문에, 브라우저의 옵션을 수정하면 CORS를 회피할 수 있습니다.

예를 들어 크롬 브라우저에서 --disable-web-security 옵션을 추가하면 CORS 에러 없이 여러 출처의 리소스에 대해 접근할 수 있습니다.

​

그렇다면, 브라우저는 어떻게 CORS를 동작하고 있을까요?

CORS는 Preflight Request, Simple Request 두 가지 방식으로 동작됩니다.

Preflight Request, Simple Request에 대해 한번 알아봅시다.

​

​

● Preflight Request​

​

본 요청을 보내기 이전에 보내는 예비 요청을 Preflight라고 부릅니다.

Preflight는 HTTP의 OPTIONS 메소드를 이용해 서버에 보내집니다.

이러한 예비 요청을 통해 본 요청을 보내기 전, CORS를 위반하고 있는지를 확인합니다.

Preflight에 대한 서버 응답이 안전하다면 브라우저는 본 요청을 서버에 다시 보냅니다.

 

cors02.jpg

[그림 2] Preflight Request 동작

​

​

● Simple Request​

​

Simple Request (단순 요청)는 Preflight Request 방식과 달리 예비 요청을 보내지 않습니다.

대신 Access-Control-Allow-Origin 헤더를 이용해 CORS 위반 여부를 검사합니다.

​

클라이언트의 요청에 대해 서버는 Access-Control-Allow-Origin 헤더와 함께 응답합니다.

​

Access-Control-Allow-Origin 헤더에는 CORS 정책이 담겨있고

브라우저는 Access-Control-Allow-Origin 헤더의 내용을 토대로 정책을 위반했는지 확인합니다.

이상이 없다면 본 요청을 서버에 보냅니다.

 

SE-694362eb-da00-41e7-8a0a-0c628824979b.png

[그림 3] Simple Request 동작

​

​

4. CORS 해결 방법

​

CORS는 서버, 클라이언트 한쪽만 의 적용으로 해결할 수 있습니다.

서버, 클라이언트 각각에서 CORS를 처리하는 대표적인 방법 두 가지를 소개합니다.

(다만, 서버에서 CORS 정책을 제어하는 것을 권장합니다.)

​

​

● @CrossOrigin 어노테이션 이용 (API)

​

스프링 기준, 스프링 4.2 이상부터 지원되는 @CrossOrigin을 이용하여 CORS 정책을 설정할 수 있습니다.

Controller에 어노테이션을 추가하면 적용됩니다.

​

• @CrossOrigin : 모든 도메인, 모든 요청 방식에 대해 허용.

• @CrossOrigin(origins = "http://www.example1.com, http://www.example2.com") : http://www.example1.com, http://www.example2.com 도메인에 대해서만 허용.

​

@CrossOrigin public class ProjectController { @GetMapping(value="/projects/list", produces = "application/hal+json") public ResponseEntity<List<Project>> getProjectList(@ModelAttribute KeystoneProject project){ return ResponseEntity.ok(projectService.getProjectList(project)); } }

​

● 프록시 이용 (Client)

​

CORS 에러는 근본적으로 자신과 다른 출처에서 HTTP 요청을 하였을 때 발생한다는 점을 기억해 보면

자신의 출처를 프록싱하면 CORS를 회피할 수 있을 것 같습니다.

클라이언트는 이 같은 아이디어로 CORS 에러를 해결합니다.

프록싱을 통해 자신의 출처를 CORS가 허용되는 출처로 바꿔 HTTP 요청을 하는 것이죠.

​

프록싱을 하면 최소한의 설정으로 CORS를 회피할 수 있어 개발 시 이용되곤 합니다.

​

​

​

​

참고

⦁ https://medium.com/@buddhiv/what-is-cors-or-cross-origin-resource-sharing-eccbfacaaa30

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

⦁ https://evan-moon.github.io/2020/05/21/about-cors/#preflight-request

⦁ https://velog.io/@roh-j/CORS-Cross-Origin-Resource-Sharing%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C

 

 

번호 제목 글쓴이 날짜 조회 수
246 [Gemini] ajax 와 fetch 의 차이 황제낙엽 2025.01.04 3419
245 [검토 완료] 디바이스 카메라로 촬영한 사진을 서버에 업로드하기 샘플 황제낙엽 2024.11.21 3987
244 브라우저에서 이미지를 편집(crop 등) 할 수 있는 오픈소스 Cropper.js 황제낙엽 2024.11.16 3842
243 [ChatGPT] json data 의 정렬 [1] 황제낙엽 2024.07.23 3352
242 DOMContentLoaded 이벤트와 window.onload 이벤트 황제낙엽 2024.07.15 3669
241 fetch() 사용 예제들 황제낙엽 2024.07.09 3380
240 [Copilot] Vanilla JavaScript에서 외부 스크립트 파일에 정의된 함수들을 로드 황제낙엽 2024.06.21 3758
239 [Copilot] ES6 모듈(module) 문법 황제낙엽 2024.06.21 3805
238 [Copilot] JSON 객체 내부 데이터를 순회하면서 조회하는 코드 황제낙엽 2024.06.02 3270
237 [Copilot] JavaScript로 서버에 특정 값을 POST 방식으로 전달하고 응답을 기다리지 않고 바로 종료 황제낙엽 2024.05.31 3615
236 json 데이터 내의 변수명에 prefix 로 type 표현하기 황제낙엽 2024.04.15 3361
235 fetch() 함수 사용 예제 file 황제낙엽 2023.11.23 3605
234 현재 document 의 host 와 port 를 얻는 방법 황제낙엽 2023.10.03 4209
233 (Bard) FileReader 로 여러개의 파일을 read 하는 법 file 황제낙엽 2023.08.23 3660
232 How to build a file upload service with vanilla JavaScript file 황제낙엽 2023.08.22 3715
231 (Bard) JavaScript로 JSON 배열을 작성하는 방법 황제낙엽 2023.08.21 3672
230 모바일 브라우저에서 file input element 를 이용하여 여러장의 이미지를 서버에 전송하려 할때 [1] 황제낙엽 2023.08.21 3703
229 navigator.mediaDevices 황제낙엽 2023.08.21 3798
228 Barcode Detection API 황제낙엽 2023.08.06 3854
227 정규식을 이용한 이메일 검증 스크립트 file 황제낙엽 2023.06.25 2894