- 데이터를 제공하는 파일 서버를 구축해야 하는 경우 AWS의 S3와 CloudFront 서비스를 이용하면 손쉽게 구축 가능 → 이미지의 경우 자주 사용
- AWS S3와 CloudFront를 통해 Webapp을 만들 경우 CORS관련 문제가 발생 가능
- 브라우저의 기본 기능을 통해 파일을 직접 다운로드를 하거나 DOM을 이용해 (
테그나 CSS) 이미지를 표시하기 때문에 문제 발생 X
- XHR을 통해 데이터를 받아서 사용하는 경우에는 Webapp이 제공되는 도메인과 CloudFront 서비스의 도메인이 다르기 때문에 CORS 문제 발생
- AWS S3에서 CORS 관련 설정을 제공하지만, 브라우저와 CloudFront의 캐시 기능과 엮이면서 S3의 CORS 기능이 재대로 동작하지 않는 경우가 빈번
- Unity3d를 이용해서 Facebook Canvas 웹게임을 만들 때 CORS 문제가 발생
- Unity3d의 기본 HTTP Client인 UnityWebRequest를 이용해서 데이터를 받아오도록 짜면 Facebook Canvas 빌드의 경우 XHR을 사용하도록 컴파일
- Facebook을 통해 서비스가 되는데, 받아와야 하는 데이터는 AWS S3에 있기 때문에 CORS 문제를 피할 수 없게됨
- Unity3d쪽은 가능하면 수정하고 싶지 않아 서버쪽에서 CORS 지원하도록 수정
크롬 브라우저 캐시로 인한 CORS 에러
- 크롬 브라우저의 캐시 정책으로 발생한 문제
- 광고 이미지를 Facebook Page에 게시물로 올리고, Canvas 게임 안에서도 배너로 표시
- 유저가 Facebook Page에 접근해서 이미지를 본 후 링크를 눌러 게임에 진입했을 경우에, Unity 게임 안에서 동일한 이미지를 XHR로 받으려고 하면 CORS 에러가 발생
- 에러 발생과정
- 유저가 Facebook Page에서 이미지를 봄 → 이미지는 img 태그로 표시되기 때문에 HTTP 통신을 보면 이미지 요청과 응답에는 CORS 관련 헤더가 없음 (크롬 브라우저는 요청과 응답을 캐시함)
- Unity가 XHR로 같은 이미지를 요청 → 요청에는 CORS 관련 헤더를 포함됨
- 크롬 브라우저의 네트워크 담당 부분에서 1에서 캐시한 응답 결과 리턴 → 자바스크립트에서 응답된 결과에 CORS 관련 헤더가 없기 때문에 에러가 발생함. (캐싱된 이미지는 CORS관련 헤더가 없음)
2의 요청과 1의 요청은 헤더가 다르고 결과도 다른 경우인데, 크롬 브라우저가 같은 결과가 나올 것을 기대하고 캐시를 사용하는 것이 문제의 원인
매우 마이너한 경우이고, 브라우저의 동작을 명확히 규정하는 표준도 없기 때문에 발생한 경우임
크롬 브라우저가 2의 요청에 1에서 캐시한 결과를 사용하지 않도록 Vary Header를 사용하면 문제 해결됨
CloudFront에 Lambda Edge를 추가해서 응답 결과에 아래와 같이 Vary header를 추가
'use strict'; // If the response lacks a Vary: header, fix it in a CloudFront Origin Response trigger. exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const headers = response.headers; if (!headers['vary']) { headers['vary'] = [ { key: 'Vary', value: 'Access-Control-Request-Headers' }, { key: 'Vary', value: 'Access-Control-Request-Method' }, { key: 'Vary', value: 'Origin' }, ]; } callback(null, response); };
CloudFront Origin별 캐시 오동작
CloudFront가 CORS 요청에 비CORS 응답을 캐시해서 발생
S3는 CORS 관련 헤더가 요청에 있을 경우에만 응답에 CORS 관련 헤더를 추가해줌
CloudFront도 단순 URL 뿐만 아니라 HTTP 헤더에 따라 다른 결과를 캐시 필요 → Origin 헤더에 따라 다른 결과를 캐시하는 기능을 제공
처음에는 잘 동작하는 듯 했는데, 한 시간 정도 지나면 CORS 요청에 비CORS 응답이 캐시되는 경우가 빈번히 발생
프로필 이미지나 정적 데이터를 제공할 뿐인 단순한 경우라서 CloudFront의 모든 응답에 CORS관련 헤더를 강제로 추가
'use strict'; // If the response lacks a Vary: header, fix it in a CloudFront Origin Response trigger. // If the response lacks CORS header, ... exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const headers = response.headers; if (!headers['vary']) { headers['vary'] = [ { key: 'Vary', value: 'Access-Control-Request-Headers' }, { key: 'Vary', value: 'Access-Control-Request-Method' }, { key: 'Vary', value: 'Origin' }, ]; } if (!headers['access-control-allow-origin']) { headers['access-control-allow-origin'] = [ { key: 'Access-Control-Allow-Origin', value: '*' } ]; } if (!headers['access-control-allow-methods']) { headers['access-control-allow-methods'] = [ { key: 'Access-Control-Allow-Methods', value: 'GET' }, { key: 'Access-Control-Allow-Methods', value: 'HEAD' } ]; } if (!headers['access-control-expose-headers']) { headers['access-control-expose-headers'] = [ { key: 'Access-Control-Expose-Headers', value: 'ETag' }, { key: 'Access-Control-Expose-Headers', value: 'Last-Modified' } ]; } callback(null, response); };
'HTTP > CORS' 카테고리의 다른 글
XHR (XML Http Request)이란 (0) | 2022.07.24 |
---|---|
3장. CORS의 HTTP 응답 헤더와 HTTP 요청 헤더 (0) | 2022.07.24 |
2장. CDN을 통한 CORS 및 CORS 요청 (0) | 2022.07.24 |
1장. CORS 기본 정리 (0) | 2022.07.24 |