사실 총정리까진 아님 ㅋㅋ;;ㅎㅎ;;ㅈㅅ;
😉CORS의 기본적인 이해
https://xionwcfm.tistory.com/235
이전에 나름대로 잘 정리해둔 포스트가 있으니
자세하게 알아보고 싶으신 분은 이 포스트를 읽어주시기 바랍니다.
이미 CORS에 대해 개념적으로 알고계신 분들 역시 지나치셔도 좋습니다.
간단하게 CORS를 이야기해보면 Cross Origin Resource Sharing
한국어로 바꿔 교차 출처 리소스 공유 정책입니다.
보안적인 문제로 같은 출처(주소)를 가진 애들끼리만 리소스를 주고받을 수 있는
SOP라는 정책을 우회하기 위한 정책이라고 할 수 있습니다.
특징적인 부분은 다음과 같은데 이를 모르고 있으면 조금 헤매게 됩니다.
1. CORS 정책은 기본적으로 브라우저에서 수행되는 규약입니다.
2. CORS 정책에서 프론트엔드 코드는 대체로 문제가 없습니다.
3. CORS 정책을 수행하기 위해 브라우저는 우리의 요청 이전에 Preflight 요청을 보냅니다.
이 부분을 기억하고 넘어가봅시다.
😊CORS 이 에러는 뭐에요?
Access to fetch at ‘무슨무슨사이트’ from origin ‘대충 내 주소’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
CORS policy에 의해 내 요청이 막혔다는 의미의 에러입니다.
읽어보면 여기서 Access-Control-Allow-Origin Header에 대한 내용이 있는것을 알 수 있습니다.
이는 서버측의 응답 헤더에 Access-Control-Allow-Origin 속성에 적절한 값을 담아 응답하지 않았다는 의미입니다.
즉 요청 자체는 무죄입니다.
그럼 어떻게 해결할 수 있을까요?
Access-Control-Allow-Origin 과 같이 CORS에 관련된 헤더값들이 존재합니다.
이 값들을 적절히 세팅해주면 해결할 수 있어요
다만 주의해야할 점은 간혹 PUT, DELETE, POST, GET 등 REST API의 메서드들은 나름대로 등록을 해주었는데
오류가 발생하는 경우가 있습니다.
이는 브라우저가 CORS 체킹을 위해 보내는 프리플라이트 요청과 큰 연관이 있는데
기본적인 흐름은
브라우저의 프리플라이트 요청 -> 서버의 적절한 헤더가 담긴 응답 -> 본 요청 -> 서버의 응답
순서로 흘러가게 됩니다.
여기서 프리플라이트 요청의 메서드는 OPTION으로 간다는 점 기억하고 이를 처리해주어야합니다.
😶로그인 구현 하려는데 왜 CORS에러가 또 떠요?
로그인 등과 같이 액세스 토큰 등 보안과 밀접한 연관이 있는 리소스를 주고받아야하는 경우가 있습니다.
그러한 경우에는 단순한 CORS 요청으로는 불가능합니다.
인증된 요청이라고 부르는 방식으로 구현해야합니다.
이부분은 클라이언트 단에서도 약간의 책임이 존재합니다.
const response = await fetch(`${BASE_URL}/api/users/login`, {
method: 'POST',
body: JSON.stringify(loginData),
credentials: 'include',
});
fetch 함수의 경우 위와같이 credentials 옵션을 include 로 설정해주어야합니다.
참고로 fetch함수의 credentials 옵션의 디폴트 값은 same-origin입니다.
axios를 사용하고 있다면
axios.post('https://example.com:1234/users/login', {
profile: { username: username, password: password }
}, {
withCredentials: true // 클라이언트와 서버가 통신할때 쿠키와 같은 인증 정보 값을 공유하겠다는 설정
})
위와 같이 withCredentials 옵션의 불리언값을 true로 설정해주어야합니다.
다만 이 인증된 요청은 서버측에서 처리해주는 것이 조금 까다로울 수 있습니다.
인증된 요청을 위해 서버측에서는
1. Access-Control-Allow-Origin 헤더의 값이 * 와일드카드이면 안됩니다.
2. Access-Control-Allow-Credentials 헤더에 적절한 값이 설정되어있어야합니다.
이러한 조건들이 만족되어야합니다.
😐다 한줄 알았는데 415 에러는 뭐에요?
415에러는 지원되지 않는 미디어 타입에 대한 에러입니다.
이는 클라이언트 측에 문제가 있을 확률이 높습니다.
const response = await fetch(`${BASE_URL}/api/users/login`, {
method: 'POST',
body: JSON.stringify(loginData),
credentials: 'include',
headers: {
'Content-Type': 'application/json;charset=utf-8',
},
});
이러한 형태로 헤더의 Content-Type을 application/json으로 명시해주면 일반적인 경우 해결됩니다.
이유는 찾아보세요
😙403에러는 먼가여..
403에러는 서버에 요청이 전달되었지만 권한 때문에 거절당했다는 상태코드입니다.
서버에 요청이 전달되기는 하였지만 서버가 클라이언트 접근을 거부할 때 반환되는 상태코드에요
이런 경우 일반적으로 요청 body에 담긴 데이터가 서버에서 요구하는 리퀘스트 바디와 일치하는지
토큰이 필요한 api의 경우 유효한 토큰을 잘 담아 보내고있는지 등을
한번 체크해보시는 것을 추천드립니다.
😎405에러는 뭔가여..
405에러는 서버가 요청 메서드를 알고는 있지만 리소스가 이 메서드를 지원하지 않는 것을 뜻합니다.
주로 서버측의 응답 바디에 아무것도 담겨있지 않은데
클라이언트 측에서 바디를 파싱하려고 시도할 때 일어나는 에러입니다.
🙄마치며
프리프로젝트 / 메인프로젝트 둘 다 로그인 회원가입 로직을 맡으면서
CORS 에러에 더 익숙해진 것 같습니다.
사실 클라이언트 측에선 딱히 해줄 게 없는데 정확히 어디가 문제인지 모르면
이게 코드가 서버에서 잘못된건지 클라이언트에서 잘못된건지 감이 안잡혀서 힘든 것 같아요
그래도 이 글이 미약하게나마 도움이 되었으면 좋겠습니다
'frontend' 카테고리의 다른 글
[radix] popover when hover trigger (0) | 2023.08.09 |
---|---|
Barrel export 패턴으로 깔끔한 import 관리 (0) | 2023.08.06 |
Parsing error: ESLint was configured to run on (0) | 2023.07.13 |
nextjs 13 typescript 환경에서 eslint airbnb 에 husky, gitmoji, lint-staged까지? (0) | 2023.07.11 |
ts react vite mui 보일러플레이트 만들기 (0) | 2023.07.10 |