▶ Environment
React(Frontend): http://localhost:5173
SpringBoot(Backend): http://localhost:8080
▶ When the Error Occurred
로그인 기능 구현 중 클라이언트와 서버의 통신 과정에서 발생하였다.
▶ Error Message
Access to XMLHttpRequest at 'http://localhost:8080/user/addbasic' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
http://localhost:5173에서 http://localhost:8080/user/addbasic으로
XMLHttpRequest를 시도했지만, CORS 정책에 의해 차단되었습니다.
요청한 리소스 응답에 Access-Control-Allow-Origin 헤더가 존재하지 않습니다.
▶ Error Description
React(포트 5173)에서 SpringBoot(포트 8080)으로 HTTP요청을 보낼 때 Same-Origin Policy에 의해 CORS 정책이 적용되어 요청이 차단되었다.
백엔드 서버가 Access-Control-Allow-Origin 헤더를 설정하지 않아 발생한 문제다.
▶ Error Analysis
문제 발생 원인
→ React 클라이언트(포트 5173)에서 SpringBoot 서버(포트 8080)으로 XMLHttpRequest를 보내려고 시도했으나, 브라우저의 CORS 정책에 의해 요청이 차단되었다.
CORS 정책에 의해 차단당한 이유
→ CORS(Cross-Origin Resource Sharing)는 보안상의 이유로, 다른 출처(다른 도메인, 포트 등)에서 오는 요청을 제한하는 브라우저 보안 정책이다.
→ React 클라이언트는 http://localhost:5173에서 실행되고, SpringBoot 서버는 http://localhost:8080에서 실행되므로, 이 둘은 다른 출처로 간주된다.
→ 따라서, React(포트 5173)에서 SpringBoot(포트 8080)로 보내는 요청은 CORS 정책에 의해 차단된다.
CORS 동작 원리
→ 클라이언트에서 서버로 HTTP 요청을 보낼 때, 브라우저는 요청의 출처(프로토콜, 도메인, 포트)를 확인한다.
→ 만약 출처가 다르면, 브라우저는 기본적으로 CORS 정책을 적용하여 요청을 차단한다.
→ 서버가 Access-Control-Allow-Origin 헤더에 허용할 출처를 명시하면, 브라우저는 이를 보고 요청을 허용할 수 있다. 이 헤더에 명시된 출처만 요청을 허용하며, 그렇지 않으면 요청을 차단하게 된다.
▶ Error Resolution
1. 전역 CORS 설정 - 성공
import org.springframework.context.annotation.Bean;
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 CORS {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:5173")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}
CORS라는 클래스를 프로젝트 폴더에 따로 만들어 전역으로 허용해주었다.
단, 전역으로 허용하는 경우 보안 측면에서 문제가 발생할 수 있음으로 2번 방법을 추천한다.
2. 특정 엔드포인트에 CORS 설정 - 성공
import org.springframework.context.annotation.Bean;
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 CORS {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/user/**")
.allowedOrigins("http://localhost:5173")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}
→ registry.addMapping("/user/**") - /user/로 시작하는 모든 엔드포인트에 CORS를 적용한다.
→ .allowedOrigins("http://localhost:5173") - localhost:5173 도메인에서 오는 요청만 허용한다.
→ .allowedMethods("GET", "POST", "PUT", "DELETE") - GET, POST, PUT, DELETE 요청만 허용한다.
→ .allowedHeaders("*") - 모든 헤더를 허용한다.
→ .allowCredentials(true); - 인증(쿠키 등)을 허용할지 설정한다.
두 가지 방법 모두 Access-Control-Allow-Origin에 허용할 출처를 명시하여 요청을 허용할 수 있도록 해준다.
(첫 방법은 localhost:5173에서 오는 모든 경로에서 오는 요청을 전역적으로 허용하였다.)
▶ Comment
CORS 정책에 대해 알고는 있었지만, 에러가 발생했을 때 그저 대처법만 복사 붙여 넣기 하여 해결하였다.
하지만 이번에 Troubleshooring Note에 직접 기록하며 조금 더 상세하게 알게 되었다.
예를 들어 "Access-Control-Allow-Origin에 허용할 출처를 명시하면 그 출처에 대한 요청은 허용한다."
와 같은 개념을 알게 되었다. 이번 노트 작성을 통하여 면접 때 CORS 정책과 해결법을 물어본다면 자신 있게 대답할 수 있을 만큼 성장한 것 같아 뿌듯하다.
Thank Ya :)
'Web Development > Troubleshooting Note' 카테고리의 다른 글
[ Troubleshooting Note ] Spring Boot - Variable might not have been initialize (1) | 2025.04.29 |
---|