본문 바로가기

성능 프로파일링

Chrome Performance 기록과 Lighthouse 지표로 CPU·렌더링·네트워크 병목을 측정하고 개선 전후를 비교합니다.

앞 글 고급 디버깅 기법에서는 개발자 도구로 논리 오류의 원인을 찾아 고치는 방법을 익혔습니다. 이제 코드가 올바르게 동작하는지 확인하고, 문제가 생기면 원인을 추적할 수 있게 되었습니다. 하지만 올바르게 동작하는 것만큼 중요한 것이 얼마나 빠르고 효율적으로 동작하는지입니다.

웹 애플리케이션의 성능은 사용 경험에 바로 영향을 줍니다. 느린 로딩, 끊기는 스크롤, 반응하지 않는 화면은 사용자를 떠나게 만들고, 빠르고 매끄러운 화면은 만족도와 참여를 높입니다. 성능 프로파일링(performance profiling)은 애플리케이션이 실행되는 동안 CPU 사용량, 네트워크 활동, 메모리, 렌더링을 자세히 기록해, 무엇이 성능을 떨어뜨리는 병목(bottleneck)인지 찾아내는 과정입니다. 이 글에서는 Chrome 개발자 도구의 Performance 패널과 Lighthouse로 성능을 측정하고 분석해 개선 방법을 찾는 과정을 정리합니다.


같은 조건에서 측정하기

동일 조건 성능 조사 루프

PROCESS · B99 WEB FUNDAMENTALS

동일 조건 성능 조사 루프

고정된 사용자 시나리오를 기록하고 network·script·layout·paint 비용을 분리한 뒤 한 변경씩 재측정한다. LCP·INP·CLS는 서로 다른 사용자 경험과 병목을 가리킨다.

동일 조건 성능 조사 루프fix a scenario and conditions, capture a trace, isolate the dominant cost, change one cause, and compare the same run 1. 기준 고정입력 · 환경 · 기대 결과2. 증거 수집trace · network · CPU 비용3. 한 원인 변경가장 작은 수정 단위4. 같은 조건 검증전후 비교 · 회귀 확인같은 조건에서 반복 측정 · 기능 회귀도 확인
동일 조건 성능 조사 루프fix a scenario and conditions, capture a trace, isolate the dominant cost, change one cause, and compare the same run. 모바일에서도 같은 노드와 분기·귀환을 세로로 배치한다. 1. 기준 고정 입력 · 환경 · 기대 결과 2. 증거 수집 trace · network · CPU 비용 3. 한 원인 변경 가장 작은 수정 단위 4. 같은 조건 검증 전후 비교 · 회귀 확인 같은 조건에서 반복 측정 · 기능 회귀도 확인

URL·데이터·기기·CPU/네트워크 제한·캐시 조건을 기록하고 같은 시나리오를 반복 측정한다. 한 번의 실행 차이를 바로 개선 효과로 단정하지 않는다.

위 그림은 성능을 조사하는 네 단계의 순환입니다. 먼저 측정할 사용자 시나리오와 입력, 환경, 기대 결과를 고정해 기준을 정합니다. 그다음 그 시나리오를 기록한 trace와 네트워크, CPU 비용 같은 정보를 모으고, 그중 가장 큰 비용을 차지하는 원인 하나를 가장 작은 단위로 바꿉니다. 마지막으로 같은 조건에서 다시 측정해 바꾸기 전후를 비교하고, 기능이 깨지지 않았는지도 확인합니다.

그림 아래의 설명처럼 URL, 데이터, 기기, CPU와 네트워크 속도 제한, 캐시 조건을 기록해 두고 같은 시나리오를 여러 번 측정합니다. 측정값은 실행할 때마다 조금씩 달라지므로, 한 번 실행한 결과의 차이를 바로 개선 효과로 단정하지 않습니다. 또 Core Web Vitals의 세 지표인 LCP, INP, CLS는 서로 다른 사용 경험과 병목을 가리키므로, 어떤 지표가 나빠졌는지부터 나눠 봐야 합니다.

