성능 최적화, 그래서 도대체 어디서부터 시작해야 할까?

김진아·2026년 6월 12일

프론트엔드 성능 최적화에 대해 공부하다 보면 자주 등장하는 말들이 있다.

  • 이미지 용량을 줄이자.
  • 폰트를 최적화하자.
  • 코드 스플리팅을 적용하자.
  • 불필요한 리렌더링을 줄이자.
  • requestAnimationFrame을 활용하자.
  • Lighthouse 점수를 개선하자.

분명 다 중요한 이야기다. 그런데 막상 실제 프로젝트에 적용하려고 하면 갑자기 막막해진다.

이미지가 문제인지, JavaScript가 문제인지, 렌더링이 문제인지 어떻게 알지?
Lighthouse에서 LCP가 느리다고 하는데, 그래서 어느 코드를 수정해야 하지?
Performance 탭을 열기는 했는데, 복잡한 그래프 중에서 무엇을 봐야 하지?

나 역시 합동세미나에서 직접 성능 최적화를 적용해보려고 하면서 같은 문제를 겪었다.
네트워크 탭은 그나마 익숙했다. 어떤 이미지가 큰지, 어떤 요청이 늦는지는 비교적 쉽게 확인할 수 있었다. 하지만 그것만으로는 부족했다. 화면에 리소스가 늦게 도착하는 문제는 찾을 수 있어도, 리소스가 이미 도착했는데 왜 화면이 늦게 그려지는지는 알기 어려웠다.

그래서 이번에는 최적화 기법을 하나씩 정리하기보다, 개발이 끝난 서비스에서 실제로 병목을 찾고 수정 방향을 정하는 흐름을 정리해보려고 한다.


최적화는 코드 수정이 아니라 디버깅이다

처음에는 성능 최적화를 “좋다고 알려진 기법을 프로젝트에 적용하는 일”이라고 생각했다.

이미지를 WebP로 바꾸고, React.memo를 붙이고, lazy loading을 적용하면 성능이 좋아질 것 같았다. 물론 실제로 도움이 될 수도 있다. 하지만 측정 없이 적용하면 무엇이 효과가 있었는지 알 수 없고, 심지어 현재 문제와 전혀 상관없는 작업을 하고 있을 수도 있다.

성능 최적화는 결국 다음 과정을 반복하는 일에 가깝다.

느린 순간을 정한다
→ 동일한 조건에서 측정한다
→ 병목이 발생한 구간을 찾는다
→ 원인을 추측한다
→ 하나를 수정한다
→ 같은 조건에서 다시 측정한다

중요한 것은 무작정 많이 고치는 것이 아니다.
어떤 문제를 해결하기 위해 무엇을 수정했고, 실제로 어떤 변화가 있었는지 확인하는 것이다.


1. 가장 먼저 할 일: “언제 느린가?”를 정하기

Performance 탭을 열자마자 복잡한 그래프를 읽으려고 하면 어렵다.
그 전에 먼저 사용자가 느끼는 문제를 구체적으로 정해야 한다.

성능 문제는 크게 두 종류로 나눌 수 있다.

첫 화면이 늦게 뜨는 경우

페이지에 처음 들어갔을 때 주요 콘텐츠가 늦게 보이는 문제다.

예를 들면 다음과 같다.

  • 흰 화면이 오래 유지된다.
  • 제목은 보이는데 대표 이미지가 한참 뒤에 나타난다.
  • 로딩 화면이 오래 유지된다.
  • 화면의 가장 중요한 콘텐츠가 늦게 등장한다.

이때는 주로 다음을 확인한다.

  • FCP
  • LCP
  • Network waterfall
  • 초기 렌더링을 막는 작업

화면은 떴지만 사용 중에 버벅이는 경우

페이지 로딩은 끝났는데 클릭, 검색, 필터링, 스크롤, 애니메이션에서 문제가 발생하는 경우다.

