
프론트엔드 성능 최적화 시작하기: 측정하고, 병목을 찾고, 개선하기
lighthouse
프론트엔드 성능 최적화 가이드
프론트엔드 성능 최적화는 단순히 “빠르게 만든다”의 문제가 아니다.
사용자가 느끼는 경험, 즉 로딩 속도, 반응성, 부드러움을 개선하는 과정이다.
이번 글에서는 두 개의 서비스(블로그, 통계 서비스)를 기반으로 실제로 어떤 병목이 발생했고, 어떻게 분석하고 개선했는지를 정리한다.
핵심은 하나다.
감으로 최적화하지 말고, 측정하고 개선하자
1. 성능은 도구로 측정해야 한다
최적화의 시작은 항상 측정이다.
대표적으로 사용한 도구는 다음과 같다.
Chrome DevTools
Network 패널
- 어떤 리소스가 얼마나 오래 걸리는지
- 이미지, JS, API 요청의 병목 확인
Performance 패널
- CPU 사용량
- 어떤 함수가 오래 실행되는지
- 렌더링 흐름 (reflow, paint 등)
Lighthouse
- 성능 점수 기반 진단
- 개선 포인트 자동 제안
webpack-bundle-analyzer
번들 사이즈를 시각적으로 분석한다.
- 어떤 패키지가 용량을 많이 차지하는지
- 불필요한 dependency 존재 여부 확인
실제로
package-lock.json에서 불필요한 패키지를 제거하면서 번들 크기를 줄일 수 있었다.2. 이미지 최적화: 가장 쉽고 효과가 큰 영역
처음 Lighthouse를 돌렸을 때 가장 먼저 보인 문제는 이미지였다.
많은 경우 이런 실수를 한다.
“120x120이니까 120 이미지를 쓰면 되겠지?”
하지만 실제로는 그렇지 않다.
핵심 포인트
- Retina 디스플레이 대응 → 2배 사이즈 사용
- 대신 압축 + 포맷 최적화
예:
Unsplash API의 쿼리 파라미터를 활용해 이미지 사이즈, 포맷, 품질을 조정했다.
추가로 중요한 것: CDN
이미지 최적화에서 빠질 수 없는 요소가 CDN이다.
- 사용자와 가까운 서버에서 리소스 제공
- latency 감소
이미지 최적화 + CDN 적용만으로도 Lighthouse 점수가 눈에 띄게 상승했다.
3. 병목 코드 최적화: 작은 코드가 전체를 느리게 만든다
Performance 패널을 보면 예상과 다르게 UI가 아니라 JS가 병목인 경우가 많다.
이번 케이스에서는
ArticleList 렌더링이 매우 느렸고, 원인은 removeSpecialCharacter 함수였다.기존 코드의 문제
- 문자열을 순회하면서
- substring + concat 반복
- O(n²)에 가까운 구조
문자열이 길어질수록 급격히 느려짐
개선 방식
- 정규식 + replace 사용
- 내부적으로 최적화된 엔진 활용
인사이트
성능 문제는 항상 “복잡한 곳”에서 발생하지 않는다 오히려 작은 유틸 함수 하나가 전체 성능을 망칠 수 있다
4. 코드 분할과 지연 로딩
초기 로딩이 느린 가장 큰 이유 중 하나는
“필요하지 않은 코드까지 한 번에 로딩하기 때문”
동적 import
- 필요한 시점에만 로딩
- 초기 번들 크기 감소
React Suspense
- 로딩 UI 처리
- 사용자 경험 개선
핵심 인사이트
- 모든 코드를 미리 로딩할 필요 없다
- “언제 필요한가” 기준으로 분할해야 한다
5. 텍스트 압축 (Gzip / Brotli)
JS, CSS, HTML은 전부 텍스트다.
👉 압축이 가능하다
프로덕션 환경에서 압축을 적용하면:
- 네트워크 전송량 감소
- 로딩 속도 개선
👉 개발 환경과 프로덕션 환경은 반드시 다르게 설정해야 한다
6. Jank: “느린 것”보다 더 중요한 문제
사용자는 “조금 느린 것”보다
버벅이는 것(Jank) 을 더 크게 느낀다
기준: 16.7ms
한 프레임 안에 작업이 끝나지 않으면
- 끊김 발생
실제 문제
막대 그래프 애니메이션에서 끊김 발생
원인:
- CPU 작업 과다
- 렌더링 타이밍 밀림
7. 브라우저 렌더링 파이프라인 이해하기
성능 최적화의 핵심은
👉 브라우저가 어떻게 화면을 그리는지 이해하는 것
렌더링 과정
문제: Reflow & Repaint
Reflow
- 레이아웃 다시 계산
- 가장 비용 큼
Repaint
- 색상 변경
- 레이아웃은 유지
해결 전략
transform / opacity 사용
- layout 건너뜀
- GPU 처리 (composite 단계)
- 애니메이션 성능 크게 개선
8. will-change: 양날의 검
브라우저에게 미리 알려주는 힌트
좋은 점
- 애니메이션 부드러움 증가
문제
- GPU / 메모리 사용 증가
- 과도하면 오히려 성능 저하
실전 전략
“항상 쓰지 말고, 필요한 순간에만”
인사이트
브라우저는 이미 최적화를 잘한다 우리가 개입하는 순간 오히려 망칠 수 있다
9. 이미지 사전 로딩 (Preload)
사용자가 이미지를 보기 전에 미리 다운로드
또는
언제 사용해야 할까?
- hover 시 바로 보여야 하는 UI
- modal 이미지
- 다음 화면 예상되는 경우
중요한 고민
“몇 개까지 preload 해야 할까?”
너무 많이 하면:
- 네트워크 낭비
- 메모리 증가
👉 항상 trade-off 존재
최종 인사이트
이번 최적화를 하면서 가장 크게 느낀 건 이거다.
1. 성능은 “감”이 아니라 “측정”이다
- Lighthouse
- Performance 패널
없이는 절대 정확히 알 수 없다
2. 병목은 예상과 다르게 나타난다
- 이미지일 수도 있고
- JS일 수도 있고
- 애니메이션일 수도 있다
3. 작은 코드가 큰 영향을 준다
- removeSpecialCharacter 같은 함수 하나가
- 전체 UX를 망칠 수 있다
4. 브라우저를 이해해야 최적화할 수 있다
- 렌더링 파이프라인
- GPU / CPU 역할
- Reflow / Repaint
5. 최적화에는 항상 trade-off가 있다
- preload → 빠름 vs 리소스 증가
- will-change → 부드러움 vs 메모리
- 코드 분할 → 초기 로딩 vs 요청 증가
마무리
프론트엔드 성능 최적화는 “한 번 하고 끝나는 작업”이 아니다.
기능을 추가할 때마다,
코드를 수정할 때마다,
조금씩 다시 무너진다.
그래서 중요한 건 기술 자체보다
“측정하고, 원인을 찾고, 개선하는 습관”
이다.
이번 글은 그 시작이었다.