성능을 개선하면 여러 이점이 있습니다. 빠르게 반응하면 만족도가 높아지고 이탈이 줄며, 쇼핑몰 같은 서비스에서는 매출로 이어지기도 합니다. 불필요한 계산과 전송을 줄이면 기기의 배터리를 덜 쓰고, 성능이 낮은 기기나 느린 네트워크를 쓰는 사용자도 서비스를 원활하게 쓸 수 있습니다. Google은 Core Web Vitals를 검색 순위 시스템에 활용하지만, 좋은 지표만으로 높은 순위가 보장되지는 않으며 콘텐츠의 관련성 같은 다른 요소도 함께 작용합니다(Google의 Core Web Vitals 안내).


Performance 패널

Performance 패널은 페이지를 불러오는 순간부터 사용자의 동작까지, 실행되는 동안의 모든 활동을 기록해 시각적으로 보여 줍니다. 기록에는 네트워크 요청, 자바스크립트 실행, 스타일 계산, 레이아웃, 그리기가 시간 순서대로 담기므로, 화면이 버벅일 때 어느 작업이 시간을 차지했는지 찾을 수 있습니다. 아래에서는 기록하는 방법, 결과를 읽는 방법, 찾은 원인을 고치는 방향을 차례로 봅니다.

기록하고 분석하기

F12나 Ctrl+Shift+I(macOS는 Cmd+Option+I)로 개발자 도구를 열고 Performance 패널을 고릅니다. 둥근 Record 버튼을 누르거나 Ctrl+E(macOS는 Cmd+E)로 기록을 시작한 뒤, 측정하고 싶은 시나리오, 예를 들어 스크롤이나 버튼 클릭, 애니메이션을 실행합니다. 시나리오가 끝나면 Stop 버튼을 눌러 기록을 멈추고, 그러면 자세한 분석 결과가 나타납니다. 페이지 로딩을 측정하려면 새로고침과 함께 기록하는 버튼을 씁니다.

결과를 읽는 방법

결과의 위쪽 개요와 각 트랙에서는 CPU 활동, 네트워크 요청, 프레임을 시간 순서로 볼 수 있습니다. 표시 위치와 색은 도구 버전에 따라 다를 수 있습니다. Frames 트랙에서는 각 프레임에 걸린 시간과 놓친 프레임을 확인합니다. 60Hz 화면의 프레임 간격은 약 1000 / 60 = 16.7ms, 120Hz는 약 8.3ms인데, 이 시간에는 브라우저의 스타일 계산, 레이아웃, 페인트도 들어가므로 모두 자바스크립트에 쓸 수 있는 시간은 아닙니다. CPU 활동은 Scripting, Rendering, Painting 같은 범례와 이벤트 이름을 함께 읽고, 색만 보고 작업의 종류나 병목을 단정하지 않습니다. 타임라인에서 구간을 드래그하면 그 구간만 확대해 볼 수 있습니다.

Summary는 고른 구간에서 Loading, Scripting, Rendering, Painting 같은 분류마다 쓴 시간을 합쳐 보여 줍니다. 가장 많은 시간을 차지하는 분류가 병목일 가능성이 높습니다.

Main 트랙은 메인 스레드에서 일어난 자바스크립트 실행, 스타일 계산, 레이아웃, 페인트를 시간 순서와 호출 관계로 보여 주는 가장 중요한 트랙입니다. 불꽃 차트(flame chart)에서 가로 폭은 실행 시간, 세로로 쌓인 층은 호출 관계를 나타내므로, 높이 쌓였다고 느린 작업인 것은 아닙니다. 항목을 클릭하면 아래쪽에 자세한 정보와 호출 스택이 나와, 어떤 코드에서 그 작업이 시작되었는지 추적할 수 있습니다.

