[Nginx] Access to XMLHttpRequest at ‘’ from origin ‘’ has been blocked by CORS policy: Response to preflight allowed for a preflight requet 해결
[Nginx] CORS policy 해결
Feb 07, 2024
Access to XMLHttpRequest at ‘백엔드 도메인’ from origin ‘프론트 도메인’ has been blocked by CORS policy: Response to preflight allowed for a preflight requet
GET https://api.~~~net::ERR_FAILED
Axios Error: Network Error
정말 정말 며칠동안 붙잡고 있던 오류였다. 그냥 흔한 axios 통신할 때 프론트엔드에서 백엔드에 접근을 하지 못하는 CORS 정책 문제였다. 이미 스프링부트의 WebConfig 파일에 이렇게 CORS 설정을 해준 상태였다.
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("https://mumul.site") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH") .allowedHeaders("*") .allowCredentials(true) // 쿠키 인증 요청 허용 .exposedHeaders("Authorization") .exposedHeaders("Access-Control-Allow-Origin")// "Access-Control-Allow-Origin" 헤더를 노출 .maxAge(3000); // 원하는 시간만큼 pre-flight 리퀘스트를 캐싱 } }
근데 전혀 오류가 사라질 기미가 없었다. 그래서 컨트롤러에
@CrossOrigin(origins = "https://mumul.site")
를 작성해서 리액트 도메인인 https://mumul.site
에서 백엔드 도메인 주소로 크로스 오리진 접근이 가능하도록 시도해 봤다. 그런데도 효과는 없었다.백엔드에서 CORS Filter 메소드도 작성도 해봤지만 CORS 에러는 사라져줄 기미가 보이지 않았다.
그러다 새삼스럽게 알게된 사실, 아 나는 지금 프론트엔드 도메인과 백엔드 도메인이 각각 Nginx를 웹 서버로서 사용하고 있지. 그래서 CORS 설정도 백엔드 nginx conf 파일에서 해주어야 한다는 사실.
Nginx
사용 시4xx
또는5xx
오류에 대해 서버는Access-Control-Allow-Origin
를 응답 헤더에 추가하지 않는다. 서버는2xx
과3xx(redirection)
에 대해서만 해당 헤더를 보낸다.만약4xx
또는5xx
오류에 대해서도Access-Control-Allow-Origin
를 응답 헤더에 추가하고 싶다면Nginx
에서 아래와 같이 추가하면 된다.add_header <header_name> <value> always
# example add_header 'Access-Control-Allow-Origin' '*' always
아~ 그랬구나.
nginx.conf 파일을 열어준다
~$ sudo nano /etc/nginx/nginx.conf
서버 블록 안에 있는 로케이션 블록에 CORS 설정 코드를 넣어준다
if ($http_origin ~* (https://mumul\.site)) { add_header 'Access-Control-Allow-Origin' "$http_origin" always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS, PATCH' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept' al> add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Max-Age' '3000'; add_header 'Access-Control-Expose-Headers' 'Authorization'; }
$http_origin ~* (https://mumul\.site))
요청하는 origin 헤더가 “https://mumul.site” 와 일치하는지 확인하는 조건문이다/ ~* 는 정규 표현식에서 대소문자를 구별하지 않는 매칭을 의미한다
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
클라이언트의 Origin 헤더와 동일한 값(여기선 https://mumul.site)를 ‘Access-Control-Allow-Origin 헤더에 응답으로 추가한다는 것이다. 이러면 해당 출처에서 온 요청은 허용한다.
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS, PATCH' always;
허용되는 HTTP 메소드이다.
add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept' always;
클라이언트에서 서버로 전송할 수 있는 요청 헤더 목록을 지정한 것이다.
add_header 'Access-Control-Allow-Credentials' 'true' always;
클라이언트가 인증된 상태로 요청을 보낼 수 있도록 허용한다. CORS 요청에서 credentials (즉, 쿠키와 HTTP 인증 정보)를 허용할지 여부를 설정한다
add_header 'Access-Control-Max-Age' '3000'
브라우저가 사전 검사 요청(pre-flight)을 캐시할 수 잇는 시간을 설정한 것이다. 사전 검사 요청의 결과를 캐시하려 성능을 향상시킨다.
add_header 'Access-Control-Expose-Headers' 'Authorization';
응답 헤더에 Authorization을 노출시켜서 클라이언트가 접근 가능하도록 한다.
그랬더니 콘솔 창에 CORS 가 사라진다. 내가 지금 뭘 하고 있는지 인지에서 시작하는 한걸음이었다.
Share article