[React] 폰트 최적화 + preload 적용해 사용자 경험 개선하기

2025. 6. 23. 15:14·웹/React

<코코> 프로젝트를 진행하며 폰트 최적화 및 preload를 적용한 내용을 기록

 

<코코> 프로젝트 현재 폰트 현황과 배포 방식

 

코코 프론트엔드는 CloudFront + S3 방식으로 배포

따라서, 사용한 데이터 용량과 네트워크 요청 수에 의해 비용 산정된다.

현재 폰트 관련 최적화 및 고려가 하나도 이루어지지 않은 상태이다.

 

index.html 폰트 로드
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/gh/orioncactus/Pretendard/dist/web/static/pretendard.css"
   />
  <link rel="preconnect" href="https://fonts.googleapis.com" />
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
  <link href="https://fonts.googleapis.com/css2?family=Jua&display=swap" rel="stylesheet" />

Pretendard : 서비스 메인 폰트

Jua 특정 컴포넌트에서만 사용되는 폰트

현재 웹폰트를 외부 CDN 두 군데에서 각각 불러오고 있으며,

둘 다 폰트 서브셋이 아니어서 용량이 매우 크다.

 

❓폰트 서브셋이란
필요하지 않은 글자는 다 제외하고 필요한 글자들만 불러오는 것.

 

그래서 결론은 웹 폰트를 외부 CDN으로 불러 오는 방식 대신 폰트 파일을 올려 서빙하는 방식(셀프 호스팅)으로 바꾸고자 한다.

 

 


 

 

먼저 폰트 파일을 다운로드 받고, 서브셋 폰트로 변환시켜 vite 프로젝트의 public/fonts 폴더 내에 두어 서빙하고자 한다.

1. 폰트 파일 다운로드 → 서브셋 파일 변환 → 서빙

먼저 폰트 파일 형식은 .woff2 / .woff 로 다운로드한다.

 

.woff (Web Open Font Format)
  • 웹에서 폰트를 빠르게 불러올 수 있도록 압축된 형태
  • .woff 보다 .woff2 가 더 강하게 압축되어 있다.
  • .woff 는 거의 모든 브라우저가 지원중, .woff2 는 지원되지 않는 브라우저(IE)도 있어, 보통 이 두개를 같이 쓴다.

 

폰트 파일 다운로드 및 서브셋 변환
[Pretendard: 기존에 쓰던 Pretendard 서브셋 폰트 파일이 있어서 그대로 사용했다.]
Pretendard는 워낙 유명한 폰트라 서브셋 폰트 파일까지 구하는 데 어렵지 않았다.

[Jua: 구글 폰트에서 다운 후 ttf -> woff, woff2 형식으로 변환했다.]
구글 폰트 - https://fonts.google.com/selection
폰트 파일 형식 변환 사이트 - https://transfonter.org/

 

폰트 폴더 위치 public/fonts

프로젝트 내 폰트 폴더 위치

 

Pretendard의 경우 굵기가 다양한데, 프로젝트에 필요한 파일만 넣어두었다.

 

폰트 적용

1. font-face 선언
// font.css

/** Pretendard */
@font-face {
  font-family: 'Pretendard';
  src:
    url('/fonts/Pretendard/Pretendard-Regular.subset.woff2') format('woff2'),
    url('/fonts/Pretendard/Pretendard-Regular.subset.woff') format('woff');
  font-weight: 400;
  font-style: normal;
}

@font-face {
  font-family: 'Pretendard';
  src:
    url('/fonts/Pretendard/Pretendard-Medium.subset.woff2') format('woff2'),
    url('/fonts/Pretendard/Pretendard-Medium.subset.woff') format('woff');
  font-weight: 500;
  font-style: normal;
}

@font-face {
  font-family: 'Pretendard';
  src:
    url('/fonts/Pretendard/Pretendard-SemiBold.subset.woff2') format('woff2'),
    url('/fonts/Pretendard/Pretendard-SemiBold.subset.woff') format('woff');
  font-weight: 600;
  font-style: normal;
}

@font-face {
  font-family: 'Pretendard';
  src:
    url('/fonts/Pretendard/Pretendard-Bold.subset.woff2') format('woff2'),
    url('/fonts/Pretendard/Pretendard-Bold.subset.woff') format('woff');
  font-weight: 700;
  font-style: normal;
}