예를 들면 다음과 같다.

  • 검색어를 입력할 때마다 입력이 끊긴다.
  • 필터를 누르면 화면이 늦게 바뀐다.
  • 모달을 열 때 버벅인다.
  • 스크롤이 끊긴다.
  • 애니메이션이 부드럽지 않다.

이때는 주로 다음을 확인한다.

  • INP
  • Long Task
  • Main Thread
  • Scripting / Rendering / Painting
  • React Profiler
  • Frames

처음부터 모든 문제를 한 번에 해결하려고 하면 안 된다.
느린 장면 하나를 정하고, 그 장면만 기록하는 것이 중요하다.


2. 측정 조건을 먼저 고정하기

성능을 비교하려면 수정 전과 수정 후의 조건이 최대한 같아야 한다.

예를 들어 초기 로딩을 확인하고 싶다면 다음과 같은 시나리오를 고정할 수 있다.

1. 배포된 페이지를 연다.
2. DevTools를 켠다.
3. 캐시를 비운다.
4. 새로고침과 함께 Performance 기록을 시작한다.
5. 첫 화면의 주요 콘텐츠가 나타나면 기록을 종료한다.

사용자 인터랙션을 확인하고 싶다면 다음처럼 기록한다.

1. 페이지를 먼저 로딩한다.
2. Performance 기록을 시작한다.
3. 느리다고 느낀 행동을 한 번만 수행한다.
4. 바로 기록을 종료한다.

여기서 중요한 점은 행동을 너무 많이 하지 않는 것이다.

검색도 하고, 스크롤도 하고, 필터도 누르고, 모달도 열면 Performance 탭에 너무 많은 정보가 쌓인다. 그러면 어느 구간이 문제인지 판단하기가 더 어려워진다.

처음에는 정말 단순하게 기록하는 편이 좋다.

검색어 한 글자 입력하기
필터 버튼 한 번 누르기
스크롤 한 번 내리기
페이지 한 번 새로고침하기

이 정도면 충분하다.


3. Lighthouse는 출발점으로만 사용하기

성능 최적화를 시작할 때 가장 먼저 Lighthouse를 돌리는 경우가 많다.

Lighthouse는 현재 페이지의 성능 상태를 빠르게 확인하기 좋다.
FCP, LCP, CLS 등의 지표를 보여주고, 개선이 필요해 보이는 항목도 알려준다.

하지만 Lighthouse만 보고 바로 코드를 수정하기는 어렵다.

예를 들어 다음과 같은 결과를 받았다고 해보자.

LCP가 느립니다.

이것만으로는 아직 아무것도 알 수 없다.

  • 대표 이미지가 너무 큰 것인지
  • 이미지 요청이 늦게 시작된 것인지
  • 서버 응답이 늦은 것인지
  • JavaScript 실행이 끝나지 않아서 화면에 늦게 그려진 것인지

모두 가능하다.

그래서 Lighthouse는 정답을 알려주는 도구라기보다, 어느 방향을 먼저 조사해야 하는지 알려주는 출발점에 가깝다.

나는 이렇게 생각하면 가장 이해가 쉬웠다.

Lighthouse는 범인을 잡아주는 도구가 아니라,
어느 사건부터 수사해야 하는지 알려주는 도구다.


4. 첫 화면이 느리다면 LCP부터 추적하기

초기 로딩 문제를 살펴볼 때 가장 먼저 확인하기 좋은 지표는 LCP다.

LCP는 화면 안에서 가장 큰 콘텐츠가 실제로 표시되는 시점을 의미한다.
사용자가 페이지에 들어왔을 때 가장 중요하게 인식하는 콘텐츠가 언제 보였는지를 확인할 수 있다.

예를 들면 다음과 같은 요소가 LCP가 될 수 있다.

  • 메인 배너 이미지
  • 게시글 대표 이미지
  • 큰 제목 텍스트
  • 첫 화면의 큰 카드
  • 히어로 영역 이미지

Performance 탭에서 확인하는 순서

