ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Study-Mate] 성능최적화 - 번들 최적화
    NextJS 2026. 4. 30. 16:58

     

    1. Lighthouse 측정

    Lighthouse를 측정하다가 LCP 점수가 다른 점수에 비해 낮게 측정되는 것을 발견했고 아래의 경고가 뜨는 것을 발견했다.

    이게 점수 하락의 원인이라고 생각하고 번들을 최적화 하기로 했다. 

     

     

     

     

    2. Analyze 확인

     

    해당 번들이 무엇인지 확인하기 위해

    nextjs가 제공하는 analyze를 사용했다.

    npm run analyze

     

    **번들 이름이 없을 경우**

    NextJS는 기본적으로 개발환경에서는 터보팩으로 번들링을 한다

    그렇기 때문에 번들 이름이 다르게 나온다.

    나는 개발환경에서도 웹팩으로 번들링을 하도록 pakage.json에 추가 설정을 하였다.

        "build": "next build --webpack",

     

     

    3. 번들 분석

     

    크게 Zod와 Supabase의 SSR 번들이 문제였다.

     

    3-1) ZOD

    - 문제 파악

    번들을 봐도 뭐가 문제일지는 유추되는게 없었다.

    공통 청크로 묶이거나 트리 쉐이킹이 제대로 되지 않았을 경우 밖에 생각이 나지 않았고

    date-fns 번들이 있는 것이 의아해서 zod를 임포트 하는 곳을 찾아보고 불필요하게 쓰이는 곳이 있는지 찾아보았다.

     

    그렇게 찾은게 /utils/utils.ts 파일이었다.

    개발 당시 유틸 함수를 일단 파일 하나에 담아 놓은게 문제였다.

    해당 파일에서 Zod 를 임포트를 하니 해당 파일에서 임포트 하는 다른 라이브러리와 함수들도 같이 묶여서 공통 청크로 분류 된 것이다.

     

     - 해결

    함수를 스플리팅 하기로 했다.

    utils.ts -> cn.ts, validation.ts, date.ts, format.ts

    로 나눠서 분리를 하고 다시 측정을 하였다

     

    - 결과

     

    - lighthouse 점수 90점 -> 90점

    - Zod 청크 제거 확인

     

    점수 변화는 없었지만, 번들 구조 자체는 개선되었다. 메인 페이지 초기 번들에서 zod 청크가 빠지고, 60% 이상 미사용이던 7716 청크 entry 하나가 사라졌다. Lighthouse 점수에 즉각 반영되지 않은 이유는 LCP가 다른 요인(폰트, 텍스트 paint 시간)에 더 영향을 받고 있었기 때문인 것 같다.

     

    - 배운점

    함수를 적절하게 나눠서 작성하는 것도 번들링에 영향이 있다는 것을 느꼈다.

     

     

    3-2) Supabase SSR

     

    - 문제 파악

    supabase-ssr 을 쓰는 곳은 supabase의 클라이언트를 생성하는 supabase/client.ts와 supabase/server.ts였다.

    나는 위 파일을 쓰는 곳을 검색하였고, 그 결과 Header.tsx 파일의 NotificationDropdown.tsx에서 쓰는 useGetNotifications Hook에서 쓰는 것을 확인하였다.

     

    나는 위 Hook에서 supabase 클라이언트를 생성하는 곳이 2군데 이상이라 공통 청크로 분류되는 것으로 추측하고 dynamic import로 분류하기로 했다.

     

    - 해결

     

    createClient를 쓰는 훅을 분리하기 위해 dynamic import로 스플리팅 하였다

     

     

    - 결과

     

    역시 점수에 변화는 미미했지만 SSR 청크 중 하나가 없어진 것을 확인하였다.

    useChat, AccountForm 등 다른 진입 경로도 있지만, 이들은 다른 페이지에서 어차피 필요해 dynamic 분리 시 점수 효과 대비 코드 복잡도 비용이 크다고 판단했다

    측정 결과 점수 변화가 미미한 시점에서 멈추는 것이 효율적이라고 판단했다

     

    - 배운점

    효과가 미미하긴 했으나 dynamic import를 이용한 코드 스플리팅을 경험해 보았고 트레이드 오프도 고민해보았다

Designed by Tistory.