이 영역을 누르면 첫 페이지로 이동
Coding Groot 블로그의 첫 페이지로 이동

Coding Groot

페이지 맨 위로 올라가기

Coding Groot

코딩 블로그

CloudFront에 올린 Font(woff, woff2)가 CORS 때문에 차단되는 경우

  • 2022.08.21 22:27
  • Programming/Web
글 작성자: Coding Groot

폰트가 계속 차단이 되는 경우 확인해 볼 것

CORS 에러가 발생한 상황

프로젝트를 하다가 유독 Web Font(woff, woff2)만 CORS에 의해 막히는 이상한 현상이 발생했습니다.

아래와 같이 CSS에서 우리가 CDN에 올려준 Font를 불러오도록 했습니다. 

우리 사이트의 css

Access-Control-Allow-Origin 응답 Header에 이 Font를 요청하는 사이트 주소도 잘 추가되어 있었습니다.

일단 저는 S3에 폰트를 업로드하고 CDN이랑 연동을 했습니다. 그리고 CDN에서는 S3 bucket의 CORS 정책을 쓰도록 했습니다.

CloudFront의 Cache 및 CORS 정책
S3 CORS 정책

CloudFront와 CORS 정책은 아무 문제가 없어 보였습니다. 

그런데 계속 Access-Control-Allow-Origin에 의해 CORS 의해 막혔습니다. Console에 뜬 메시지는 다음과 같습니다. 

Access to font at 'https://cdn.주소.com/font.woff2' from origin 'https://www.주소.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Access to font at 'https://cdn.주소.com/font.woff2' from origin 'https://www.주소.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Console에 나온 CORS관련 로그 캡처

정말 이상했던게 다른 AJAX 요청은 잘 되는데 유독 Font 파일만 가져올 때 CORS Error가 나는 것이 이상했습니다. 

처음에는 이전에 CORS 정책을 안 넣어줬었는데 그것 때문인가 했습니다. 그래서 cache invalidation을 하고 다른 잘되는 request의 Last-Modified 값을 봤는데 전부 최신 파일을 받아오고 괜찮아 보였습니다.

그래서 팀원이 검색을 해서 다음과 같은 글을 발견했습니다.

https://stackoverflow.com/questions/52893199/cors-issue-with-woff2-fonts-behind-cdn-in-chrome

Content-Type을 application/font-woff2으로 해줘야지 Invalidation이 제대로 된다 이런 말이 있더군요. (하지만 저건 옛날 MIME입니다. 최신으로 찾아보시고 설정하세용.) 하지만 이것도 해결이 안 됐습니다. 

문제

답은 의외로 간단한 곳에 있었습니다.

크롬이 친절히 다 알려줬습니다.

"님 Preflight Request Block 됨" 

크롬에 뜬 issue

Preflight Request가 차단돼서 발생한 오류였던 것입니다. 

Webfont는 Preflight Request를 보낸다

제가 예전에 쓴 CORS 글에서도 간단히 다룬 적이 있습니다. 

Simple Request의 조건은 간단하게 다음과 같습니다. (더 정확한 것은 문서를 확인해주세용.)

  • HTTP Method가 GET, POST, HEAD 중 하나
  • Content-Type이 아래 중 하나이다
    • text/plain
    • application/x-www-form-urlencoded
    • multipart/form-data

WebFont는 font/woff, WebFont2는 font/woff2라는 MIME type을 쓰고 있습니다. 모두 Simple Request의 Content-Type 조건은 아닙니다.

따라서 WebFont의 Content-Type은 Preflight처리됩니다.

제가 오류가 발생한 이유는 Preflight Request용도로 사용된는 OPTIONS 메서드를 허용하지 않아서 허용하는게 무엇인지 브라우저가 알 수 없으니 CORS 정책에 의해 차단되고 있었던 겁니다.

Preflight Request란?

Simple Request가 아닌 Request는 Preflight Reqeust를 먼저 보내서 몇 가지를 확인을 받도록 되어있습니다.

Preflight Request는 먼저 브라우저가 OPTIONS 메서드로 원하는 리소스에 대해 HTTP 요청을 보내도 괜찮은지 확인하는 것입니다.

예를 들어서, 제가 어떤 폰트에 GET 요청을 보냈다고 해봅시다.

// AJAX Request from Browser
fetch('https://cdn.주소.com/awesome-font.woff2')

그럼 브라우저는 자동으로 Simple Request에 해당하지 않으므로 아래와 같이 Preflight Request를 만들어서 보냅니다.

OPTIONS /awesome-font HTTP/1.1
Origin: https://www.웹사이트주소.com
Access-Control-Request-Method: GET
Access-Control-Request-Headers: Content-Type, ...생략
...생략

