V VibeCoding 365
사전 목록 security

VIBECODING 365 / DICTIONARY

교차 출처 리소스 공유

Cross-Origin Resource Sharing (CORS)

DEFINITION

교차 출처 리소스 공유(CORS)는 서버가 HTTP 헤더로, 자신과 다른 출처의 페이지 스크립트가 이 응답을 읽어도 된다고 브라우저에 알리는 방식이다. 지금 정의는 WHATWG Fetch 표준의 CORS 프로토콜에 있다. MDN은 이를 헤더 기반 메커니즘이라 부르며, 스크립트가 시작하는 교차 출처 HTTP 요청을 브라우저가 제한한다고 적는다. 출처는 스킴(프로토콜), 호스트, 포트가 모두 같아야 같다. 경로만 다른 주소는 같은 출처이고, https와 http, 또는 서로 다른 포트는 다른 출처다.

요청은 가는데 스크립트가 못 읽는 이유

동일 출처 정책은 한 페이지의 스크립트가 다른 출처의 자원을 마음대로 읽지 못하게 한다. MDN이 드는 예는, 악성 사이트가 로그인된 웹메일이나 사내망 페이지를 스크립트로 읽어 밖으로 보내는 일을 막는 것이다. 다만 요청 자체를 모두 막지는 않는다. 링크 이동, 폼 전송, 이미지·스크립트 태그로 끼워 넣기는 대개 허용된다. 막히는 쪽은 fetch나 XMLHttpRequest처럼 스크립트가 응답 본문을 읽는 경로다. 그래서 같은 주소라도 터미널 도구는 되고 브라우저 콘솔만 빨간 경우가 생긴다. CORS는 그 읽기를 서버가 골라 열어 주는 예외다. MDN은 웹 폰트, WebGL 텍스처, 캔버스에 그린 이미지에도 이 공유 규칙이 쓰일 수 있다고 적는다.

폼이 오래전부터 보내던 요청

오래된 CORS 문서의 「단순 요청」은 지금 Fetch가 쓰지 않는 이름이다. 동기는 HTML 폼이 예부터 다른 출처로 GET·POST를 보낼 수 있었다는 점이다. 서버는 그런 요청이 이미 온다고 가정해야 하므로, 미리 묻지 않고 가는 요청까지 막지는 않는다. 그래도 스크립트가 응답을 읽으려면 서버가 Access-Control-Allow-Origin으로 허용해야 한다. Fetch가 세이프리스트로 두는 메서드는 GET, HEAD, POST다. 수동으로 붙인 헤더는 Accept, Accept-Language, Content-Language, 제한된 Content-Type, 단순 Range 정도다. Content-Type이 폼 인코딩, multipart, plain 텍스트가 아니면 바로 가지 않는다. JSON 본문, Authorization 같은 커스텀 헤더, PUT·DELETE·PATCH는 브라우저가 먼저 OPTIONS로 물어본다. 쓸 메서드와 헤더 이름을 알리고, 서버가 허용 메서드·허용 헤더·허용 출처로 승인한 뒤에야 본요청이 간다. 이 미리 묻기 응답은 초 단위로 캐시할 수 있다. MDN 예는 86400초를 들고, 기본은 5초라고 적는다. 브라우저마다 내부 상한이 있어 그보다 긴 값은 잘린다.

쿠키를 실으면 별표가 안 된다

교차 출처 fetch는 기본적으로 쿠키와 HTTP 인증을 보내지 않는다. 포함하려면 credentials를 include로 두거나 XMLHttpRequest의 withCredentials를 켠다. 그때 서버는 Access-Control-Allow-Credentials를 true로 주고, Allow-Origin에는 별표가 아니라 요청한 출처 문자열을 그대로 적어야 한다. Fetch는 자격 증명이 있는 요청에서 별표를 금지한다. 아무 사이트가 로그인된 응답을 읽게 되기 때문이다. MDN은 미리 묻는 요청 자체에는 자격 증명을 실으면 안 된다고 적는다. 실제 요청에 쿠키를 실을 수 있다는 표시로, 미리 묻기 응답에 Credentials true가 있어야 한다.

콘솔에만 이유가 나오는 오류

CORS가 실패하면 스크립트에는 오류만 보이고 구체 이유는 숨긴다. MDN은 보안상 그렇게 한다고 적고, 원인은 브라우저 콘솔에서 보라고 한다. 대부분의 수정은 서버 응답 헤더에 있다. 프론트만 고쳐서는 다른 출처 API가 열리지 않는다. 화면 앱과 API 호스트가 갈라진 바이브 코딩 프로젝트에서 콘솔의 CORS 차단은, 허용 출처가 없거나 쿠키를 쓰는데 별표를 쓴 경우가 많다. 서버를 건드리지 못하는 외부 API면, 자신이 통제하는 서버로 받아 같은 출처처럼 돌려주는 방법이 MDN에 안내되어 있다.

ENGLISH

Cross-Origin Resource Sharing (CORS)

EXAMPLE

Access-Control-Allow-Origin: https://app.example