백엔드 팀원들의 코드를 모두 합친 첫날이었다.
아무래도 각자 다른 부분을 작성하고 연관관계도 있다보니 처음에는 컴파일 오류나는 부분들이 꽤 있었다.
그래도 import 설정을 추가하고 일부 수정했더니 다행히 코드가 잘 실행됐다.
github에 코드 올리고 머지하는것도 이제는 조금 익숙해져서 비교적 큰 충돌 없이 잘 진행되고 있다.
아무래도 부트캠프 과정에서 배운 내용을 바탕으로 하고있고 초기에 API명세, 테이블명세를 잘 작성해두어서
필드명이나 메서드명을 서로 참조하는게 편했던것같다.
다음에 본 프로젝트에 들어가서도 코드 구현 전에 분석, 설계 부분을 명확히 하는게 중요할것같다.
그런데 한가지 문제가 생겼다.
아직 배포환경은 구성하지 못해서 Ngrok을 통해서 프론트엔드 코드와 연동 테스트를 하려고했는데
CORS 설정때문에 안되는 부분이 있었다.
컨트롤러에 @CrossOrigin을 붙였는데 왜...?
구글링으로 찾아본 내용에서는 Spring Security는 기본적으로 보안을 강화하기 위해 CSRF 공격을 방지하기 위한 기능을 제공한다고 한다.
따라서 CORS 필터가 적용되므로 @CrossOrigin 애너테이션만으로는 CORS를 우회할 수 없다고 한다.
Spring Security가 적용된 애플리케이션에서 CORS를 허용하려면 Spring Security 설정에서 명시적으로 CORS를 설정해주어야한다고 한다.
(해당 부분은 조금 더 확인이 필요할것같다.)
따라서 두가지 과정을 진행했다.
- CORS 허용하기
- CORS 허용되었는지 확인하기.
혼자 작업할때는 Postman으로 확인을 하고있다보니 CORS를 고려할 필요가 없었다.
프론트에서 요청을 했을때 발견된 문제였는데 매번 프론트분께 요청을 보내달라고 할수도 없는 상황이라서
로컬에서 테스트가 가능한가? 찾아봤더니 방법은 여러가지가 있었다.
코드 작업부터 결과 확인까지 관련 내용을 정리했다.
[CORS 허용하기]
고민하고 알아본 시간에 비해 방법은 아주 간단했다.
현재 SecurityConfiguration 파일에 해당 내용을 추가해주면 됐다.
SecurityConfiguration은 WebMvcConfigurer를 구현하고 있으므로 해당 메서드가 이미 존재했다.
addCorsMappings(CorsRegistry registry) 메서드를 재정의하여 CORS 설정을 변경할 수 있었다.
@Configuration
public class SecurityConfiguration implements WebMvcConfigurer {
...
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PATCH", "DELETE")
.exposedHeaders("authorization");
}
}
.addMapping("/**") 모든 경로에 대해 CORS 설정을 추가하고 있다.
.allowedOrigins("*") 모든 Origin에서의 요청을 허용하고 있다. (필요한 경우 특정 Origin만 지정할 수 있다.)
.allowedMethods("") 지정된 메서드만 허용한다.
.exposedHeaders("") 지정된 헤더를 노출시키도록 설정했다. 클라이언트와 JWT를 주고받기위해 필요한 설정이다.
추가로, ngrok을 실행할 때
ngrok http 8080이 아닌 아래 코드로 실행해주었다.
ngrok http --host-header=rewrite 8080
[CORS 확인하기]
크게 두가지 방법이 있었다.
Curl을 사용하는 방법과 Postman을 사용하는 방법.
나는 현재 맥북을 사용하고 있어서 터미널에서 Curl을 바로 사용할 수 있었다.
아래 메서드를 순서대로 입력하면 200, 403과 같은 HttpStatus를 응답으로 받아볼 수 있다.
curl \
--verbose \
--request OPTIONS \
'https://Cors 확인하고 싶은 주소' \
--header 'Origin: http://요청하는 주소' \
--header 'Access-Control-Request-Headers: Origin, Accept, Content-Type' \
--header 'Access-Control-Request-Method: 요청메서드'
처음에는 위 사진처럼 403과 Invalid CORS request를 응답으로 받았다.
코드 수정 이후에는 아래와 같이 200으로 정상적으로 응답을 받은것을 확인할 수 있다.
두번째 방법은 포스트맨을 사용하는것이다.
curl을 사용하는 방법은 코드를 적어야하는 내용이 많아서 포스트맨을 이용한 방법이 더 직관적이었다.
요청을 보낼때 헤더에 Origin 값으로 요청하는 주소를 적어주면 테스트가 가능하다.
회원가입 기능을 테스트해보았는데 CORS 설정 전에는 Invalid CORS request가 응답으로 왔다.
이후에 CORS 설정을 하고나니 정상적으로 응답이 오는것을 확인할 수 있었다.
아무래도 해당 부분은 실제로 프로젝트 작업한것을 확인해볼 수 있는 중요한 부분이다보니 더 신경쓰이는 부분이었다.
다들 열심히 작업했는데 이 설정때문에 테스트도 못해보면 안되니까..!🥲
일단 로컬에서는 되는걸로 확인을 했는데, 부디 내일 프론트분들이랑 테스트할때도 잘 동작했으면 좋겠다!
+ 추가 (6.23)
기대했던것과 달리 ngork으로 서버를 열어서 프론트 분들께 공유드렸는데 CORS 오류가 계속해서 발생했다.
응답 헤더에 "Access-Control-Allow-Origin"이 없다는 오류였다.
코드를 엄청 뜯어보고 구글링도 많이 했는데 결국 두가지 조치를 통해 해결될 수 있었다.
1) 허용 메서드에 OPTIONS 추가.
해당 오류는 preflight 요청에서 발생하는 오류였다.
분명히 모든 Origin을 허용했는데 작동이 되지 않아서 확인해보니 preflight요청은 OPTIONS 메서드를 통해서 요청된다고 한다.
따라서 CORS 허용 메서드에 OPTIONS를 추가해주어야한다.
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PATCH", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("Authorization");
}
2) 프론쪽에서 요청 전달시 헤더 추가
이런 저런 조치를 하다가 도저히 안돼서 메서드도 모든 메서드를 허용해서 테스트를 해본적이 있다.
그렇게 조치를 했는데도 해결이 안돼서 어디서부터 손을 봐야되나 고민하고 있었는데
ngork 자체에서 발생하는 문제였다.
Get 요청에 대해 소개 페이지로 강제로 이동하는이슈가 있어서 프론트에서 API 호출시 아래 헤더를 추가해주어야했다.
* headers:
key: ngrok-skip-browser-warning
value: true
두가지 조치를 하고나니 요청과 응답이 정상적으로 주고받아지는것을 확인할 수 있었다.
-> 요청이 정상적으로 들어오고있다.
preflight 요청으로 인해 OPTIONS 요청이 먼저 오는것을 확인할 수 있다.
(JSON 형태로 자료를 주고받고 있으며 여러 조건으로 인해
Simple Request가 아니라서 preflight 요청을 보내게 된다.)
참고자료
Spring Boot CORS 해결하는법(ngrok CORS도 해결)
[Spring Boot] CORS를 해결하는 3가지 방법
'부트캠프 개발일기 > Pre-Project' 카테고리의 다른 글
92일차: Pre-Project Day 12(배포: EC2, S3, RDS, gradle) (0) | 2023.06.26 |
---|---|
91일차: Pre-Project Day 11 (Mapper/MapStruct 생성안됨) (0) | 2023.06.23 |
90일차: Pre-Project Day 10-1 (인증 에러 처리: AuthenticationFailureHandler, AuthenticationEntryPoint) (0) | 2023.06.22 |
89일차: Pre-Project Day 9 (HandlerInterceptor, JWT 정보 가져오기) (0) | 2023.06.21 |
88일차: Pre-Project Day 8-2 (JWT 로그아웃, Redis) (2) | 2023.06.20 |