메인 스레드의 한 작업이 50ms를 넘으면 긴 작업(long task)이라고 부르며, Chrome은 빨간 삼각형과 50ms를 넘은 부분의 음영으로 표시합니다. 긴 작업은 입력 처리와 렌더링을 늦출 수 있지만, 긴 작업이 없다고 매 프레임을 제시간에 그렸다고 판정할 수는 없습니다.

아래쪽의 Bottom-Up 탭은 고른 구간에서 같은 활동에 쓴 시간을 합쳐 보여 줍니다. Self Time은 그 활동 자체에 쓴 시간이고, Total Time은 그 활동이 부른 자식 활동까지 합친 시간이며, 각 열로 정렬할 수 있습니다. Call Tree 탭은 어떤 함수가 어떤 함수를 불렀는지 계층으로 보여 주고, Event Log 탭은 모든 이벤트를 시간 순서로 나열합니다. 같은 함수의 자식 비용을 Total Time에 다시 더하면 시간이 두 번 계산되므로, 비교할 열을 먼저 정해 둡니다. 판독 기준은 Chrome의 Performance 기능 문서에 정리되어 있습니다.

개선 방향

Performance 패널에서 찾은 병목에 따라 개선 방법을 고릅니다. 긴 작업을 만드는 자바스크립트는 계산을 줄이거나 나누고, 무거운 계산은 웹 워커로 옮깁니다. DOM을 바꿀 때는 어떤 속성을 바꾸는지와 읽기와 쓰기의 순서에 따라 스타일 계산과 레이아웃 비용이 달라지므로, 불필요한 변경과 강제 레이아웃을 줄이고 관련 작업을 묶습니다. 가상 DOM을 쓰는 라이브러리라도 계산과 렌더링의 범위를 확인해야 하며, 그것만으로 성능이 저절로 좋아지지는 않습니다. CSS는 지나치게 복잡한 선택자나 다시 레이아웃을 일으키는 속성 변경을 줄입니다.

이미지는 화면에 표시되는 크기에 맞게 준비합니다. 화면 아래쪽의 이미지는 지연 로딩을 쓸 수 있지만, 첫 화면에서 가장 큰 콘텐츠인 LCP 후보 이미지를 지연 로딩하면 주요 콘텐츠가 늦게 보일 수 있습니다(web.dev의 LCP 최적화). 네트워크는 번들링과 캐싱으로 반복 요청과 전송을 줄이고, 코드 분할(code splitting)은 처음 받는 코드를 줄이는 대신 나중에 나눈 코드를 더 요청하게 되므로 요청 수와 첫 로딩 비용을 나눠 확인합니다.

애니메이션에는 레이아웃과 페인트를 다시 하지 않아도 되는 transform과 opacity를 우선 씁니다. 다만 이 속성들이 GPU 가속이나 더 빠른 실행을 보장하는 것은 아니므로 실제 비용을 측정해 확인합니다. 화면을 갱신하는 코드는 Canvas API 기초에서 본 requestAnimationFrame()으로 브라우저의 렌더링 주기에 맞출 수 있습니다.


Core Web Vitals로 원인 나누기

Core Web Vitals 원인 진단 지도

FLOWCHART · B99 WEB FUNDAMENTALS

Core Web Vitals 원인 진단 지도

저하된 지표가 LCP·INP·CLS 중 무엇인지 먼저 구분한 뒤, 각 지표에 맞는 network·main-thread·rendering·stability 증거를 확인한다.

