프론트 개발을 하면서 숱하게 만나왔던 CORS 에러... 항상 야매로 인터넷에 뜨는 해결책 이것저것 찔러보다 해결되면 넘어가고 말았었는데,
이번에 인턴 활동 하면서 & 서버 공부 하면서 CORS가 일어나는 이유와 해결 방법에 대해 완전 이해해버렸다!
까먹지 않기 위해 내용을 기록해 두려고 한다
CORS란?
Cross Origin Resource Sharing, 이 말은 즉슨 Origin이 다른(=출처가 다른) 자원들을 서로 공유한다는 뜻이다.
Origin은 Protocol + Host + Port 이 세 가지로 판단하며, 이 3가지가 같으면 동일한 출처로 간주한다.
예를 들어, 아래 경우들은 서로 다른 출처로 간주되는 경우이다.
Protocol이 다름 | https://lamerry.com http://lamerry.com |
Host가 다름 | https://lamerry.com https://naver.com |
Port가 다름 | https://lamerry:3000 https://lamerry:8080 |
이처럼 서로 다른 출처에서 요청이 들어오는 경우, CORS 정책에 의하여 해당 출처가 '허용'된 경우에만 요청을 처리하게 된다.
CORS 정책이 있는 이유?
웹에서는 <img>, <video>, <script> 등의 태그로 페이지 로딩 이후에 브라우저에서 하위 자원들을 가져올 수 있다.
(각 src 항목에 넣어주던 것들을 기억해라)
이때, 사용자가 악의를 가지고 이것들을 수정한다면...? 악의적인 script가 실행될 수도 있는 아주 위험천만한 상황이 일어나는 것이다!
CORS의 동작 원리
웹 브라우저에서 요청을 보내는 경우는 크게 3가지로 나누어볼 수 있다.
1) Simple request 2) Preflight request 3) Credential request
1) Simple request
- 조건을 만족하는 경우, 별다른 확인 없이 바로 서버에게 요청을 보낸다. (보통 단순 get 요청의 경우)
- 바로 서버에게 요청을 보낸 후, 응답 헤더의 Access-Control-Allow-Origin을 보고 CORS 정책 위반 여부를 판단한다.
2) Preflight request
- 서버에 영향을 줄 수 있는 요청으로 OPTIONS 메소드를 이용해 안전한지 확인 후, 본 요청을 보낸다.
- Preflight request의 응답 헤더 Access-Control-Allow-Origin을 보고 CORS 정책 위반 여부를 판단한다.
3) Credential request
- 다른 출처 간 통신에서 조금 더 보안을 강화하고 싶을 때 사용하는 방법으로,
- credentials 옵션을 이용해 Access-Control-Allow-Origin 헤더뿐 아니라 다른 것들도 확인하여 위반 여부를 판단한다.
CORS 위반
결국 위 3개의 상황에서 볼 수 있듯이, Access-Control-Allow-Origin 헤더에 요청하는 곳(출처, Origin)이 있는지 여부를 가지고 판단한다는 것이다.
결국 CORS 위반이 발생하는 상황을 아래 한 문장으로 정리할 수 있다.
3️⃣ 브라우저에서 1️⃣ 도메인이 다른 곳에 소스 요청 시, 2️⃣ 허용되지 않은 도메인이라면 발생한다
그럼 여기서 바꿔볼 수 있는 것을 바꿔볼까?
CORS 해결
1️⃣ 도메인이 다른 곳에 소스 요청 -> X, 도메인은 변경할 수 없다!
2️⃣ 허용되지 않은 도메인 -> O, 서버에서 Response Header에 해당 도메인을 허용해 준다
: CORS 해결법으로 가장 많이 뜨는 방법으로, 서버 단에서 Response Header에 모든 도메인을 허용하거나 or 해당 도메인을 허용하도록 설정한다.
response.setHeader('Access-Control-Allow-origin', '*');
3️⃣브라우저 -> O, 브라우저가 아닌 서버에서 요청한다
: 보통 웹 브라우저를 띄우는 웹 서버(WAS)가 따로 존재할 것인데, 거기서 Proxy 설정을 해 주어 웹 서버->서버로 요청이 가게끔 처리하는 방법이다.
나의 경우 Vue + Nuxt.js를 사용한 프로젝트에서 작업해야 했기에 해당 기준으로 방법을 작성한다.
1. config.yml에 Proxy 정보를 입력해 둔다
server:
middleware:
proxy:
proxies:
"/lamerry/": http://lamerry:3000
2. API 요청 시, 정의해둔 url로 호출한다
api.call<BaseResponse>({
...options,
url: '/lamerry/list'
})
3. WAS에서 proxy 처리된다
이렇게 끝! 드디어 CORS에 대해 완전 이해했다... 얼마나 걸렸는가 ㅠㅠ
느리지만 여러 공부를 하며 차곡차곡 쌓아온 지식들이 하나가 되어 풀리는 쾌감이 장난 아니었다 ㅎㅎ
막연하게 공부한다는 생각에 항상 두려웠는데, 그 두려움을 조금은 떨칠 수 있을 것 같다.
[참고]
https://inpa.tistory.com/entry/WEB-📚-CORS-💯-정리-해결-방법-👏#1._chrome_확장_프로그램_이용
[Vue3] devServer proxy 설정하는 이유, 방법
'💻 Web' 카테고리의 다른 글
[Frontend/Nuxt] Nuxt3에서 달력 라이브러리 사용하기 (0) | 2023.09.24 |
---|