서론
현재 React와 SpringBoot를 사용하여 프론트엔드와 백엔드 개발을 하고 있다.
Jwt 토큰( Access Token, Refresh Token)을 사용하여 인증하고 있고, Interceptor를 사용하여 요청이 Controller 단에 도착하기 전에 인증을 한다. 그런데 요청을 보내면 react의 url인 localhost:3000을 allow 해주었는데도 CORS 에러가 발생한다. 이유가 뭘까?
문제 상황
CORS 에러 발생
위와 같이 React(localhost:3000) 에서 SpringBoot(localhost:8080)로 요청을 보낼 때 CORS 에러가 발생한다.
백엔드 로그 확인
서버에서는 JwtInterceptor에서 에러가 발생했다고 한다.
JwtInterceptor 코드
JwtInterceptor의 preHandle을 확인해보니 request.getHeader에서 문제가 발생한 것 같았다.
여기서 알 수 있는 것은 Authorization 헤더가 없다는 것이었다. 그래서 요청을 확인해 보았다.
요청 확인
분명 요청에 Authorization 헤더에 Access Token 값을 넣어서 요청이 갔다. 근데 왜 Authorization 헤더가 없다는 걸까?
문제 해결
preflight 요청
네트워크 탭을 잘 확인해 보면 2개의 요청이 있다. 하나는 본 요청, 하나는 preflight 요청이다.
preflight에 대한 설명은 아래의 글을 참고하면 될 듯하다.
preflight 요청을 눌러보면 앞으로 보낼 요청을 알려준다. (나 이렇게 요청 보낼거야~ 라는 뜻)
Access-Control-Request-Headers는 authorization 헤더를 포함할 것이라는 뜻이고 Access-Controle-Request-Method는 POST로 보내겠다는 뜻이다.
preflight 요청 시에는 헤더를 포함하지 않기 때문에, request.getHeader를 할 때 Authorization 헤더를 찾을 수 없었던 것이다.
해결(?)
해결법을 찾아보니, 위처럼 OPTIONS 메서드를 허용해 줘서 preflight 시에 요청을 허용해 주는 방법이 많이 나왔다.
근데 과연 저렇게 허용하는게 맞을까? preflight 때문에 OPTIONS 메서드 자체를 허용해 주는 것이 좋아 보이진 않는다.
해결!
찾아보니 CorsUtils에 isPreFlightRequest라는 메서드가 있었다. 이걸 사용하면 preflight인 경우에만 요청을 통과시킬 수 있게 코드를 작성할 수 있다.
마무리
사실 글의 첫 번째 사진인 브라우저에서 발생한 에러 메시지를 보면, preflight가 통과 못했다고 친절히 알려준다ㅎ..
CORS 에러가 왜 뜨지? 싶어서 CORS라는 글자에만 집중한 내 실수다. 앞으로는 에러 코드를 좀 꼼꼼히 읽어보는 습관을 가지자!
'BE > Spring Boot' 카테고리의 다른 글
@Cacheable로 API 성능 개선하기 (with Redis, Scheduler, AOP) (0) | 2023.11.11 |
---|---|
Open ID Connect 으로 구글 로그인 구현하기 (feat. SpringBoot) (1) | 2023.11.02 |
로그인 시 id가 없을 때 status code는 200? 404? (0) | 2023.03.31 |
Spring Boot + Docker로 배포하기 (0) | 2022.07.24 |
REST API와 flutter sdk를 이용한 카카오 로그인의 차이점 (0) | 2022.07.07 |