Core Web Vitals 원인 진단 지도저하된 LCP, INP, CLS를 각각 network와 render delay, main-thread interaction, layout stability 증거로 라우팅하고 같은 시나리오에서 재측정하는 진단 지도 현장·실험실에서 저하 확인같은 URL · 기기 · 시나리오 기록어떤 사용자 경험이나빠졌는가?주 콘텐츠가 늦게 보임LCP · LOADlargest element timing입력 뒤 paint가 늦음INP · INTERACTinteraction latency예상치 못한 위치 이동CLS · STABILITYlayout shift scoreWaterfallLCP breakdownTTFB · resource loadrender delayInteraction · long taskhandler · main threadlayout / paintLayout Shifts track크기 없는 mediafont · 삽입 DOM원인 하나 변경 → 같은 시나리오 재측정lab 개선을 field data와 함께 확인LCPINPCLS
Core Web Vitals 원인 진단 지도저하된 LCP, INP, CLS를 각각 network와 render delay, main-thread interaction, layout stability 증거로 라우팅하고 같은 시나리오에서 재측정하는 진단 지도. 모바일에서도 같은 노드와 분기·귀환을 세로로 배치한다. 현장·실험실에서 저하 확인 같은 URL · 기기 · 시나리오 기록 어떤 사용자 경험이 나빠졌는가? 주 콘텐츠가 늦게 보임 LCP · LOAD largest element timing Waterfall LCP breakdown TTFB · resource load render delay 입력 뒤 paint가 늦음 INP · INTERACT interaction latency Interaction · long task handler · main thread layout / paint 예상치 못한 위치 이동 CLS · STABILITY layout shift score Layout Shifts track 크기 없는 media font · 삽입 DOM 원인 하나 변경 → 같은 시나리오 재측정 lab 개선을 field data와 함께 확인 LCP INP CLS

Core Web Vitals는 LCP·INP·CLS다. 일반 Lighthouse 로딩 감사에는 사용자 상호작용이 없어 INP를 직접 측정하지 못한다. 상호작용 trace로 원인을 재현하고 현장 데이터로 실제 방문의 개선을 확인한다.

위 그림은 나빠진 지표에 따라 확인할 정보를 고르는 지도입니다. 먼저 실제 사용자의 현장 데이터(field data)나 실험실 측정(lab data)에서 성능 저하를 확인하고, 같은 URL과 기기, 시나리오를 기록해 둡니다. 그다음 어떤 사용 경험이 나빠졌는지 묻습니다.

주요 콘텐츠가 늦게 보인다면 LCP(Largest Contentful Paint)의 문제입니다. 네트워크의 요청 시간표와 LCP의 구성, 즉 첫 응답 시간(TTFB), 리소스를 받는 시간, 받은 뒤 그리기까지의 지연을 나눠 봅니다. 입력한 뒤 화면이 늦게 바뀐다면 INP(Interaction to Next Paint)의 문제로, 상호작용과 긴 작업, 이벤트 핸들러와 메인 스레드, 그 뒤의 레이아웃과 페인트를 확인합니다. 화면의 요소가 예상하지 못하게 움직인다면 CLS(Cumulative Layout Shift)의 문제로, Layout Shifts 트랙에서 크기를 정하지 않은 이미지나 동영상, 글꼴이 바뀌며 생긴 이동, 나중에 끼워 넣은 DOM을 찾습니다.

원인 하나를 바꾼 뒤에는 같은 시나리오로 다시 측정하고, 실험실에서의 개선이 현장 데이터에서도 나타나는지 함께 확인합니다. 그림 아래의 설명처럼 일반적인 Lighthouse의 페이지 로드 감사에는 사용자 상호작용이 없어 INP를 직접 측정하지 못하므로, 상호작용을 재현한 Performance 기록으로 원인을 찾고 현장 데이터로 실제 방문에서 나아졌는지 확인합니다.

더 깊이: INP 값은 어떻게 정해질까

INP는 2024년 3월 12일에 FID(First Input Delay)를 대신해 Core Web Vitals에 들어갔습니다. FID가 첫 상호작용 하나의 입력 지연만 쟀다면, INP는 방문하는 동안의 클릭, 탭, 키 누름을 모두 관찰합니다. 마우스를 올리는 것, 스크롤, 확대는 여기에 들어가지 않습니다. 한 상호작용의 지연은 세 부분의 합으로, 이벤트 핸들러가 시작되기까지 기다린 입력 지연(input delay), 핸들러를 실행한 처리 시간(processing duration), 핸들러가 끝난 뒤 다음 화면이 그려지기까지의 표시 지연(presentation delay)입니다.

