💥 개요
사이드 프로젝트 진행 시 항상 문제가 되던건, CORS였습니다. CORS란
CORS(Cross-Origin Resource Sharing)는 클라이언트(웹 브라우저)에 의해 제어되는 HTTP 기반 보안 메커니즘입니다. 이를 통해 서비스(API)는 클라이언트가 요청할 수 있는 오리진 이외에 요청할 수 없는 오리진도 표시할 수 있습니다. 한 오리진에서 로드한 웹사이트(HTML 문서 또는 JS 스크립트)가 다른 오리진의 리소스와 상호 작용할 수 없게하는 SOP(Same-origin policy)와 함께 설계되었습니다. CORS는 일부 크로스 오리진 요청을 명시적으로 허용하고 다른 요청은 거부하는데 사용됩니다.
CORS는 기본적으로 웹 브라우저에서 구현되지만 API 클라이언트에서도 옵션으로 사용할 수 있습니다. 현재 Google Chrome, Firefox, Opera 및 Safari와 같은 모든 인기 웹 브라우저에 구현되어 있고 이 표준은 2014년 1월 W3C 권고안으로 승인되었습니다. 이런 이유로 현재 사용 가능한 모든 웹 브라우저에 CORS가 구현되어 있다고 볼 수 있습니다.
라고 하는데, 쉽게 말하자면 "현재 클라이언트와 다른 곳에서 요청하는 악의적인 데이터를 통신하는것을 방지하기 위함" 입니다.
❓ 문제 원인
항상 Spring Boot에서 Cors를 설정하게 되면 보통 아래와 같이 설정을 하라는 글을 많이 찾을 수 있습니다.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")// 혹은 localhost:3000
.allowedMethods("*")
.maxAge(3000);
}
}
하지만 위와 같이 설정하게 되면 몇가지 문제점이 있습니다. 위와 같이 .allowedOrigins에 와일드카드(*)를 넣고 프로젝트를 실행하게 되면 보통 문제가 해결된다고 합니다. 하지만 클라이언트(여기서는 같이 프로젝트를 진행하던 프론트 리액트 개발자)에서 쿠키를 사용하려면(인증정보 등을 담음) withCredentails를 true로 설정해줘야 하는데, 이렇게 되면 백엔드 쪽 에서도 withCredentails를 true로 설정해줘야 합니다.
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowCredentials(true)
.maxAge(3000);
}
하지만 위의 코드를 실행하면 Cors 설정이 동작하지 않습니다. 스프링부트 2.4.0부터 보안 문제로 인해 allowCredentials가 true일 때 allowedOrigins에 와일드카드(*)를 사용할 수 없게 되었습니다. 그렇다면 아래와 같이 직접 Origin을 명시해줘야 합니다.
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("https://pick-time.vercel.app")
.allowedMethods("*")
.allowCredentials(true)
.maxAge(3000);
}
이렇게 직접 설정을 하면, CORS 에러는 어느정도 해결됩니다.
하지만 현재 프론트 개발자는 5명인 상황에서 고정 IP가 아닌 이상 Origin을 매번 바꿔서 배포해야하고, Wifi를 사용하게 된다면 프론트 로컬에서는 항상 CORS를 만나게 됩니다. 그럼 이걸 어떻게 해결해야 할까요?
✅ 해결 방법
정말 너무 간단해서 처음에 CORS를 만나게 된 사이드 프로젝트에서는 위와 같은 방법으로 해결했지만, 프론트 개발자는 CORS를 로컬에서 피하기 위해 proxy를 사용하여 우회하여 개발하고 서버 배포시에는 위와 같이 Origin을 지정해주는 방식으로 해결했습니다. 하지만 아래와 같이 .addAllowedOriginPattern를 적용하게 된다면 문제는 간단하게 해결됩니다.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
//.allowedOrigins("https://pick-time.vercel.app") //기존 설정 주석
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowCredentials(true)
.maxAge(3000);
}
}
출처
https://sisiblog.tistory.com/285
'Error > 트러블슈팅' 카테고리의 다른 글
[JAVA] ENUM에 setter를 쓰면 생기는 일 (feat. 싱글턴) (1) | 2024.12.10 |
---|---|
[Trouble Shooting - Transaction과 DB Session] DB 특정 테이블 (row) 업데이트 안되는 문제 (0) | 2023.07.17 |
[Trouble Shooting - RequestBody와 생성자] 스프링부트 LocalDateTime JsonFormat 안됨 (2) | 2023.05.19 |
[Trouble Shooting] Spring boot 중복 파일 업로드시 file not found에러 발생 (0) | 2023.04.26 |