/** Jua */
@font-face {
  font-family: 'Jua';
  src:
    url('/fonts/Jua/Jua-Regular.woff2') format('woff2'),
    url('/fonts/Jua/Jua-Regular.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

font.css는 index.css에서 import 된다.

 

2. css에서 font-family 적용
// global.css

/* 기본 폰트 설정 */
body {
  font-family: 'Pretendard', sans-serif;
  font-weight: 400;
  line-height: 1.5;
  background-color: #f8f9fa;
  color: #111827;
}

 

2. preload

폰트 파일은 가장 나중에 다운로드 되는데, preload는 폰트 파일을 먼저 다운로드 받게 한다. 따라서 필요한 부분 (초기 화면) 등에서 사용되는 폰트라면 preload를 설정하자.

나의 경우 초기화면에서 사용되는 폰트 위주로 preload를 적용하려고 한다.

 

preload 전

preload 적용 전에는 폰트 파일들이 초기 화면이 보이기 직전에 (거의 마지막에) 로드 되고 있다.

따라서 초기 화면 렌더링 후 지연되어 시스템 글꼴 먼저 보여진 뒤, 지정된 글꼴로 바뀌게 되면서 폰트가 우글거리게 된다.

 

preload 적용
 <link
        rel="preload"
        href="/fonts/Pretendard/Pretendard-Regular.subset.woff2"
        as="font"
        type="font/woff2"
        crossorigin="anonymous"
    />
<link
  rel="preload"
  href="/fonts/Pretendard/Pretendard-Semi-B.subset.woff2"
  as="font"
  type="font/woff2"
  crossorigin="anonymous"
/>
<link
  rel="preload"
  href="/fonts/Pretendard/Pretendard-Bold.subset.woff2"
  as="font"
  type="font/woff2"
  crossorigin="anonymous"
/>
<link
  rel="preload"
  href="/fonts/Jua/Jua-Regular.woff2"
  as="font"
  type="font/woff2"
  crossorigin="anonymous"
/>

index.html 의 <head> 태그 내에 preload를 할 폰트를 위와 같이 선언해주었다.

 

preload 적용 후

preload 적용 후에는 폰트를 먼저 다운로드 하고, 폰트들이 초기 화면이 보이고 난 직후에 우글거리지 않고 정상적으로 바뀌어져 있다.

 

유의해야할 점: preload로 인한 로딩 시간 증가

preload 적용 전
preload 적용 후

 

위가 적용 전, 아래가 적용 후의 폰트 다운로드 시간이다.

폰트의 다운로드 시간이 조금 더 길어졌으며 전체 초기 로딩 시간(Finish 시간)이 미세하지만 증가했다.

preload를 하면 폰트를 최대한 빨리 다운받으려고 시도하기 때문에 다른 리소스들과 경쟁이 생겨 결과적으로 전체 로딩 지연이 생길 수 있다.

 

결론

  • preload는 폰트 로딩 우선순위를 높여서 UI 깜빡임(FOUT으로 인한 현상)은 줄여준다.
  • 하지만 다른 리소스들과 경쟁이 생기며 네트워크 혼잡을 일으킬 수 있으며, 결과적으로 초기 로딩 시간이 증가하게 될 수 있음.
  • 따라서 꼭 필요한 폰트 리소스만 preload 하는 게 좋음. (초기 화면에서 쓰이는 폰트, 자주 쓰이는 폰트 등)

 

마치며

소스를 찾아보며 브라우저 별로 폰트 처리가 다른 크로스 브라우징 이슈를 해결한 사례도 보았다.

브라우저 별로 폰트가 적용되는 정도를 테스트한 뒤 트러블슈팅 해봐도 좋겠다.

'웹 > React' 카테고리의 다른 글

[React] memo, useCallback을 사용한 렌더링 최적화  (3) 2025.07.08
[코드 개선하기] try, catch vs React Query의 onSuccess, onError : 비동기 처리 로직 통일하기  (0) 2025.06.25
[React, Vite, Vite-bundle-analyzer] CSR에서 초기 로딩 시간 단축하기 2 - 라이브러리 청크 단위로 정적 분리  (0) 2025.06.03
[React, Vite, Vite-bundle-analyzer] CSR에서 초기 로딩 시간 단축하기 1 - 코드 스플리팅, 지연 로딩하기 (+ 번들 시각화)  (0) 2025.06.02
React에서의 이벤트 처리: 이벤트 버블링, 위임, 합성 객체  (0) 2025.03.29
'웹/React' 카테고리의 다른 글
  • [React] memo, useCallback을 사용한 렌더링 최적화
  • [코드 개선하기] try, catch vs React Query의 onSuccess, onError : 비동기 처리 로직 통일하기
  • [React, Vite, Vite-bundle-analyzer] CSR에서 초기 로딩 시간 단축하기 2 - 라이브러리 청크 단위로 정적 분리
  • [React, Vite, Vite-bundle-analyzer] CSR에서 초기 로딩 시간 단축하기 1 - 코드 스플리팅, 지연 로딩하기 (+ 번들 시각화)
Hyemimi
Hyemimi
배움의 과정에서 느껴지는 소소한 즐거움을 중요시합니다 🌱
  • Hyemimi
    Hyemi.techlog
    Hyemimi
  • 전체
    오늘
    어제
    • 분류 전체보기 (32)
      • 웹 (15)
        • React (10)
        • Next (1)
      • 앱 (0)
        • Flutter (0)
      • 회고 (2)
        • 카카오테크 부트캠프 (4)
      • 언어 (1)
        • JavaScript (0)
        • TypeScript (1)
        • Python (0)
      • CS (3)
      • 알고리즘 (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    부트캠프추천
    부트캠프
    preload
    카카오테크부트캠프
    카테부
    OSSCA
    비동기
    KTB
    react
    kakaotechbootcamp
    Kakao
    오픈소스 컨트리뷰션 아카데미
    카카오
    판교부트캠프
    CSR
    폰트 최적화
    최적화
    카테부커뮤니티
    Vite
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
Hyemimi
[React] 폰트 최적화 + preload 적용해 사용자 경험 개선하기
상단으로

티스토리툴바