페이지의 INP는 그 방문에서 가장 오래 걸린 상호작용의 지연입니다. 다만 상호작용이 아주 많은 페이지에서 우연히 튄 값 하나가 결과를 정하지 않도록, 상호작용 50번마다 가장 긴 것 하나를 빼고 고릅니다. 그래서 INP를 줄이려면 평균이 아니라 가장 느린 조작을 찾아야 합니다. 이렇게 구한 방문별 값을 모아 75번째 백분위가 200ms 이하이면 좋음, 500ms를 넘으면 나쁨으로 판정합니다.

세 부분을 나눠 보면 고칠 곳이 달라집니다. 입력 지연이 길면 그때 다른 긴 작업이 메인 스레드를 차지하고 있었다는 뜻이고, 처리 시간이 길면 핸들러 자체가 무겁다는 뜻이며, 표시 지연이 길면 핸들러가 바꾼 DOM의 스타일 계산과 레이아웃이 오래 걸린 것입니다. 정의는 web.dev의 INP 설명에 있습니다.


Lighthouse

Lighthouse는 Google이 만든 오픈 소스 자동화 도구로, 웹 페이지의 성능, 접근성, 권장 사항, SEO를 감사(audit)하고 개선 방법을 제안합니다. 개발자 도구 안에서 실행하거나 Node.js의 명령줄 도구로 실행할 수 있습니다.

Lighthouse 실행

개발자 도구에서 Lighthouse 패널을 고르고, Performance, Accessibility, Best Practices, SEO 가운데 측정할 분류를 선택합니다. 예전에 있던 PWA 분류는 Lighthouse 12에서 없어졌습니다. 기기는 Mobile이나 Desktop 가운데 실제 사용자의 기기를 기준으로 고르고, 모드와 CPU, 네트워크 제한, 캐시 조건, 도구 버전을 기록해 둡니다. Mobile 결과와 Desktop 결과를 서로의 개선 전후 값으로 비교하면 안 됩니다.

페이지 로드 모드에서 설정을 확인한 뒤 감사를 실행합니다. 공식 안내는 Analyze page load로 설정을 열고 Run audit로 실행하는 순서이지만, Chrome의 버전과 모드에 따라 버튼 이름이나 화면이 다를 수 있으므로 설정을 여는 단계와 실행하는 단계를 구분해서 진행합니다. 감사가 끝나면 분류마다 점수와 개선 제안이 표시됩니다.

Lighthouse의 지표

Lighthouse의 실험실 로딩 지표와 Core Web Vitals는 구분해서 읽어야 합니다. 지금의 Core Web Vitals는 LCP, INP, CLS 세 가지이며, 다음 지표가 모두 여기에 속하지는 않습니다.

FCP(First Contentful Paint)는 처음으로 글자나 이미지가 그려지는 시점으로, 사용자가 무언가를 보기 시작하는 순간입니다. LCP는 뷰포트에서 가장 큰 이미지, 동영상, 글 덩어리가 그려지는 시점으로, 사용자가 페이지의 주요 콘텐츠를 알아보는 순간입니다. CLS는 페이지를 쓰는 동안 일어난 예상하지 못한 레이아웃 이동을 세션 창(session window)마다 합산한 값 가운데 가장 큰 값으로, 로딩이 끝난 뒤의 이동도 포함합니다. Speed Index는 페이지의 내용이 눈에 보이게 얼마나 빨리 채워지는지를 나타냅니다.

INP는 페이지를 방문하는 동안 일어난 클릭, 탭, 키보드 입력이 다음 화면에 반영되기까지 걸린 시간을 관찰해 대표 반응 시간으로 나타내며, 200ms 이하가 좋은 상태입니다. 예전의 TTI(Time to Interactive)는 상호작용할 수 있게 되는 시점을 추정하던 지표로, Lighthouse 10에서 없어졌으므로 지금 보고서에서는 찾을 수 없습니다.