1. Performance 탭을 연다.
2. 새로고침과 함께 기록한다.
3. 기록 결과에서 LCP 시점을 찾는다.
4. LCP 항목을 클릭한다.
5. 어떤 요소가 LCP element인지 확인한다.

가장 먼저 해야 하는 일은 단순하다.

무엇이 늦게 보였는지 확인하기

이미지가 문제인지, 텍스트가 문제인지도 모르는 상태에서 무작정 이미지 최적화를 시작하면 안 된다.


5. LCP가 느린 이유를 네 구간으로 나누기

LCP element를 찾았다면, 이제 LCP가 늦어진 이유를 조금 더 구체적으로 나눠볼 수 있다.

LCP는 크게 다음 네 구간으로 나누어 생각할 수 있다.

구간의미확인할 방향
TTFBHTML의 첫 응답을 받기까지 걸린 시간서버 응답, 캐시, CDN
Resource load delayHTML을 받은 뒤 LCP 리소스 요청이 시작되기까지 걸린 시간요청 발견 시점, 우선순위
Resource load duration리소스를 실제로 다운로드하는 시간이미지 크기, 포맷, 네트워크
Element render delay리소스를 다 받았지만 화면에 그려지기까지 기다린 시간JavaScript, CSS, 렌더링 작업

이렇게 나누면 막연했던 LCP 문제가 조금씩 구체적으로 보이기 시작한다.


경우 1. 리소스 다운로드 자체가 오래 걸린다

LCP element가 큰 이미지라고 해보자.

Network 탭에서 해당 이미지를 찾아보니 파일 크기가 크고 다운로드 시간도 길다.
이 경우에는 리소스 크기 자체를 줄이는 방향을 생각할 수 있다.

예를 들면 다음과 같은 최적화가 후보가 된다.

  • 이미지 크기 줄이기
  • 이미지 포맷 변경하기
  • CDN 활용하기
  • 캐시 정책 확인하기
  • 실제 화면 크기에 맞는 이미지 제공하기

중요한 것은 “이미지 최적화는 무조건 해야 한다”가 아니다.

LCP 리소스의 다운로드 시간이 길다는 근거를 확인했기 때문에
이미지 최적화를 선택하는 것이다.


경우 2. 리소스 요청 자체가 늦게 시작된다

이번에는 이미지 파일이 그렇게 크지 않은데도 LCP가 늦다고 해보자.

Network 탭의 waterfall을 확인해보니, 대표 이미지 요청이 HTML을 받은 직후가 아니라 한참 뒤에 시작됐다.

이 경우에는 다운로드 속도보다 요청 시작 시점이 문제다.

다음과 같은 상황을 의심할 수 있다.

  • 중요한 이미지에 lazy loading이 적용되어 있다.
  • JavaScript 실행 이후에 이미지가 DOM에 추가된다.
  • API 응답을 받은 뒤에야 이미지 URL을 알 수 있다.
  • CSS의 background image로만 이미지를 불러오고 있다.
  • 브라우저가 해당 리소스의 중요도를 늦게 판단하고 있다.

이때는 다음과 같은 방향을 검토할 수 있다.

  • 중요한 이미지의 로딩 우선순위 조정
  • preload 적용 여부 확인
  • 초기 HTML에서 리소스를 더 빨리 발견할 수 있게 변경
  • 불필요한 lazy loading 제거

여기서 Network 탭은 굉장히 유용하다.

수정 전: JavaScript 실행 이후 이미지 요청 시작
수정 후: HTML을 받은 직후 이미지 요청 시작

이런 식으로 waterfall을 비교하면 수정 효과를 눈으로 확인할 수 있다.


경우 3. 리소스를 다 받았는데도 화면에 늦게 그려진다

이 경우부터는 Network 탭만으로 부족하다.

이미지는 이미 다운로드가 끝났는데, 실제 LCP 시점은 훨씬 뒤에 있다.
즉, 리소스는 도착했지만 화면에 나타나지 못하고 기다린 것이다.

