친구랑 프로젝트를 진행하는 도중에 아래 사진을 받았습니다.
이전의 프로젝트에서도 경험한CORS
의 에러인데 해결 방법(django)만 알고 어떠한 에러인지 자세히 알지 못해서 포스팅했습니다.
백엔드 개발자가 포스트맨으로도 확인하고 테스트 코드가 다 통과하더라고 발생할 수 있는 에러입니다.
왜일까요 ?
아래 포스팅을 읽고 답을 얻으셨으면 좋겠습니다.
스프링 부트에서는 처음 해결해보네요 : >
교차 출처 리소스 공유를 뜻하는 CORS는
서로 다른 출처에서 리소스를 공유
한다는 뜻입니다.
여기서
Origin
감이 오시나요 ?
- CORS에서 Origin이란 웹 컨텐츠의 출처를 의미한다고 합니다.
그림으로 한번 살펴보겠습니다.
URL
은 상단의 형태로 구성되어 잇습니다.
이 중 Protocol
+ Host
+ Port
를 합쳐 부르는 말이 Origin(출처)
입니다.
즉, CORS 허용 설정을 하지 않았다면 !
개발 중인 서버의
Origin
→http://localhost:8080
서버에 요청을 보낸 React의
Origin
→http://localhost:3000
가정할 때
Origin
의Port
부분이 동일하지 않기 때문에 문제가 발생하는 것입니다.
CORS
에 대한 개념은 알겠습니다. 그렇다면 왜 제한할까요 ?
서로 다른 출처를 가진 두 애플리케이션이 자유롭게 서로를 접근할 수 있는건 매우 위험합니다. 보안을 위해서죠
크롬에서 F12를 눌러 개발자 도구를 통해서도 어떤 서버와 통신하고, 어떤 정보를 주고 받는지 등등 여러 정보를 확인할 수 있습니다.
만약 다른 출처를 가진 애플리케이션에 접근 제한이 없다면 XSS
나 CSRF
등을 통해 중요한 데이터를 빼갈 수 있는거죠 !
중요한 부분은 이
CORS
를 확인하는 로직이 서버가 아닌 브라우저에 구현되어 있습니다. 그렇게 때문에Postman
과 같은 툴을 이용해 API요청을 보낼때는CORS
에러가 발생하지 않았던거죠 !
기본적으로 웹 클라이언트 애플리케이션이 다른 출처의 리소스 요청을 할 때 HTTP 프로토콜을 사용합니다.
(1) 요청 헤더에 Origin 추가
요청을 보낼 때, HTTP 헤더에 Origin 필드가 포함
되어 해당 리소스를 요청한 출처가 전송
됩니다.(2) 응답 헤더에 Access-Control-Allow-Origin 추가
Access-Control-Allow-Origin 헤더를 응답에 포함
시킵니다.(3) 출처 비교
서버로부터 받은 Access-Control-Allow-Origin 값과 요청 시 보낸 Origin 값을 비교
합니다.(4) 응답 유효성 판단
출처가 일치하는지 여부를 확인
하고, 이를 기반으로 응답이 유효한지를 판단합니다.서버에서
http://localhost:3000
오리진의 요청에 대해 CORS를 허용해주면 되겠죠 ?
파일구조입니다 ! MvcConfiguration
파일을 생성하고 아래 코드를 작성했습니다.
@Configuration
@EnableWebMvc
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("*")
.allowCredentials(false)
.maxAge(3000);
}
}
addCorsMappings
메서드를 오버라이딩해서 모든 RequestMapping
에 대하여, 통신을 주고 받은 React Origin(port:3000)
의 요청에 대해 CORS를 허용
해주었습니다.
allowCredentials(false) - 기본 설정
maxAge(3000);
Preflight 요청의 최대 유효 기간을 설정합니다.
Preflight 요청은 실제 요청을 보내기 전에 브라우저가 서버에게 허용 여부를 물어보는 사전 요청
입니다.
이를 통해 브라우저와 서버 간의 허용 여부를 확인하고, 그 정보를 기억하는 시간을 maxAge로 설정할 수 있습니다. 여기서는 3000초(5분) 동안 Preflight 요청의 결과를 기억하게 됩니다.
Preflight의 자세한 동작방식은 아래 참고 자료가 잘 설명해주셨습니다 !
동작방식 참고하기 좋은 자료 evan-moon
아래는 Spring Secutiry
참고 자료 혹시 몰라서 첨부합니다 : >
Spring Security 참고자료