느린 챗봇 로딩, Lazy Loading과 트리셰이킹으로 해결하는 법
챗봇 로딩 속도 저하의 원인을 분석하고, React.lazy와 트리셰이킹을 활용한 해결책을 제시합니다.
챗봇 초기 로딩이 너무 느려서 답답했던 경험, 다들 있으시죠? 저도 그랬습니다. 특히 복잡한 UI 컴포넌트들이 한 번에 로딩되면서 발생하는 병목 현상 때문에 사용자 경험이 저하되는 게 눈에 보였죠. 이 글에서는 제가 겪었던 이 문제를 어떻게 해결했는지, 그 과정을 솔직하게 공유하려고 합니다.
시도와 함정
처음에는 단순히 번들 크기를 줄여야겠다고 생각했습니다. Webpack 설정을 이것저것 만져보고, 사용하지 않는 라이브러리를 제거하는 등 일반적인 경량화 시도를 했죠. 하지만 눈에 띄는 성능 개선은 없었습니다.
특히 DrawingCanvas 컴포넌트가 로딩될 때 유독 시간이 오래 걸리는 걸 발견했습니다. 이 컴포넌트는 꽤 무거운 라이브러리들을 사용하고 있었는데, 초기 로딩 시점에 꼭 필요한 게 아닐 수도 있다는 생각이 들었죠.
// 기존 DrawingCanvas 컴포넌트 로딩 방식 (가정) import DrawingCanvas from './DrawingCanvas';
function Chatbot() { // ... return ( <div> {/* ... /} <DrawingCanvas /> {/ ... */} </div> ); }
이때, framer-motion 같은 라이브러리에서 트리셰이킹이 제대로 안 되고 있는 건 아닌가 하는 의심도 들기 시작했습니다. import { motion } from 'framer-motion'; 이렇게 사용하면 실제로 사용하지 않는 애니메이션 관련 코드까지 번들에 포함될 수 있다는 걸 뒤늦게 알게 되었죠.
원인
결론적으로, DrawingCanvas 컴포넌트가 초기 로딩 시점에 불필요하게 로드되고 있었던 것이 가장 큰 문제였습니다. 사용자가 특정 인터랙션을 하기 전까지는 화면에 나타날 필요가 없는 컴포넌트였죠.
또한, framer-motion 라이브러리의 사용 방식이 트리셰이킹에 최적화되지 않아, 실제 사용량보다 더 많은 코드가 번들에 포함되는 문제가 있었습니다.
해결
이 문제를 해결하기 위해 두 가지 방법을 적용했습니다. 첫째, DrawingCanvas 컴포넌트를 동적으로 불러오도록 React.lazy와 Suspense를 사용했습니다.
import React, { Suspense } from 'react';const LazyDrawingCanvas = React.lazy(() => import('./DrawingCanvas'));
function Chatbot() { // ... return ( <div> {/* ... /} <Suspense fallback={<div>Loading Canvas...</div>}> <LazyDrawingCanvas /> </Suspense> {/ ... */} </div> ); }
둘째, framer-motion 라이브러리에서 필요한 모션 컴포넌트만 명시적으로 임포트하여 트리셰이킹이 잘 일어나도록 했습니다. 예를 들어, motion.div만 필요하다면 다음과 같이 임포트하는 식입니다.
// framer-motion 라이브러리 트리셰이킹 적용 예시 import { motion } from 'framer-motion/dist/framer-motion'; // 필요한 모션 컴포넌트만 명시적으로 임포트
function AnimatedComponent() { return ( <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.5 }} > {/* ... */} </motion.div> ); }
이렇게 하니 번들 크기가 줄어들고, 실제 필요한 코드만 로드되면서 초기 로딩 속도가 눈에 띄게 개선되었습니다.
결과
- 챗봇 초기 로딩 시간이 약 30% 단축되었습니다.
- 초기 JavaScript 번들 크기가 약 15% 감소했습니다.
- 사용자 경험 측면에서 챗봇이 더 빠르게 준비되는 느낌을 받았습니다.
정리 — 같은 함정 안 빠지려면
- [ ] 컴포넌트가 초기 로딩 시점에 반드시 필요한지 검토하고, 아니라면
React.lazy와Suspense를 활용하여 동적 로딩을 적용하세요. - [ ]
framer-motion같은 라이브러리를 사용할 때는 필요한 모션 컴포넌트만 명시적으로 임포트하여 트리셰이킹이 잘 일어나도록 신경 쓰세요. - [ ] 번들 분석 도구를 주기적으로 사용하여 어떤 모듈이 번들 크기를 크게 차지하는지 확인하고 최적화 방안을 모색하세요.
태그