이때 확인해야 하는 것이 Element render delay다.

가능한 원인은 다음과 같다.

  • 큰 JavaScript 번들을 파싱하고 실행하느라 Main Thread가 바쁘다.
  • 초기 렌더링 전에 불필요한 계산을 많이 하고 있다.
  • 너무 많은 컴포넌트를 한 번에 렌더링하고 있다.
  • 로딩 상태 때문에 주요 콘텐츠를 늦게 DOM에 추가하고 있다.
  • 초기 화면과 상관없는 스크립트가 먼저 실행되고 있다.
  • CSS 처리나 레이아웃 계산이 오래 걸리고 있다.

이 경우에는 Performance 탭의 Main Thread를 봐야 한다.

Network 탭은 리소스가 언제 도착했는지 알려준다.
Performance 탭은 리소스가 도착했는데도 왜 화면에 나오지 못했는지 알려준다.

이 차이를 이해하고 나니 Performance 탭을 왜 봐야 하는지 조금 감이 왔다.


6. FCP가 느리다면 첫 렌더링을 막는 요소 확인하기

LCP가 주요 콘텐츠가 나타나는 시점이라면, FCP는 화면에 처음으로 어떤 콘텐츠라도 나타나는 시점이다.

LCP만 늦다면 대표 이미지나 큰 콘텐츠의 문제일 가능성이 있다.
그런데 FCP부터 늦다면 페이지의 첫 렌더링 자체가 막히고 있을 수 있다.

이때는 다음을 확인해볼 수 있다.

확인할 항목어떤 문제가 있을 수 있는가
HTML 응답서버 응답 자체가 느릴 수 있다
CSS초기 렌더링을 막는 CSS가 클 수 있다
JavaScript초기 렌더링 전에 너무 많은 스크립트가 실행될 수 있다
폰트텍스트 렌더링이 폰트를 기다리고 있을 수 있다
초기 데이터 요청데이터를 모두 받을 때까지 화면을 숨기고 있을 수 있다

여기서도 바로 특정 기법을 적용하는 것이 아니라, 어떤 구간이 오래 걸리는지 먼저 확인해야 한다.


7. 화면은 떴는데 버벅인다면 Main Thread 보기

첫 화면은 잘 떴는데 클릭이나 스크롤이 느리다면 이제는 런타임 성능을 봐야 한다.

예를 들어 다음과 같은 상황이다.

  • 필터 버튼을 누르면 화면 전환이 늦다.
  • 검색창에 글자를 입력할 때 입력이 끊긴다.
  • 긴 리스트를 스크롤할 때 버벅인다.
  • 모달을 열 때 순간적으로 멈춘다.
  • 애니메이션이 뚝뚝 끊긴다.

이때는 페이지를 새로고침하며 기록하는 것이 아니라, 문제가 발생하는 행동만 기록한다.

1. 페이지를 먼저 로딩한다.
2. Performance 기록을 시작한다.
3. 느린 행동을 한 번 수행한다.
4. 바로 기록을 종료한다.
5. Main Thread에서 오래 걸린 작업을 찾는다.

8. Main Thread에서는 긴 작업부터 찾기

Performance 탭을 처음 보면 Flame Chart가 굉장히 복잡하게 느껴진다.

수많은 함수와 색깔이 한 번에 보이기 때문이다.
하지만 처음부터 모든 함수를 이해하려고 할 필요는 없다.

가장 먼저 해야 하는 일은 이것이다.

느린 순간에 가로로 길게 늘어진 작업을 찾기

가로 폭은 실행 시간을 의미한다.
길게 이어진 작업이 있다면 그동안 Main Thread가 바빴다는 뜻이다.

처음에는 다음 정도만 구분해도 충분하다.

영역의미의심할 방향
ScriptingJavaScript 실행이벤트 핸들러, 반복 계산, 데이터 가공
Rendering스타일 계산, LayoutDOM 크기, 레이아웃 계산
Painting실제 픽셀 그리기넓은 repaint, 무거운 시각 효과
Loading리소스 로딩 처리Network 요청과 연결하여 확인

