환경 구성
| 소프트웨어 | 버전 |
|---|---|
| JDK | 8 |
| Spring Boot | 2.1.8.RELEASE |
| Vue CLI | 4.3.1 |
문제 개요
Vue와 Element UI로 개발한 프론트엔드가 Spring Boot 백엔드와 통신 시 다음 오류 발생:
no 'access-control-allow-origin' header is present on the requested resource
이는 브라우저의 동일 출처 정책(Same-Origin Policy)에 기인한 교차 출처 문제입니다.
핵심 개념
동일 출처 정책
보안 정책으로 한 출처의 문서/스크립트가 다른 출처의 리소스와 상호작용하는 것을 제한합니다. 다음 조건을 모두 만족해야 동일 출처로 인정됩니다:
- 프로토콜 동일
- 도메인 동일
- 포트 번호 동일
교차 출처 요청 필요성
현대 웹 개발의 프론트엔드-백엔드 분리 아키텍처에서는 도메인과 포트가 서로 달라 교차 출처 접근이 필수적입니다.
해결 방법
1. 프론트엔드 프록시 설정 (개발 환경 전용)
// vue.config.js
module.exports = {
devServer: {
port: 8000,
proxy: {
'/data': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
};
⚠️ 주의: 프로덕션 환경에서는 적용 불가
2. 백엔드 CORS 필터 설정 (Spring Boot)
환경 변수 설정
# application.yml
cors:
permitted-origins:
allowed-methods: GET,POST,PUT,DELETE,OPTIONS
exposed-headers: Authorization,Content-Type
credentials-enabled: false
max-age: 1800
구성 프로퍼티 클래스
@Data
@ConfigurationProperties(prefix = "cors")
public class CorsSettings {
private String permittedOrigins;
private String allowedMethods;
private String exposedHeaders;
private boolean credentialsEnabled;
private long maxAge;
}
CORS 필터 등록
@Configuration
@EnableConfigurationProperties(CorsSettings.class)
public class CorsConfiguration {
@Autowired
private CorsSettings config;
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowCredentials(config.isCredentialsEnabled());
// Origins 설정
if(StringUtils.isEmpty(config.getPermittedOrigins())) {
corsConfig.addAllowedOriginPattern("*");
} else {
Arrays.stream(config.getPermittedOrigins().split(","))
.forEach(corsConfig::addAllowedOrigin);
}
// 메서드 설정
Arrays.stream(config.getAllowedMethods().split(","))
.forEach(corsConfig::addAllowedMethod);
// 헤더 설정
Arrays.stream(config.getExposedHeaders().split(","))
.forEach(corsConfig::addAllowedHeader);
corsConfig.setMaxAge(config.getMaxAge());
source.registerCorsConfiguration("/**", corsConfig);
FilterRegistrationBean<CorsFilter> bean =
new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
}
결과
백엔드 CORS 필터 구현을 통해 프론트엔드-백엔드 간 교차 출처 요청이 정상 처리됩니다.