
Cross Origin Resource Sharing 크로스 오리진 리소스 공유는
💡
한 도메인에서 로드되어 다른 도메인에 있는 리소스와 상호 작용하는 클라이언트 웹 애플리케이션에 대한 방법을 정의! 즉,
출처가 다른 서버간 리소스 공유를 허용하는 것입니다.
API를 자주 사용하는 현재의 프론트엔드 개발자에게는 다른 서버로부터 리소스를 받아오는 작업이 흔하지만, 예전에는 요청을 하는 도메인과 요청을 받는 도메인이 다르다면 이는 웹브라우저 정책을 위반하게 되어 작업이 쉽지 않았습니다. 이를 현재로 와서 허용하는 정책이 CORS 입니다.
❓
그냥 처음부터 허용을 하면 안됐던걸까요? 지금은 API 요청이 흔한 트랜드인데 이제는 정책 없이 허용하면 안되나요?
예전에 아직 보안 정책이 생소했던 때에 크로스 사이트 요청 위조(CSRF) 문제가 발생했습니다. 이는 브라우저에서 사용자의 토큰 등의 정보가 쿠키로 저장되어 있는데 이를 악용한 사례입니다.
예를 들어 브라우저에서 ‘착한닷컴’ 이라는 페이지에 로그인 하여 여러 작업을 사용하던 중, 사용자를 속여 새로운 브라우저 탭으로 ‘나쁜닷컴’ 이라는 사이트를 로드하게 했다고 가정합니다. 그러면 이 ‘나쁜닷컴’ 사이트에서는 브라우저에 저장되어있던 사용자의 정보를 받아서 사용하게 되며, 사용자를 가장하여 ‘착한닷컴’의 엑세스 권한을 받게 됩니다. 사용자가 아님에도 사용자 정보를 도용하는 거죠.
이를 방지하는 동일 오리진 정책이 먼저 등장합니다.
이름 그대로 동일한 오리진의 리소스로만 요청을 보낼 수 있도록 하는 것입니다.
여기서 오리진 (Origin) 이란 프로토콜, 포트, 그리고 도메인을 포함하는 출처를 의미합니다.

SOP를 따라 아래의 URL을 확인해보자면
SOP로 인해, 유용한 URL임에도 실제로는 정책에 위반되는 origin이 많다는 것이 보입니다.
그리하여 여기서 SOP를 확장 시킨 것이 CORS입니다.
크로스 오리진 요청을 할 때 요청-응답 프로세스는 다음과 같습니다.

서버에서 크로스 오리진 액세스를 허용하지 않는 경우에는 오류 메시지로 응답합니다.
💡
사전요청이란, 본격적인 cross origin (교차 출처) HTTP 요청 전에 서버 측에서 요청의 메서드와 헤더를 인식하고 있는지에 대한 요청입니다. (Access-Control-Requestion-Method, Origin, Access-Control-Request-Headers)
HTTP 요청 메서드는 클라이언트가 서버에 수행하고자 하는 작업으로 GET, POST, PUT, DELETE 등이 있습니다.
CORS 상호 작용에서는 브라우저 요청과 엑세스 제어 헤더를 GET을 통해 요청합니다. 일반적으로 GET을 통한 요청은 위험이 낮아 확인 작업이 따로 필요하지 않습니다.
하지만!
복잡한 경우 서버 확인이 필요합니다. 데이터를 삭제하거나 수정하는 일 등이 이에 해당합니다. 아래와 같은 경우가 있습니다.
OPTIONS 요청 전송
클라이언트(브라우저)가 서버로 사전 요청을 보내기 위해 HTTP OPTIONS 요청을 보냅니다. 이 요청에는 실제 요청이 아닌, 서버에 보낼 요청의 정보(메서드, 헤더 등)를 포함합니다.

서버 응답 확인
서버는 OPTIONS 요청을 받고, 해당 요청이 허용되는지 확인한 후, 허용 여부와 허용되는 메서드, 헤더 등을 포함한 응답을 클라이언트에 반환합니다. 이때 서버 응답 헤더에는 다음이 포함되어야 합니다.
그러면 돌아오는 응답은 아래와 같이 보내집니다.

사전 요청 응답 검증
클라이언트는 서버의 응답을 확인하여 요청이 허용되는지 확인, 서버가 요청을 허용하는 경우, 클라이언트는 본 요청을 진행할 수 있습니다.
본 요청 전송
사전 요청이 허용된 경우, 클라이언트는 설정된 메서드와 헤더로 실제 요청을 서버에 보냅니다.
본 요청에 대한 응답 처리
서버가 본 요청을 처리하고 응답을 보내면, 클라이언트가 이를 수신하고 결과를 처리합니다.
CORS 이전에 존재하던 우회 방법으로 지금은 사용하지 않습니다만, 이런 방법이 있었다는 점!
JSON with Padding (JSONP)는 HTML script 태그를 사용하여 외부 데이터를 받아올때 SOP 정책에 적용되지 않아, 웹 애플리케이션 간의 통신을 가능하게 해준 기술입니다.
이전 CORS이 등장하기 전 SOP 에 의해 제한되었던 외부 데이터 사용을 강제로 실행시킨 기술이었지만, 앞서 언급한 것처럼 보안 문제와 외부 도메인의 대한 신뢰도 문제가 여전히 남아있었습니다. 지금은 CORS가 있기 때문에 이를 사용하는 것이 권장되며, 현재는 오래된 JSONP 2009년 이후로 잘 작동하지 않습니다.
예제 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSONP Example</title>
</head>
<body>
<h2>JSONP Example</h2>
<div id="result">Loading...</div>
<script>
// JSONP 응답을 받을 콜백 함수 정의
function handleResponse(data) {
document.getElementById("result").innerText = `User: ${data.name}, Age: ${data.age}`;
}
// JSONP 요청 보내기
const script = document.createElement("script");
script.src = "https://example.com/getUserData?callback=handleResponse";
document.body.appendChild(script);
</script>
</body>
</html>
콜백 함수 정의
handleResponse 함수는 JSON 데이터를 받아서 DOM에 출력하는 역할을 합니다. 이 함수의 이름은 요청 시 URL 파라미터에 callback=handleResponse로 포함됩니다.
스크립트 태그 동적 생성 및 요청
script 태그를 만들어 src 속성에 서버 URL을 지정합니다. 서버는 callback 파라미터를 포함한 응답을 JavaScript 코드로 보내게 됩니다.
서버 응답 예시
서버는 아래와 같이 JavaScript 코드 형태로 응답합니다.
handleResponse({ "name": "Alice", "age": 25 });
서버에서 CORS를 구성할때에 아래와 같은 사항에 유의해야 합니다.
VSCode 혹은 다른 IDE도 마찬가지로 가끔 웹페이지를 index.html을 통해 열었는데 CORS 에러가 뜰 때가 존재합니다. 이는 일반적으로 파일을 브라우저로 열었을때 오리진이 file:// 으로 설정되어 CORS 충돌이 나는 것입니다.
오리진이 동일하게 해야 요청을 제대로 보낼 수 있으므로 VSCode에서는 오리진을 https:// 으로 열어주는 Go Live Server를 통해 열면 문제를 해결 할 수 있습니다.
추가 참고 자료:
https://evan-moon.github.io/2020/05/21/about-cors/
https://docs.tosspayments.com/resources/glossary/cors
https://www.youtube.com/watch?v=bW31xiNB8Nc
https://velog.io/@yejinh/CORS-4tk536f0db
발표는 어려워...ㅠㅠㅠㅠ