자주 마주하는 CORS에러, 나올 때마다 찾아보지 말고 확실하게 기억하려고 정리하는 글.
1. CORS란
CORS는 Cross-origin resource sharing의 약자로 한국어로는 교차 출처 자원 공유이다.
CORS 에러는 주로 한 사이트에서 주소가 다른 서버로 요청을 보낼 때 자주 접하게 되는 오류이다.
A.com 사이트에서 B.com 서비스에 API로 정보를 받아오기 위해 브라우저에서 HTTP 요청을 보냈을 때 Origin이 다르기 때문에 "브라우저"에서 안전하지 않다고 판단해 막아버린다. (서버가 하는 일이 아니라는 것!)
1) 여기서의 Origin이 무엇인가
url을 하나 예시로 들어 구조를 살펴보면 다음과 같다.
https://niliso.tistory.com:3000/entry
Protocol://Host:Port (보통 생략함)/Path
여기서 Protocol, host, port 까지를 Origin이라고 한다.
2. 왜 필요할까
1) SOP란
CORS가 왜 필요한지 알기위해서는 SOP를 먼저 알아야 한다.
SOP는 Same-Origin Policy로 동일 출처 정책이다. 이름에서도 느껴지듯이 동일한 출처, URL끼리만 API등을 통한 데이터 접근이 가능하도록 하는것이다.
왜 이런 정책을 만들었을까에 대한 이해를 위해 예시를 가져왔다.
악의적인 마음을 품은 해커가 자신의 웹사이트를 구축해놓고, 이 웹사이트를 가리키는 링크를 담은 메일을 사용자에게 보내는 것이다. 그리고 이 사용자는 A라는 웹사이트에 로그인이 되어 있어서 브라우저 단에 인증 정보가 존재한다고 해보자. 만약 그 사용자가 실수로 해당 링크를 클릭하여 해커의 웹사이트에 접속하면, 해커가 심어둔 JavaScript 코드가 실행되어 자기도 모르게 A 웹사이트로 개인 정보를 조회하는 API 요청을 보낼 것이다. 이 사용자의 브라우저 단에는 인증 정보가 존재하기 때문에, 이것이 해당 요청에 함께 실어서 전송되면 서버는 인증된 요청이라 생각하여 개인 정보를 응답해줄 것이다. 그러고 나면 그 개인 정보를 해커가 빼돌릴 수 있게 된다. (이것이 바로 CSRF 공격이다.)
위와 같은 상황에서 해커의 웹사이트와 A 웹사이트는 Origin이 다르기 때문에 API 요청을 보낼 수 없다. 따라서 SOP는 브라우저의 아주 기본적인 보안 정책으로서 기능하는 것이다.
[출처] https://it-eldorado.tistory.com/163
2) 그래서 CORS는 왜?
CORS는 SOP와 반대로 다른 Origin에서 요청을 허용해주기 위해 요청을 받는 백엔드쪽에서 이걸 허락할 다른 출처들을 미리 명시해두는것이다.
웹이 발전하면서 여러 서비스들간에 리소스 교환이 필요해졌고, 이를 위해 CORS가 꼭 필요한것이다.
오류로 많이 만나서 뭘 막는애인줄 알았는데, 사실은 그 반대였음,, 빡세게 막는 SOP를 예외해주기위해 CORS 설정이 필요한겨👀
3. 어떻게 동작해?
1) Simple Request

브라우저는 다른 출처끼리의 요청이 보내질때 헤더에 Origin이 포함해서 보내고, 요청을 받은 서버는 응답헤더에 Access-Control-Allow-Origin을 포함해서 리턴한다.
요청을 받은 브라우저에서 요청의 출처값이 답장 헤더의 Access-Control-Allow-Origin에 포함되어 있으면 응답 데이터를 받아오게된다.
(없으면 바로 에러 빡)
Simple Request로 보낼 수 있는 조건은 요기에서 확인!
2) Preflight Request

Preflight Request는 가장 흔한 요청으로, 정식요청 전 먼저 OPTIONS 메서드 요청을 통해 실제 요청이 전송하기 안전한지 확인하는 예비 요청을 보낸다. 서버의 데이터에 영향을 줄 수 있는 요청이기 때문에 미리 체크 하는것이다.
브라우저는 이 예비 요청의 응답을 통해 정책을 비교한 후 안전하다고 판단되었을 경우에만 본 요청을 보내고 응답을 받는다.
3) 인증정보를 포함한 요청

토큰 같은 사용자 식별정보가 담기 요청에 대해서는 XMLHttpRequest 객체나 Request 생성자가 호출될 때 credentials 항목을 true로 세팅해야하고, 응답 헤더에서는 Access-Control-Allow-Origin에는 *를 사용할 수 없으며 반드시 Access-Control-Allow-Credentials: true가 존재해야한다. 아니면 브라우저에서 CORS 에러를 떨군다.
4. 설정은 어케해?
1) Spring boot
Spring boot에서 CORS 설정은 어노테이션과 Configuration으로 설정가능한데, 내 플젝에서는 Configuration으로 하였다.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH");
}
}
2) Node.js
const http = require('http');
const server = http.createServer((request, response) => {
response.setHeader("Access-Control-Allow-Origin", "*");
})
[참고 자료들]
https://developer.mozilla.org/ko/docs/Web/HTTP/CORS
https://evan-moon.github.io/2020/05/21/about-cors/
https://it-eldorado.tistory.com/163
'뇌에 쑤셔넣기' 카테고리의 다른 글
배포 전략 - Rolling, Blue-Green, Canary 기법 (0) | 2023.02.14 |
---|---|
[SpringBoot]SpringBoot에서 Filter와 Interceptor 사용하기 (0) | 2023.01.02 |
댓글