gdg 프로젝트 도중, 백엔드에서 제공해준 서버환경에 접속하여, api를 통해 이메일 인증을 테스트 해 보았다. 내 컴퓨터는 window인데, 이메일 인증이 제대로 실행되지 않고, CORS 에러가 발생하였다. 하지만, 다른 팀원들 MAC북에서는 제대로 작동이 이루어졌다. 이 에러가 프론트와 벡이 모두 알아야할 중요한 에러 상황이라고 하고, 전에 프로젝트 진행에서도 이 에러가 발생한 적이 있다.
따라서 그 에러가 뭔지, 어떻게 해결해야하는 지 공부해보려고 한다.
: 한 도메인이 다른 도메인을 가진 리소스에 액세스 할 수 있게 하는 보안 메커니즘
-> 클라이언트에서 도메인이 다른 서버에서 제공하는 api사용하는 일이 많아짐.
-> 동일한 도메인 간 요청만 할 수 없어졌음
-> 요청 방식에 따라 다른 cors 에러가 발생
: Cross-Origin 정책을 지원
-> 다른 리소스에 접근하는 것이 가능
: Same-Origin 정책
ex)
---> 즉, CORS는 다른 도메인의 리소스를 나의 도메인으로 가져오기 위해 요청하는 것이다. 그때 요청하는 방식이 자바스크립트를 통한 것이라면, SAME-ORIGIN 정책을 따른다면, 오류가 난다.
: 요청 방식에 따라 Same Origin / Cross Origin 정책을 따르게 되는데, 정책을 위반하는 행동을 하게 되면 에러가 발생한다. 그렇다면 각각 정책이 어떤 내용인가? 무엇인가?
Origin : Protocol + Host + Port
-> 여기서는 위의 3가지만 기억하면 된다. 위 3가지가 같으면 동일한 출처로 판단 하나라도 다르면, 다른 출처로 판단하여 차단함
: 동일한 출처에서만 리소스를 공유할 수 있다.
-> 다른 서버 (Cross-Origin)에 있는 이미지나 유튜브 영상 같은 리소스는 상호작용이 불가능하다.
: 해커를 통해 개인정보가 유출되는 것과 같은 악의적인 경우를 방지하기 위해
: 출처 비교와 차단은 브라우저에서 진행
-> 서버에 요청 시, 서버는 말끔히 응답을 해주고, 브라우저는 이를 분석해서 동일 출처가 아니면 CORS 오류를 발생시킨다.
즉, 서버에서는 정상적으로 응답했다고 하지만 브라우저 단에서는 받을 수 없으므로 문제가 발생한다.
-> 브라우저가 판단하는 말은, 브라우저를 통하지 않고 서버 간에 통신할 때에는 정책이 적용되지 않는다. 즉, 서버에서 다른 서버로 API요청 시에는 CORS 오류로부터 자유로워진다.
하지만 인터넷은 열린 공간이고, 다른 출처에서 리소스를 가져와서 사용하는 것은 매우 흔한 일이라 무턱대고 막을 수는 없다. 따라서, 다른 리소스의 요청이더라도 CORS의 조항에 해당하면 다른 리소스 간 공유를 허용하도록 하였다.
: 다른 출처의 리소스 공유에 대한 허용/비허용 정책
-> 즉, SOP 정책을 위반해도 CORS 정책을 따르면 다른 출처의 리소스라도 허용
---> 사실 cors 동작 방식의 위의 방식 말고도 총 3가지의 시나리오가 존재한다.
: 브라우저가 요청을 보낼 때, 한 번에 보내지 않고 예비요청을 보내 서버와 잘 통신되는지 확인 후 본 요청을 보낸다.
: 예비 요청을 생략하고 바로 서버에 직행으로 본 요청
-> 서버가 이에 대한 응답의 헤더에 Access-Control-Allow-Origin 헤더를 보내주면 브라우저가 CORS정책 위반 여부를 검사
-> 3가지 경우를 만족해야 함
: 클라이언트에서 서버에게 자격 인증 정보를 실어 요청할 때 사용되는 요청
--> 이 부분에 대해서는 추후 필요할 때 더 깊게 공부해도록 하겠다.
: 서버에서 Access-Control-Allow-Origin 헤더에 허용할 출처를 기재해서 클라이언트에 응답
-> 각 서버의 문법에 맞게 HTTP 헤더를 추가해주면 된다.
: Allow CORS: Access-Control-Allow-Origin' 크롬 확장 프로그램을을 설치
-> 활성화 시키면, 로컬 환경에서 API 테스트 시, cors 문제를 해결할 수 있다.
: gdg 프로젝트에서 코디네터의 프로필 사진, 나이, 키, 이름 등의 정보를 백에 요청하는 과정에서 아래와 같은 오류가 계속해서 발생하는 것이다.
일단 내가 수행해본 해결 방법은 아래와 같다. 일단 내가 위에 작성했던, cors 를 공부하며 학습했던 해결 방법을 직접 적용시켜 보고자 하였다.
: 크롬 내에는 cors 문제를 해결해주기 위한 확장 프로그램이 존재한다. 하지만 문제는 해결되지 않았다. 이때부턴 갑자기 cors에러가 아닌 404 에러가 뜨는 것이다.
: Access-Control-Allow-Origin 헤더에 허용할 출처를 기재하여 보았다. 내가 요청하는 origin과 같은 지도 확인하였다. 그런데, 모두를 허용을 해주었고, origin이 같음에도 전혀 오류가 해결되지 않았다. 겉으로 보기에는 문제가 없는데, 해결되지 않는 이 문제가 답답하였다. 한 2틀 내내 이 문제로 머리를 싸맸던 것 같다.
-> 심지어, 다른 팀원들의 컴퓨터에서는 잘 수행이 되는데, 내 컴퓨터에서만 위와 같은 문제가 발생하는 것이다. 무언가 문제가 있다....라는 생각이 들었는데, 그 문제를 찾아내지는 못했다. 내가 아는 것이 부족해서 (특히 네트워크 분야. ) 쉽사리 찾을 수 없었을 지도 모른다. 그래서 위와 같이 cors 에 대해서도 학습을 해본 것이다.
-> 도통 문제가 해결이 되지 않아......
: 이 프로젝트와는 전혀 연관이 없지만, 마지막 유일한 희망으로 부트캠프 멘토님께 이 에러에 대해 아래와 같이 말씀 드렸다.
<에러 사항>
"도커를 이용해서 백에서 프론트 팀원들에게 서버 환경을 제공해서 API 테스트를 하는 도중에 문제가 생깁니다. 일단, 저희 팀의 문제점을 말씀드리겠습니다.(docker-compose로 spring jar파일, mariaDB, Redis 컨테이너를 만들었습니다)
위에서 만든 도커 컨테이너로 다른 프론트 팀원은 정상적으로 작동하는데 제 컴퓨터에서만 프론트 팀원은 CORS 오류가 발생했습니다. 백엔드 측에서 @CrossOrigin을 이용해서 localhost:3000을 허용했는데 왜 이런 오류가 발생하는지 궁금합니다.
위에서 발견한 오류는 임시 방편으로 크롬 확장 프로그램(CORS)를 이용하여 해결하였지만, 제대로 된 요청 URL을 적었는데 404 오류가 발생했습니다. 일단 동일한 axios 코드로 다른 프론트 팀원은 정상 작동하였는데 왜 저에게만 404 오류가 발생하는지 궁금합니다. "
<원인>
<해결 방법>
1. localhost로 변경
: 위의 밑줄 친 부분을 127.0.0.1:8080 에서 localhost:8080로 변경
2. 프로젝트 파일을 터미널에서 열기 클릭
netstat -a -o
: 3306 포트 차지 되어있는 거 확인 후 사용 중지
taskkill /f /pid 6612
: 해당 포트의 pid 찾아서 사용 중지. workbench 완전히 삭제
axios.defaults.withCredentials = true;
: axios 함수 위에 다음과 같이 작성해준다.
-> 쿠키를 허용해주는 코드이다.
: port가 차지되어있었기 때문이다. 백엔드 코드가 네트워크가 문제였던 것이 아니다.
: 둘은 같은 의미라고 알고 있는데, 어떤 차이가 있어서 바꿔주었더니 실행이 되는지? 단지 전자는 IP 주소 vs. 후자는 호스트 이름 아닌가? 이 이유는 아직도 잘 모르겠다.. 바꿨더니 왜 실행이 되었는지...
이것과는 무관하게 그냥 port 가 문제였을지도 모르겠다.
---> 어쨌튼 위와 같은 문제를 드디어, 해결해서 너무 기뻤다. 이 맛에 코딩을 하는 구나 싶으며, 2일 간의 고뇌가 행복으로 순식간에 바뀌었다.
cors 문제가 발생하면, axios, 백엔드 header allow origin 확인 해보자. 나의 컴퓨터에서만 안되는 것이라면 port와 같은 내부적인 부분을 살펴보자
: cors 라는 것은 다른 도메인의 리소스를 가져오는 것에 대한 정책이다. 이 정책이 위반되면 오류가 나게 되는 것이다. 일단, 그에 앞서 sop라는 것이 있다. 이는 같은 도메인의 리소스만 가지고 있다는 정책이다. 요청 방식에 따라 sop정책을 따르는 것들이 있는데, (API 요청) 하지만, 리소스를 공유하는 게 흔한 현대 인터넷 세계에서 다른 도메인에서 리소스를 가져오는 것을 막는 것은 좋지 않다. 그래서 허용한 출처에 대해서는 다른 출처라도 리소스를 가져올 수 있게 CORS의 조항에 맞는 경우에는 허용해주는 것이다. 즉, 클라이언트의 요청 출처와 서버에서 응답으로 헤더에 써서 돌려주는 허용가능한 출처가 일치하면, 다른 출처여도 리소스를 받아올 수 있는 것이다.
하지만, 이 2개가 일치하지 않으면 CORS 정책을 위반하는 것이므로 CORS 에러가 난다. 이를 해결해주기 위해서는, 서버 측에서 모든 출처의 접근을 허용할 수도 있다. (이 부분은 악의의 보안 문제가 발생할 수 있다.) 또는 서버 측에서 임의로 허용 출처를 헤더에서 변경해줄 수도 있다.
--> 즉, 같은 도메인에서만 리소스를 받아와야하는 SOP정책을 따르더라도, CORS 정책을 충족한다면 (클라이언트의 출처와 서버의 헤더에 있는 허용 출처가 같은 경우) 다른 출처의 리소스를 가져올 수 있다는 것. 그 2개가 다를 경우에는 CORS 문제가 발생한다는 것.