Lighthouse의 개선 제안에서 지표에 영향을 주는 문제를 확인합니다. 예전 보고서의 Opportunities와 Diagnostics 중심 구성은 최신 버전에서 Insights 중심으로 바뀌었으므로, 쓰는 버전의 보고서 구조를 따르면 됩니다. 이미지 크기 조정, 렌더링을 막는 리소스 제거, 자바스크립트 실행 시간 단축 같은 제안이 대표적입니다.

현장 Core Web Vitals의 좋은 기준은 LCP 2.5초 이하, INP 200ms 이하, CLS 0.1 이하입니다. 모바일과 데스크톱을 나눠, 실제 방문의 75번째 백분위 값이 세 기준을 모두 만족하는지 봅니다. 한 번 실행한 Lighthouse 점수나 한 번의 클릭 시간은 이 현장 판정을 대신하지 못합니다(web.dev의 Web Vitals).


개선 효과를 수치와 동작으로 판정하기

다음 값은 계산을 연습하기 위한 가상의 측정값이며, 이 사이트를 측정한 결과가 아닙니다. 같은 URL, 브라우저, 모바일 모드, CPU와 네트워크 제한, 빈 캐시 조건에서 상품 목록의 첫 로딩을 바꾸기 전과 후에 세 번씩 기록했다고 가정합니다.

비교 항목바꾸기 전 3회바꾼 뒤 3회중앙값 비교
LCP(ms)2800, 3000, 29002300, 2400, 25002900 → 2400
가장 긴 메인 스레드 작업(ms)120, 110, 13045, 48, 47120 → 47

LCP의 중앙값은 500ms, 약 17.2% 줄었습니다. 바꾼 뒤에도 이미지가 올바르게 표시되는지, 상품 개수와 정렬, 버튼 동작이 그대로인지 확인해야 개선이라고 할 수 있습니다. 가장 긴 작업이 47ms로 줄어 긴 작업 기준을 넘지 않게 되었지만, 60Hz의 프레임 간격 16.7ms보다는 길기 때문에 스크롤이 매끄럽다는 결론은 따로 검증해야 합니다. 가장 느린 한 번만 골라 비교하지 말고, 반복한 값과 그 편차도 함께 남깁니다.

// 브라우저 Console 또는 Node.js에서 실행하는 계산 예제
function median3(values) {
    return [...values].sort((a, b) => a - b)[1];
}

const before = median3([2800, 3000, 2900]);
const after = median3([2300, 2400, 2500]);
console.log(before, after, before - after); // 2900 2400 500

세 번 측정한 값을 정렬해 가운데 값을 고르는 함수입니다. 중앙값은 한 번 튀는 값의 영향을 덜 받으므로, 여러 번 측정한 결과를 비교할 때 평균과 함께 자주 씁니다.


정리

  • 성능 프로파일링은 시나리오와 환경을 고정하고 기록해, 가장 큰 비용의 원인을 하나씩 바꾸며 같은 조건에서 다시 측정하는 반복 과정입니다.
  • Performance 패널의 Main 트랙과 불꽃 차트, Bottom-Up의 Self Time과 Total Time으로 어떤 작업이 시간을 쓰는지 찾고, 50ms를 넘는 긴 작업을 확인합니다.
  • 프레임 간격은 60Hz에서 약 16.7ms이며 브라우저의 렌더링 작업도 포함하므로, 긴 작업이 없다고 매끄럽다고 단정하지 않습니다.
  • Core Web Vitals는 LCP, INP, CLS이며, 나빠진 지표에 따라 네트워크와 렌더링, 메인 스레드의 상호작용, 레이아웃 이동을 나눠 봅니다.
  • Lighthouse는 실험실 측정으로 개선 제안을 주지만, 페이지 로드 감사는 INP를 직접 측정하지 못하고 현장 데이터의 판정을 대신하지 못합니다.
  • 개선은 여러 번 측정한 값의 중앙값과 편차로 비교하고, 기능이 그대로 동작하는지도 함께 확인합니다.

