📌Same-Origin Policy
- 스크립트 코드는 어디 서버에서 왔는지 출처가 있다
- 혼자 개발하면 localhost 서버 => live server extension이나 npm run start한 리액트 서버 키면 localhost(내컴퓨터)가 서버가 되어 스크립트 코드가 내 브라우저에 다운로드 되고 실행 됨
- 구글에 접속하면 google 도메인 서버 => google에 접속하면 google 웹서버로 부터 온 스크립트 코드가 내 브라우저에 다운로드 되고 실행 됨
- 스크립트 코드가 브라우저에서 실행될 때, 스크립트의 출처(스크립트를 가져온 서버)와 요청할 출처(요청한 서버)가 다르면 SOP정책에 위반 된다
- 즉, 동일한 출처에 대해서만 리소스 접근을 허용하는 정책
❓출처란?
- 브라우저마다 다를 수 있지만 대부분
protocol(scheme) + host + port
의 일치여부를 판단합니다.

- 동일 출처 비교 예시

📖CSRF 공격 예시(CSRF 토큰으로 방어 필요)
- 해커는 악성 웹사이트를 만듭니다, 이때 이 웹사이트의 코드에 다음과 같은 부분이 있습니다.
<form action="http://facebook.com/api/content" method="post">
<input type="hidden" name="body" value="나는 바보다." />
<input type="submit" value="Click Me"/>
</form>
- 유저는 페이스북에 로그인이 되어있는 상태여서 브라우저에 로그인 토큰 또는 세션ID를 보유하고 있습니다
- 유저는 이 웹사이트에 접속하여 저
form
태그를 제출하게 됩니다
- 페이스북은 유저가 로그인된 상태에서 "나는 바보다."라는 글을 써돌라는 요청을 받습니다
📌Cross Origin Resource Sharing
- 서로다른 출처간에도 요청과 응답을 일부분 허용하는 정책
- 즉, SOP를 위반해도 CORS을 지키면 허용하겠다
📖기본 로직
- 웹에서 다른 출처로 리소스를 요청할 때, HTTP 프로토콜의 Origin이라는 필드에 요청을 보내는 출처를 담는다
- 서버에서는 응답시 HTTP 프로토콜의 Access-Control-Allow-Origin이라는 필드에 값을 담아 응답한다
- 브라우저에서는 본래의 Origin과 Access-Control-Allow-Origin를 비교하여 이 응답이 유효한지 판단합니다
📖Preflight Request
- 예비 요청과, 본 요청을 나누어서 통신
- 요청 메소드가
GET, POST
가 아닌 OPTIONS

- 예비 요청
- Origin 헤더에 자신의 출처를 넣는다.
- Access-Control-Request-Method 헤더에 실제 요청에 사용할 메소드를 설정
- Access-Control-Request-Headers 헤더에 실제 요청에 사용할 헤더들을 설정
- 예비 요청 응답
- Access-Control-Allow-Origin 헤더에 허용되는 Origin들의 목록을 설정한다.
- Access-Control-Allow-Methods 헤더에 허용되는 메소드들의 목록을 설정한다.
- Access-Control-Allow-Headers 헤더에 허용되는 헤더들의 목록을 설정한다.
- Access-Control-Max-Age 헤더에 해당 예비 요청이 브라우저에 캐시 될 수 있는 시간을 초 단위로 설정한다.
- 브라우저는 보낸 요청과 응답해준 정책을 비교하여 판단
- 캐시되어 있는 동안은 예비 요청없이 캐시 응답 사용
📖Simple Request
- 예비 요청 생략 후 바로 본 요청

- 예비 요청을 생략할 수 있는 조건(simple request가 될 수 있는 조건)
- 요청 메소드가
GET, HEAD, POST
중 하나
Accept
, Accept-Language
, Content-Language
, Content-Type
, DPR
, Downlink
, Save-Data
, Viewport-Width
, Width
를 제외한 헤더를 사용하면 안된다.
Content-Type
헤더가 application/x-www-form-urlencoded
, multipart/form-data
, text/plain
중 하나
- 대부분 HTTP API 요청은
text/xml
이나 application/json
으로 통신하기 때문에 3번째 Content-Type
이 위반되기 때문에, 대부분의 API 요청은 그냥 예비 요청(preflight)으로 이루어진다 라고 이해
📖Credentialed Request
- 인증된 요청은 클라이언트에서 서버에게 자격 인증 정보(Credential)를 실어 요청할때 사용되는 요청
- 자격 인증 정보란 세션 ID가 저장되어있는 쿠키(Cookie) 혹은 Authorization 헤더에 설정하는 토큰 값

- 예비 요청도 원래 있어야 하나 생략함
- 요청
- 브라우저의 쿠키와 같은 인증과 관련된 데이터를 함부로 요청 데이터에 담지 않도록 되어있다, 이걸 담도록 하기 위해
credentials
옵션을 설정 해줘야함
- 응답 : 서버도 마찬가지로 이러한 인증된 요청에 대해 일반적인 CORS 요청과는 다르게 대응
- 응답 헤더의 Access-Control-Allow-Credentials 항목을 true로 설정해야 한다.
- 응답 헤더의 Access-Control-Allow-Origin 의 값에 와일드카드 문자("*")는 사용할 수 없다.
- 응답 헤더의 Access-Control-Allow-Methods 의 값에 와일드카드 문자("*")는 사용할 수 없다.
- 응답 헤더의 Access-Control-Allow-Headers 의 값에 와일드카드 문자("*")는 사용할 수 없다.
- 즉, 전부를 통칭하는 별표가 아닌 구체적인 값들을 넣어야함
📌CORS에러 해결 방법
📖백엔드에서 해결
- 서버에서 Access-Control-Allow-Origin 헤더 세팅 : 백엔드 코드(spring, express.js 또는 웹서버인 apache, Nginx 또는 WAS인 Tomcat에서도 세팅 가능)
📖프론트에서 해결
- 프록시 서버 사용 및 직접 구축
- 프록시(Proxy) : 클라이언트와 서버 사이의 중계 대리점이라고 보면 된다.
- 모든 출처를 허용한 서버 대리점을 사용

- http-proxy-middleware 라이브러리 사용 등