그다음 긴 작업을 클릭하고, Summary와 Bottom-Up을 확인한다.

1. 긴 작업을 클릭한다.
2. Summary에서 작업 종류와 소요 시간을 확인한다.
3. Bottom-Up에서 시간이 많이 걸린 함수를 확인한다.
4. Call Tree에서 어떤 흐름으로 호출됐는지 확인한다.
5. 실제 코드로 이동한다.

Performance 탭에서 가장 중요한 것은 모든 정보를 읽는 것이 아니다.

느린 순간에 가장 많은 시간을 사용한 작업 하나를 찾는 것

이렇게 접근하면 Flame Chart가 조금 덜 무섭다.


9. Scripting이 길다면 JavaScript 실행 흐름 확인하기

필터 버튼을 누르거나 검색어를 입력했을 때 Scripting 구간이 길게 나타난다면, JavaScript 실행 비용이 큰 상황일 수 있다.

예를 들어 다음과 같은 코드가 있다고 해보자.

const filteredMovies = movies
  .filter((movie) => movie.title.includes(keyword))
  .sort((a, b) => b.popularity - a.popularity);

데이터가 적으면 문제가 없을 수 있다.
하지만 데이터가 많고, 입력할 때마다 반복해서 실행되고, 그 결과로 많은 컴포넌트가 다시 렌더링된다면 버벅임이 생길 수 있다.

이 경우에는 다음과 같은 흐름으로 판단한다.

검색어 입력
→ Performance 기록
→ 입력 직후 Scripting 구간이 길게 나타남
→ Bottom-Up에서 반복 계산 함수 확인
→ 불필요한 계산 여부 확인
→ 최적화 적용
→ 동일한 조건으로 재측정

수정 방향은 상황에 따라 달라질 수 있다.

  • 계산 횟수 줄이기
  • 메모이제이션 검토
  • debounce 적용
  • 이벤트 처리 분리
  • 큰 작업 나누기
  • 필요하다면 Web Worker 검토

중요한 것은 무작정 useMemo를 붙이는 것이 아니다.

실제로 반복 계산 비용이 크다는 근거를 확인한 뒤
메모이제이션을 선택하는 것


10. React 렌더링이 의심된다면 React Profiler로 이동하기

Performance 탭에서 JavaScript 실행이나 렌더링 비용이 크다는 사실을 확인했다면, 그다음에는 React Profiler를 활용할 수 있다.

브라우저 Performance 탭과 React Profiler는 역할이 조금 다르다.

도구확인하기 좋은 것
Performance 탭브라우저 전체 흐름에서 어떤 작업이 오래 걸렸는지
React Profiler어떤 컴포넌트가 왜 다시 렌더링됐는지

따라서 다음과 같은 순서가 자연스럽다.

Performance 탭에서 느린 순간 찾기
→ JavaScript 또는 Rendering 비용이 크다는 근거 확인
→ React Profiler에서 컴포넌트 렌더링 흐름 확인
→ 불필요한 렌더링 원인 찾기
→ 상태 구조 또는 props 전달 방식 수정
→ 다시 측정

이때 검토할 수 있는 것은 다음과 같다.

  • 상태가 너무 상위에 위치해 있는지
  • 작은 상태 변경으로 너무 많은 컴포넌트가 다시 렌더링되는지
  • 매번 새로운 객체나 배열이 전달되고 있는지
  • 리스트가 너무 많은 컴포넌트를 한 번에 렌더링하고 있는지
  • memo, useMemo, useCallback이 실제로 필요한 상황인지

React 최적화도 결국 측정 이후에 적용해야 한다.


11. Rendering이 길다면 Layout을 의심하기

Main Thread에서 Rendering 작업이 길게 나타난다면 레이아웃 계산을 확인해야 한다.

브라우저는 DOM과 CSS를 바탕으로 요소의 위치와 크기를 계산한다.
이 과정이 Layout이다.