연습 문제

1. 긴 작업의 초과분

같은 조건의 로딩 기록에서 메인 스레드 작업이 40ms, 70ms, 120ms였습니다. 각 작업이 50ms를 넘은 만큼과 그 합은 얼마일까요? 이 합만으로 실제 방문의 INP가 200ms 이하라고 판정할 수 있을까요?

해설 보기

넘은 만큼은 max(0, 작업 시간 - 50)이므로 각각 0ms, 20ms, 70ms이고, 합은 90ms입니다. 이것은 주어진 작업의 초과분을 계산한 것일 뿐이며, Lighthouse의 TBT(Total Blocking Time)라고 부르려면 그 도구가 합산하는 구간과 작업 조건까지 맞아야 합니다(web.dev의 TBT).

INP에는 입력이 처리되기까지 기다린 시간, 이벤트 처리 시간, 다음 화면을 그리기까지의 지연이 모두 들어갑니다. 로딩 중 작업의 합만으로는 사용자 상호작용의 INP를 판정할 수 없으며, 실제 입력 시나리오의 기록과 현장 데이터를 확인해야 합니다(web.dev의 INP).

2. 가장 긴 작업의 개선 비율

표의 가장 긴 메인 스레드 작업은 중앙값이 120ms에서 47ms로 줄었습니다. 줄어든 시간과 비율을 계산해 보세요. 이 결과만으로 “스크롤이 매끄러워졌다”고 기록할 수 있을까요?

해설 보기

120 - 47 = 73ms 줄었고, 비율은 73 / 120 ≈ 60.8%입니다. 같은 조건에서 세 번씩 측정한 중앙값이므로 첫 로딩의 긴 작업이 줄었다는 기록은 할 수 있습니다.

하지만 이 기록은 첫 로딩을 측정한 것이고, 47ms도 60Hz의 프레임 간격 16.7ms보다 깁니다. 스크롤이 매끄러운지는 스크롤 시나리오를 따로 기록해 프레임이 제시간에 그려지는지 확인한 뒤에야 말할 수 있습니다.

3. 지연 로딩한 대표 이미지

첫 화면 맨 위의 큰 대표 이미지가 LCP 요소인데, <img src="hero.jpg" loading="lazy">로 작성되어 있습니다. LCP에 어떤 영향이 있을까요? 어떻게 고치면 될까요?

해설 보기

LCP가 늦어질 수 있습니다. loading="lazy"는 이미지가 화면에 들어올 때쯤 불러오도록 미루는 설정이라, 브라우저가 첫 화면의 레이아웃을 계산한 뒤에야 이미지를 요청하게 되어 주요 콘텐츠가 늦게 보입니다.

첫 화면의 LCP 이미지는 loading="lazy"를 빼고, 필요하면 fetchpriority="high"로 먼저 받아 오게 합니다. 고친 뒤에는 같은 조건에서 LCP의 구성 가운데 리소스를 받는 시간이 줄었는지 다시 측정해 확인합니다.

이것으로 10장을 마칩니다. 10장에서는 Jest로 단위 테스트를 쓰고, 통합 테스트와 E2E 테스트로 더 큰 흐름을 검증하고, 여러 브라우저에서 호환성을 확인하고, 개발자 도구로 버그를 추적하고, 성능을 측정해 개선하는 방법까지 코드의 품질을 지키는 방법을 살펴봤습니다. 다음 장의 SPA 개념부터는 싱글 페이지 애플리케이션의 구조를 시작으로 React의 기초와 상태 관리 라이브러리, 그 밖의 유용한 프런트엔드 라이브러리를 다룹니다.