초기 로딩 속도 3초에서 0.8초로: Plaid 홈페이지 성능 최적화

김충영's avatar
Dec 15, 2025
초기 로딩 속도 3초에서 0.8초로: Plaid 홈페이지 성능 최적화

1. 소개

안녕하세요, Plaid DX팀에서 프론트엔드 리드를 맡고 있는 김충영입니다. 최근 우리 회사의 얼굴인 홈페이지 리뉴얼 프로젝트를 진행하면서, 디자인과 기능을 구현하는 것만큼이나 '사용자에게 얼마나 빠르게 콘텐츠를 보여줄 것인가'에 대한 고민을 깊게 하게 되었습니다. 개발 환경에서는 쾌적하게 돌아가던 페이지가 배포 후 실제 모바일 환경에서 테스트해보니 초기 로딩이 3초 가까이 걸리는 현상을 목격했기 때문입니다.

이번 글에서는 제가 홈페이지를 개발하며 마주쳤던 성능 저하의 원인들을 분석하고, 이미지 최적화, 번들 사이즈 축소, 그리고 렌더링 전략을 통해 어떻게 로딩 속도를 0.8초 대까지 단축시켰는지 그 구체적인 과정을 공유하려 합니다. 성능 최적화는 단순히 "빠르게 만든다"를 넘어 사용자 이탈을 막고 비즈니스 가치를 높이는 핵심 작업입니다. 저처럼 성능 문제로 고민하는 프론트엔드 개발자분들에게 이 기록이 작은 이정표가 되기를 바랍니다.


2. 현상 분석: 무엇이 우리 웹사이트를 느리게 만들었나?

최적화를 시작하기 전, 정확한 진단이 필요했습니다. 구글의 Lighthouse와 Chrome DevTools를 통해 우리 홈페이지의 현재 상태를 측정해보았습니다.

측정 결과, Performance 점수는 40점대였으며, 특히 LCP(Largest Contentful Paint)가 3.2초로 매우 느리게 측정되었습니다. 네트워크 탭과 번들 분석기를 통해 파악한 주된 원인은 다음과 같았습니다.

Core web 지표 중 하나인 LCP
  1. 거대한 자바스크립트 번들: 모든 페이지의 코드가 하나의 파일로 뭉쳐져 있어, 당장 필요 없는 코드까지 다운로드하고 있었습니다.

  2. 최적화되지 않은 이미지: 고해상도 PNG 파일들이 그대로 서빙되어 네트워크 대역폭을 잡아먹고 있었습니다.

  3. 폰트 로딩 지연: 웹 폰트 용량이 커서 텍스트가 늦게 뜨거나 깜빡이는 현상이 발생했습니다.

3. 리소스 다이어트: 이미지와 폰트 최적화

가장 먼저 시도한 것은 '물리적인 파일 크기'를 줄이는 것이었습니다. 코드를 건드리기 전, 리소스만 최적화해도 드라마틱한 효과를 볼 수 있기 때문입니다.

3.1. 차세대 이미지 포맷(WebP) 도입

기존에는 디자이너분이 전달해주신 고화질 PNG, JPG를 그대로 사용하고 있었습니다. 하지만 웹에서는 투명 배경이 필요 없는 경우 굳이 PNG를 고집할 이유가 없습니다. 저희는 브라우저 호환성이 좋은 WebP 포맷으로 이미지를 변환하여 적용했습니다.

적용 방법: <img> 태그를 활용해 브라우저가 지원하는 포맷을 선택적으로 로딩하도록 했습니다.

HTML

<picture>
  <source srcSet="hero-image.webp" type="image/webp" />
  <img src="hero-image.jpg" alt="메인 배너" />
</picture>

결과적으로 이미지 용량을 평균 40% 이상 절감할 수 있었고, 육안으로 보이는 퀄리티 차이는 거의 없었습니다.

3.2. 폰트 경량화

웹 폰트 역시 초기 로딩을 방해하는 큰 요소입니다. 특히 한글 폰트는 파일 크기가 MB 단위로 매우 큽니다. 저희는 '밚, 갂' 처럼 실생활에서 거의 쓰이지 않는 글자를 제거한 서브셋(Subset) 폰트를 적용하고, 압축률이 높은 WOFF2 형식을 사용했습니다.

CSS