그럼 미리 서버가 Origin이랑 Header를 보고 아래와 같이 허용하는 것 응답으로 알려줍니다. 

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://www.웹사이트주소.com
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
Access-Control-Allow-Headers: Content-Type, ...생략
...생략

브라우저는 "음..! 서버에서는 이런 것들을 허용하고 있군!" 한번 확인을 하고 제대로 Request를 보냅니다.

GET /awesome-font HTTP/1.1
Origin: https://www.웹사이트주소.com
Content-Type: font/woff2
...생략

Preflight에서 허용하는 것에 맞추어 본래 Request가 보내지면 서버에서는 font파일을 보내주게 됩니다.

해결법

해결법은 Preflight Request를 허용해주면 됩니다.

위에서 설명했다시피 브라우저는 Simple Request가 아닌 경우에 실제 Request를 보내기 전 Preflight Request를 보냅니다. 이것을 위해 HTTP OPTIONS 요청을 사용합니다.

OPTIONS /나의소중한webfont HTTP/1.1
Origin: https://cdn.주소.com
Access-Control-Request-Method: GET

저는 바보같이 GET 요청만 할테니깐 GET, HEAD만 허용했었습니다. OPTIONS도 허용해줍시다.

CloudFront에서 미리 요청을 보낼 수 있도록 OPTIONS 메서드 허용해줍시다.

CloudFront > Distribution 선택 > Behaviours > Edit

GET, HEAD와 함께 OPTIONS도 허용했습니다.

S3 CORS 정책은 건드릴 필요 없습니다. (애초에 CORS AllowedMethods로 "OPTIONS"를 지원하지도 않습니다.)

그러며 해결될 겁니다!


참고한 문서

  • https://developer.mozilla.org/ko/docs/Web/HTTP/CORS#%EB%8B%A8%EC%88%9C_%EC%9A%94%EC%B2%ADsimple_requests
  • https://coding-groot.tistory.com/91#simple-request%EC%9D%B8-%EA%B2%BD%EC%9A%B0
  • https://stackoverflow.com/questions/52893199/cors-issue-with-woff2-fonts-behind-cdn-in-chrome
  • https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/ManageCorsUsing.html#cors-allowed-methods
반응형

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • HTTP 1.1 - 같은 서버(도메인)에 관한 동시 연결 제한

    HTTP 1.1 - 같은 서버(도메인)에 관한 동시 연결 제한

    2024.09.12
  • CertBot 인증서가 만료가 되었다

    CertBot 인증서가 만료가 되었다

    2024.01.21
  • 웹 문서를 만들기 전에 고민해볼 것들

    웹 문서를 만들기 전에 고민해볼 것들

    2022.04.17
  • Flask를 CLI에서 실행해야 하는 이유와 환경 세팅하기

    Flask를 CLI에서 실행해야 하는 이유와 환경 세팅하기

    2021.06.08
다른 글 더 둘러보기

정보

Coding Groot 블로그의 첫 페이지로 이동

Coding Groot

  • Coding Groot의 첫 페이지로 이동

검색

메뉴

  • 홈
  • 태그
  • 방명록
  • 소개
  • 블로그 저작권

카테고리

  • 분류 전체보기 (183) N
    • Git (23)
      • Git Tutorial (9)
      • Git Note (7)
      • Git Lecture (7)
    • Programming Language (1)
      • C (2)
      • C Sharp (5)
      • Java (4)
      • JavaScript (7)
      • Julia (5)
      • Python (4)
    • Programming (8)
      • Algorithm (2)
      • Compiler (5)
      • Data Structure (0)
      • Web (12)
      • NestJS (2)
    • DevOps, Infra (36)
      • Apple (6)
      • Cloud (15)
      • Database (1)
      • Network (4)
      • Linux (8)
    • Game Programming (11)
      • Unity Tutorial (5)
      • Unity Note (6)
    • Hardware Design (1)
      • Digital Circuit (1)
    • Note (49)
      • Coffee (2)
      • Retrospect (15)
      • Reading List (14)
    • Mathematics (1)

최근 글

인기 글

댓글

공지사항

아카이브

태그

  • git
  • 회고
  • 서평
  • tutorial
  • aws
  • Github
  • javascript
  • 한빛미디어
  • 전체 보기…

정보

Coding Groot의 Coding Groot

Coding Groot

Coding Groot

블로그 구독하기

  • 구독하기
  • RSS 피드

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기

나의 외부 링크

  • GitHub
  • SlideShare
  • 유니티 2020 수업
  • TIL Blog
  • 모도코

방문자

  • 전체 방문자
  • 오늘
  • 어제
Powered by Tistory / Kakao. Copyright © Coding Groot.

티스토리툴바