특히 JavaScript에서 DOM 스타일을 변경한 직후 크기나 위치를 다시 읽으면, 브라우저가 미뤄두었던 레이아웃 계산을 즉시 수행해야 할 수 있다.

element.style.width = "200px";
const width = element.offsetWidth;

이런 작업이 반복되면 Layout Thrashing이 발생할 수 있다.

조금 더 극단적인 예시는 다음과 같다.

elements.forEach((element) => {
  element.style.width = "200px";
  console.log(element.offsetWidth);
});

스타일을 변경하고 크기를 읽는 작업이 계속 반복된다.

이런 경우에는 읽기와 쓰기를 나누는 방향을 생각할 수 있다.

const widths = elements.map((element) => element.offsetWidth);

elements.forEach((element, index) => {
  element.style.width = `${widths[index] + 10}px`;
});

Performance 탭에서는 Recalculate Style, Layout 등의 작업이 반복되거나 길게 나타나는지 확인하면 된다.


12. Painting이 길다면 화면에 다시 그리는 범위 확인하기

Painting은 브라우저가 실제 픽셀을 그리는 과정이다.

Main Thread에서 Painting 작업이 많이 발생한다면 다음과 같은 것을 의심할 수 있다.

  • 넓은 영역이 자주 다시 그려지고 있다.
  • 큰 그림자나 blur 효과를 자주 변경하고 있다.
  • 스크롤 중 많은 요소의 스타일이 계속 바뀌고 있다.
  • 애니메이션이 Layout과 Paint를 반복적으로 유발하고 있다.

이 경우에는 어떤 스타일 변경이 repaint를 발생시키는지 확인하고, 가능한 경우 다시 그리는 범위를 줄이는 방향을 생각할 수 있다.

여기서도 핵심은 같다.

시각 효과가 많으니 전부 제거하는 것이 아니라,
실제로 Paint 비용이 크다는 근거를 확인한 뒤 수정한다.


13. DOM이 너무 크다면 렌더링 비용도 커진다

카드 리스트나 테이블처럼 반복되는 요소가 많은 화면에서는 DOM 크기도 확인해야 한다.

DOM이 너무 커지면 초기 렌더링뿐 아니라 이후의 스타일 계산, Layout, Paint 비용도 커질 수 있다.

예를 들어 게시글 카드 수백 개를 한 번에 렌더링하고 있다면 다음을 검토할 수 있다.

  • pagination
  • 무한 스크롤
  • virtualization
  • 불필요한 wrapper 제거
  • 화면 밖 영역 지연 렌더링

이 역시 무조건 적용할 필요는 없다.

Performance 탭에서 Rendering 시간이 길고, DOM이 지나치게 크다는 근거가 있을 때 적용하면 된다.


14. 애니메이션과 스크롤이 끊긴다면 Frames 확인하기

스크롤이나 애니메이션이 부드럽지 않은 경우에는 Frames 영역을 확인한다.

브라우저는 여러 프레임을 연속으로 그리면서 움직임을 표현한다.
한 프레임을 처리하는 데 너무 오래 걸리면 화면이 끊겨 보인다.

확인 흐름은 다음과 같다.

1. Performance 기록을 시작한다.
2. 스크롤하거나 애니메이션을 실행한다.
3. 기록을 종료한다.
4. Frames 영역에서 유난히 오래 걸린 프레임을 찾는다.
5. 해당 프레임의 Main Thread 작업을 확인한다.
6. Scripting, Rendering, Painting 중 어디에서 시간이 많이 들었는지 확인한다.

이때 검토할 수 있는 방향은 다음과 같다.

  • 스크롤 이벤트가 너무 자주 실행되고 있는지
  • DOM 측정과 스타일 변경이 반복되는지
  • 애니메이션에 top, left, width 변경이 많이 사용되는지
  • transform, opacity 중심으로 바꿀 수 있는지
  • requestAnimationFrame이 필요한 상황인지
  • repaint 범위가 지나치게 넓은지