@font-face {
  font-family: 'Pretendard';
  src: url('/fonts/Pretendard-Medium.subset.woff2') format('woff2');
  font-display: swap; /* 폰트 로딩 전 시스템 폰트 노출 */
}

이 작업을 통해 폰트 파일 크기를 2.5MB에서 300KB 수준으로 8분의 1 가까이 줄일 수 있었습니다.

4. 번들 사이즈 줄이기: Code Splitting & Lazy Loading

리소스 최적화 후, 다음 타깃은 자바스크립트 번들 파일이었습니다. React는 SPA(Single Page Application) 특성상 초기에 모든 스크립트를 다운로드하는데, 이를 효율적으로 쪼개는 작업이 필요했습니다.

4.1. Route 기반 코드 스플리팅

사용자가 처음에 '메인 페이지'에 접속했다면, '마이페이지'나 '설정 페이지'의 코드는 당장 필요하지 않습니다. React의 lazy와 Suspense를 활용해 라우트 별로 코드를 분할(Code Splitting)했습니다.

TypeScript

// 변경 전
import MyPage from './pages/MyPage';

// 변경 후: 해당 페이지에 접근할 때 JS 파일을 받아옵니다.
const HomePage = lazy(() => import('@pages/home/HomePage.tsx'));
const IntroductionPage = lazy(() => import('@pages/introduction/IntroductionPage.tsx'));
const PortfolioPage = lazy(() => import('@pages/portfolio/PortfolioPage.tsx'));
const PortfolioDetailPage = lazy(() => import('@pages/portfolio-detail/PortfolioDetailPage.tsx'));
const NuvionPage = lazy(() => import('@pages/nuvion/NuvionPage.tsx'));

4.2. 컴포넌트 Lazy Loading

페이지 단위뿐만 아니라, 한 페이지 내에서도 당장 보이지 않는 무거운 컴포넌트(예: 하단 푸터, 이미지가 많은 섹션 등)는 화면에 진입할 때 로딩하도록 처리했습니다.Intersection Observer를 활용하거나 라이브러리를 통해 뷰포트에 들어올 때 로딩을 트리거하여 초기 JS 실행 시간을 대폭 단축시켰습니다.

5. 사용자 경험(UX) 챙기기: CLS 방지 및 로딩 UI

속도가 빨라진 것만큼이나 중요한 것은 "사용자가 느끼는 체감 속도"입니다. 이미지가 로딩되면서 텍스트가 아래로 툭 떨어지는 CLS(Cumulative Layout Shift) 현상은 사용자 경험을 크게 해칩니다.

이미지의 widthheight(또는 aspect-ratio)를 CSS에 미리 명시해두면, 이미지가 로딩되기 전에도 브라우저가 공간을 확보해두어 레이아웃이 흔들리지 않습니다.

또한, 데이터를 불러오는 동안 흰 화면을 보여주는 대신 로딩 스피너를 적용했습니다. 사용자는 뼈대 화면을 보며 "로딩 중이구나"라고 인지하게 되고, 심리적인 대기 시간을 훨씬 짧게 느끼게 됩니다.

6. 성과 및 마무리

이러한 일련의 최적화 과정을 거친 후, 다시 한번 성능을 측정해보았습니다.

  • LCP: 3.2초 → 0.8초 (약 75% 개선)

  • JS 번들 사이즈: 초기 로딩 시 1.8MB → 450KB (약 75% 감소)

  • Lighthouse 점수: 42점 → 91점

물론 이 수치가 끝은 아닙니다. 서비스가 고도화될수록 성능은 다시 느려질 수 있기에, 지속적인 모니터링과 관심이 필요할 것입니다.

이번 글에서는 제가 Plaid 홈페이지를 만들며 적용했던 대표적인 최적화 기법들을 정리해보았습니다. 사실 최적화에는 정답이 없습니다. 프로젝트의 상황과 비즈니스 로직에 따라 트레이드오프가 발생하기 마련이니까요. 하지만 "사용자에게 더 나은 경험을 제공하겠다"는 목표 하나로 끈질기게 분석하고 개선해 나가는 과정 자체가 개발자로서 한 단계 성장하는 계기가 되었다고 생각합니다.

이 글이 여러분의 프로젝트 성능을 개선하는 데 조금이나마 힌트가 되었으면 좋겠습니다. 긴 글 읽어주셔서 감사합니다.

Share article

플래드