• 데이터를 제공하는 파일 서버를 구축해야 하는 경우 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 에러가 발생
  • 에러 발생과정
    1. 유저가 Facebook Page에서 이미지를 봄 → 이미지는 img 태그로 표시되기 때문에 HTTP 통신을 보면 이미지 요청과 응답에는 CORS 관련 헤더가 없음 (크롬 브라우저는 요청과 응답을 캐시함)
    2. Unity가 XHR로 같은 이미지를 요청 → 요청에는 CORS 관련 헤더를 포함됨
    3. 크롬 브라우저의 네트워크 담당 부분에서 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);
    };

참고 URL : https://medium.com/bgpworks/aws-s3-cloudfront%EB%A1%9C-cdn-%EA%B5%AC%EC%B6%95-%EC%8B%9C-cors-%EA%B0%95%EC%A0%9C-%EC%84%A4%EC%A0%95-eb271a3ca3c6


'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

+ Recent posts