예시 ) https://www.domain.com:3000 출처에 대한 여러 URL의 동일 출처 비교
URL Same-Origin? 이유 https://www.domain.com:3000/about O 프로토콜, 호스트, 포트 번호 동일 https://www.domain.com:3000/about?username=inpa O 프로토콜, 호스트, 포트 번호 동일 http://www.domain.com:3000 X 프로토콜 다름 (http ≠ https) https://www.another.co.kr:3000 X 호스트 다름 https://www.domain.com:8888 X 포트 번호 다름 https://www.domain.com X 포트 번호 다름 (80 ≠ 3000)
기본적으로 브라우저는 토큰이나 쿠키 등과 같이 사용자의 정보와 관련된 데이터를 저장하는데, 만약 해커가 CSRF, XSS 등의 방법으로 해커가 심어 놓은 스크립트가 실행되어 인증 요청을 보내면, 그로 인해 얻은 개인 정보를 해커의 서버로 보내는 등의 문제가 발생할 수 있다.
이를 막기 위해 등장한 것이 동일 출처 정책(SOP)이다.
CSRF (Cross-Site Request Forgery, 크로스 사이트 요청 위조)
공격자가 이용자가 인증된 상태에서 웹 애플리케이션에 의해 수행되는 비인가된 명령을 실행할 수 있게 하는 공격. 이를 위해서 공격자는 이용자가 웹 애플리케이션에 요청하는 HTTP 요청을 위조하여, 이용자의 권한으로 원하지 않는 동작을 수행하도록 유도한다.
XSS (Cross-Site Scripting, 크로스 사이트 스크립팅)
공격자가 웹 페이지에 악성 스크립트를 삽입하여, 이용자 브라우저에서 실행되게 하는 공격. 이를 통해 공격자는 이용자의 개인 정보를 탈취하거나, 이용자의 브라우저를 제어하여 다른 공격을 수행할 수 있다.
출처를 비교하는 로직은 서버에 구현된 스펙이 아니라 브라우저에 구현된 스펙이다.

서버는 리소스 요청에 대한 응답을 제대로 주지만 브라우저가 응답을 분석해서 동일 출처가 아니면 오류를 발생시킨다.(서버가 Access-Control-Allow-Origin 헤더에 허용할 출처를 담지 않고 응답을 전달한 경우)
즉, 응답 데이터는 정상이지만 브라우저 단에서 받을 수 없도록 차단한 것이다.
브라우저가 정책으로 차단을 한다는 말은, 브라우저를 통하지 않고 서버 간에 통신을 할때는 정책이 적용되지 않는다는 말과 같다.
즉, 클라이언트 단 코드에서 API 요청을 하는게 아니라, 서버 단 코드에서 다른 출처의 서버로 API 요청을 하면 CORS 에러로부터 자유로워 진다. 그래서 이를 이용한 프록시(Proxy) 서버라는 것이 있다.
클라이언트는 HTTP Request 헤더에 Origin을 담아서 서버에게 Request 전달Origin: http://localhost:3000
서버는 HTTP Response 헤더에 Access-Control-Allow-Origin을 담아 클라이언트에게 Response 전달Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Origin이라는 필드를 추가하고, 값으로 '이 리소스를 접근하는 것이 허용된 출처 url'을 전달한다.클라이언트에서 Origin과 서버가 보내준 Access-Control-Allow-Origin을 비교한다.
Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교해본 후 차단할지 말지를 결정한다.주로 사용하는 방식으로, 본 요청을 보내기 전에 브라우저 스스로 이 요청이 안전한지 확인하기 위해 보내는 사전 요청이다. 이 때, OPTIONS 메서드를 사용한다.

Preflight request와 동작 방식은 같고 사전 요청의 유무만 다르다. 단순 요청은 사전 요청 없이 그냥 바로 서버에 요청을 보낸다. 하지만 아무때나 단순 요청을 할 수 있는 것은 아니다. 특정 조건을 만족하는 경우에만 사전 요청을 생략할 수 있고, 사실상 조건이 까다로워서 충족하기 어렵다.
좀 더 보안을 강화하고 싶을 때 사용하는 방식으로, 요청 헤더에 인증 정보를 담아 보내는 요청이다. 출처가 다를 경우에는 별도의 설정을 하지 않으면 민감한 정보이기 때문에 쿠키를 보낼 수 없다. 이 경우에는 프론트와 서버 양측 모두 CORS 설정이 필요하다.
withCredentials : true를 넣어줘야 한다.Access-Control-Allow-Credentials : true를 넣어줘야 한다.Access-Control-Allow-Origin을 설정할 때, 모든 출처를 허용한다는 뜻의 와일드카드(*)로 설정하면 에러가 발생한다. 인증 정보를 다루는 만큼 출처를 정확하게 설정해주어야 한다.서버에서 모든 클라이언트에 요청에 대한 cross-origin HTTP 요청을 허가하는 Access-Control-Allow-Origin: *를 헤더에 추가할 수 있다.
하지만 이렇게 설정하면 모든 출처에 대한 요청을 허용하는 것이기 때문에 보안에 취약 할 수 있다.(심각한 보안 이슈를 초래할 수 있음) 따라서 가급적이면 출처를 명시하는 것이 좋다.
프록시 서버는 중간에서 헤더를 추가하거나 요청을 허용/거부하는 역할을 할 수 있다. 따라서 응답을 주고 받을 때 프록시 서버에서 Access-Control-Allow-Origin: * 을 헤더를 담아 응답해 주면 된다.
프론트엔드에서 webpack-dev-server proxy 기능을 사용하면 서버 쪽 코드를 수정하지 않고 해결 할 수 있다.

webpack-dev-server의 프록시를 사용하면, 브라우저에서 API를 요청 할 때 백엔드 서버에 직접적으로 요청을 하지 않고 현재 개발 서버의 주소로 요청을 하게 된다. 해당 요청을 받아 그대로 백엔드 서버로 전달, 백엔드 서버에서 응답한 내용을 다시 브라우저쪽으로 반환한다.
참고)
https://velog.io/@jesop/SOP%EC%99%80-CORS
https://yoo11052.tistory.com/139
https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F
https://velog.io/@mmm2815/WEB-Server-SOP%EC%99%80-CORS