15. 수정은 하나씩 하고, 반드시 다시 측정하기

최적화를 하다 보면 여러 가지를 한 번에 고치고 싶어진다.

이미지도 줄이고, 폰트도 바꾸고, lazy loading도 추가하고, 컴포넌트 구조도 바꾸고 싶다.
하지만 여러 작업을 한 번에 하면 무엇이 실제로 효과가 있었는지 알 수 없다.

그래서 한 번에 하나씩 수정하고 다시 측정하는 편이 좋다.

예를 들어 다음과 같이 기록할 수 있다.

항목수정 전수정 내용수정 후
LCP4.1초대표 이미지 요청 우선순위 조정2.8초
대표 이미지 요청 시작1.5초초기 HTML에서 더 빨리 발견되도록 변경0.4초
필터 클릭 후 Long Task170ms반복 계산 줄이기55ms
초기 DOM node 수2,100개페이지네이션 적용480개

숫자가 크게 개선되지 않을 수도 있다.
하지만 그것도 의미가 있다.

이 수정은 현재 병목과 큰 관련이 없었다.
→ 다른 구간을 다시 확인한다.

이 과정을 반복하다 보면 성능 최적화가 막연한 작업이 아니라 디버깅처럼 느껴지기 시작한다.


16. 실제로 따라 할 수 있는 최적화 흐름

마지막으로 전체 흐름을 한 번에 정리해보면 다음과 같다.

1. 느린 순간을 구체적으로 정한다.

2. 같은 조건에서 기록한다.
   - 초기 로딩 문제라면 새로고침과 함께 기록
   - 인터랙션 문제라면 느린 행동 하나만 기록

3. Lighthouse로 어떤 방향을 먼저 볼지 확인한다.

4. 첫 화면이 느리다면 LCP element를 찾는다.
   - TTFB가 긴가?
   - 리소스 요청 시작이 늦은가?
   - 다운로드가 오래 걸리는가?
   - 다운로드 후 렌더링이 늦는가?

5. 사용 중에 버벅인다면 Main Thread를 본다.
   - Scripting이 긴가?
   - Rendering이 긴가?
   - Painting이 긴가?
   - Long Task가 있는가?

6. React 렌더링이 의심된다면 React Profiler로 좁힌다.

7. 원인과 연결되는 수정 하나를 적용한다.

8. 같은 조건으로 다시 측정한다.

9. 수치와 그래프를 비교한다.

10. 다음 병목으로 이동한다.

조금 더 짧게 정리하면 다음과 같다.

느린 순간 정의
→ 측정
→ 병목 구간 확인
→ 원인 추측
→ 하나 수정
→ 재측정

마무리

성능 최적화를 공부할 때는 보통 다양한 기법을 먼저 접하게 된다.

이미지 최적화, 폰트 최적화, JavaScript 최적화, 렌더링 최적화, 코드 스플리팅, 캐싱, 메모이제이션 등 알아야 할 것은 정말 많다.

하지만 실제 프로젝트에서는 기법을 많이 아는 것보다, 현재 문제에 맞는 기법을 선택하는 능력이 더 중요하다는 생각이 들었다.

무작정 이미지를 줄이고, 무작정 memo를 붙이고, 무작정 lazy loading을 적용하는 것이 아니라 먼저 질문해야 한다.

지금 사용자가 느끼는 느린 순간은 언제인가?
그 순간 브라우저는 무엇을 하고 있었는가?
가장 오래 걸린 작업은 무엇인가?
이 수정은 정말 현재 병목을 줄였는가?

Performance 탭은 처음 보면 복잡하다.
하지만 모든 그래프를 완벽하게 읽으려고 하지 않아도 된다.

처음에는 단 하나만 찾으면 된다.

내가 느리다고 생각한 순간에, 가장 오래 걸린 작업은 무엇이었는가?

그 질문에서부터 실제 성능 최적화가 시작된다.
:::

0개의 댓글