#Frontend

critical-script, 배달의민족 웹뷰 로딩 성능을 30% 개선한 인라인 스크립트 로딩 전략 이야기

critical-script, 배달의민족 웹뷰 로딩 성능을 30% 개선한 인라인 스크립트 로딩 전략 이야기
01

Summary

웹뷰 로딩 속도 30% 폭풍 개선! 배달의민족 'critical-script' 최적화 비결

직렬 워터폴을 깨뜨리는 인라인 스크립트 병렬화 기법과 Vite 플러그인 직접 제작기

배달의민족 하이브리드 앱 웹뷰의 느린 로딩 속도를 극복하기 위해 워터폴 구조를 전면 개선한 실전 가이드입니다. HTML 파싱 시점에 API prefetch와 CSS 변수 선행 주입을 수행하는 'critical-script' 번들러 플러그인을 구축하고, LCP/FCP 성능을 대폭 끌어올린 엔지니어링 과정을 상세히 다룹니다.

  • 01직렬 구조 워터폴에서 API 요청 및 리소스 로딩을 분리해 병렬화
  • 02실사용자 데이터 기준 LCP(Largest Contentful Paint) 25~35% 절감 달성
  • 03*.critical.ts 파일 정의 기반 개발자 경험(DX) 최적화 및 메인 앱 타입/상수 공유
  • 04전역 캐시 맵과 Axios 요청 인터셉터를 연동한 Fetch 응답 핸드오프 구현
  • 05인라인 크기 오버헤드를 막기 위한 빌드 타임 8KB Output Limit 자동 검증

RECOMMENDATION

웹뷰 기반 하이브리드 앱이나 SPA 환경에서 LCP/FCP 로딩 성능 향상을 고민하는 프론트엔드 개발자에게 적극 추천합니다. 번들러 플러그인을 활용한 크리티컬 패스 최적화와 메인 앱과의 데이터 변환 어댑터 패턴 등 실무에 즉시 적용 가능한 아이디어를 얻을 수 있습니다.

The Problem

배달의민족 B마트 등 커머스 웹뷰는 네이티브 앱과 달리 HTML, JS 번들 다운로드 및 실행 후 API를 요청하는 순차적 워터폴 구조로 인해 화면 로딩 속도가 느렸습니다. 네트워크 환경이나 기기 성능이 낮을수록 로딩 지연으로 인한 이탈률 상승 및 주문 전환율 감소 우려가 존재했습니다.

The Solution

HTML 파싱 직후 API prefetch, LCP 이미지 preload, 디바이스 인셋 설정을 먼저 실행하는 인라인 스크립트 전략을 도입했습니다. 이를 모노레포에 쉽게 적용하고 메인 앱과 코드 및 타입을 공유할 수 있도록 Vite 기반의 번들러 플러그인인 'critical-script'를 직접 개발했습니다.

The Result

가게홈 및 상품상세 등 실사용자 데이터 집계 결과 LCP 지표가 25~35% 균등하게 개선되었습니다. 또한 FCP 및 레이아웃 깜빡임을 크게 완화하여 80여 개 이상의 사내 주요 웹뷰 페이지로 성공적으로 확대 적용되었습니다.

Trade-off

인라인 스크립트는 네트워크 왕복 시간을 병렬화할 뿐 백엔드 API 응답 시간이나 렌더링 CPU 시간 자체를 절감하지는 못합니다. 또한 메인 앱과 독립된 런타임이므로 서드파티 라이브러리 미지원에 따른 어댑터 작성이 필요하며, 인라인 용량 증가 방지를 위한 8KB 크기 제한 관리가 수반됩니다.

03

Key Concepts

Concept · 01

critical-script (번들러 플러그인)

페이지 단위 인라인 스크립트를 esbuild로 압축/번들링하여 빌드 타임에 HTML <head> 내에 직접 삽입해주는 Vite 기반의 번들러 플러그인입니다. 임계 경로(Critical Path) 로딩을 번들 다운로드 이전에 수행하도록 돕습니다.

  • *.critical.ts 파일 경로를 감지하여 IIFE 형태로 번들링 후 React 컴포넌트로 변환
  • 인라인 스크립트 용량이 8KB를 초과할 경우 빌드를 실패시키는 안전장치 포함
Concept · 02

API Prefetching & 캐시 핸드오프

메인 JavaScript 번들이 로드되어 실행되기 전에 HTML 파싱 단계에서 미리 fetch를 통해 백엔드 API 요청을 보낸 뒤 캐싱하는 기법입니다.

  • 인라인 스크립트가 Fetch API 요청 Promise를 window 전역 객체 캐시에 저장
  • 메인 앱 실행 시 Axios Request Interceptor가 캐시를 확인하여 즉시 응답을 채택
Concept · 03

LCP / FCP 리소스 Preloading

화면 초기 진입 시 가장 큰 영역을 차지하는 이미지(LCP)나 첫 콘텐츠가 나타나는 시점(FCP)을 당기기 위해 필요한 데이터 및 리소스를 사전에 로드하는 전략입니다.

  • API prefetch 응답의 메인 이미지 URL을 읽어 <link rel='preload'>를 HTML 헤드에 즉시 삽입
  • AppBridge를 통해 네이티브 디바이스 인셋을 미리 받아 CSS 변수로 지정하여 스켈레톤 UI 위치 오차 방지