CORS는 Cross-Origin Resource Sharing의 약자입니다. 브라우저는 기본적으로 다른 origin의 응답을 JavaScript가 마음대로 읽지 못하게 막는데, server가 Access-Control-Allow-Origin 같은 header로 허용 범위를 알려주면 cross-origin 요청을 허용합니다.
중요한 점은 CORS가 client library의 문제가 아니라 browser 보안 정책이라는 것입니다. server가 허용 header를 제대로 내려줘야 하고, method나 header가 단순 요청 범위를 벗어나면 browser가 먼저 preflight OPTIONS 요청을 보내 허용 여부를 확인할 수 있습니다.
꼬리질문
조금 더 깊게 물어본다면
답변 뒤에 이어질 수 있는 질문들을 하나씩 열어볼 수 있어요.
origin은 무엇으로 결정되나요?
scheme, host, port 세 가지 조합으로 결정됩니다. https://example.com과 http://example.com은 scheme이 달라서 다른 origin입니다. port가 달라도 다른 origin입니다.
CORS는 server를 보호하는 기능인가요?
주로 browser 사용자를 보호하기 위한 정책에 가깝습니다. server는 요청 자체를 받을 수 있지만, browser가 JavaScript에 응답을 노출하지 않도록 막습니다. CORS는 인증/인가를 대체하지 않으며, server는 여전히 자체 권한 검사를 해야 합니다.
SOP가 없으면 어떤 문제가 생기나요?
Same-Origin Policy가 없으면 악의적인 사이트의 JavaScript가 사용자 브라우저를 통해 다른 사이트의 API를 자유롭게 호출하고 응답을 읽을 수 있습니다. 로그인된 세션을 이용해 개인정보를 탈취하거나 사용자 모르게 요청을 보내는 공격이 가능해집니다.
preflight는 언제 발생하나요?
simple request 조건을 벗어나는 method, header, content type을 사용할 때 발생합니다. 예를 들어 Authorization header가 있거나 PUT, DELETE method를 쓰면 browser가 먼저 OPTIONS 요청으로 허용 여부를 확인합니다.
simple request의 조건은 무엇인가요?
method가 GET, HEAD, POST 중 하나이고, Content-Type이 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나이며, 추가 custom header가 없는 경우입니다. 이 조건을 모두 만족하면 preflight 없이 바로 요청이 전송됩니다.
preflight 캐싱은 어떻게 하나요?
server가 Access-Control-Max-Age 헤더로 초 단위 캐시 유효 시간을 지정합니다. 브라우저는 그 시간 동안 같은 origin과 method 조합에 대해 preflight를 생략합니다.
credentials를 포함할 때 주의할 점은?
cookie 같은 credentials를 보내려면 client에서 credentials 옵션을 켜고, server도 Access-Control-Allow-Credentials: true를 응답해야 합니다. 이때 Access-Control-Allow-Origin: *는 사용할 수 없고 특정 origin을 명시해야 합니다.
CORS와 CSRF는 어떻게 다른가요?
CORS는 browser가 cross-origin 응답을 JavaScript에 노출할지 제어하는 정책입니다. CSRF는 사용자가 인증된 상태에서 악의적인 사이트가 사용자 권한으로 요청을 보내도록 유도하는 공격입니다. CORS는 응답 읽기를 막지만, CSRF는 요청 자체를 악용합니다. 둘은 보호 대상과 메커니즘이 다릅니다.