[NextJS Conf] Optimizing Third-Party Loading in Next.js (Houssein Djirdeh)
[NextJS Conf] Optimizing Third-Party Loading in Next.js (Houssein Djirdeh)
직번
Next.js 팀이 LCP(Largest Contentful Paint) 점수를 향상시키기 위해 부분적인 프리 렌더링, 스트리밍 등과 같은 놀라운 작업을 하고 있습니다. 하지만 이번 발표에서 강조하고 싶은 것은 LCP와 같은 메트릭에 제3자 리소스가 미치는 영향입니다.
또 다른 중요한 성능 메트릭인 INP(Interaction to Next Paint)를 살펴보겠습니다. INP는 클릭, 탭 및 키보드 상호작용의 대기 시간을 계산하여 응답성을 측정합니다. 좋은 INP 점수는 200밀리초 이하입니다. 상호작용 수와의 상관 관계를 시도할 때 매우 유사한 차트를 볼 수 있습니다.
INP(INP)를 통해 로드되는 서드 파티 리소스에 대해 살펴보겠습니다. INP 사이트에서 더 많은 서드 파티 리소스를 로드하면 응답성 측면에서 성능이 저하되는 경향이 있습니다. 여기서 중요한 점은 상관관계가 반드시 인과관계를 의미하지는 않는다는 것입니다. 이전 차트만 보고 성능 저하가 서드 파티 리소스 때문이라고 단정지을 수는 없습니다. 그러나 과거에 수행한 많은 연구 데이터를 함께 살펴보면 서드 파티 리소스가 성능 저하에 기여한다는 사실이 명확해집니다.
서드 파티 리소스가 사용자 경험에 상당한 부정적 영향을 미친다는 점을 명확히 하기 위해, 다른 관점에서 이 문제를 살펴볼 수 있습니다. 이를 위해 몇 가지 로컬 테스트를 실행할 수 있습니다. 저는 Shad Cen의 분류 웹사이트로 테스트를 진행했습니다. 여기서 Shad Cen과 그가 Next.js 생태계에서 수행한 놀라운 작업에 박수를 보냅니다.
이 웹사이트를 선택한 이유는 첫째, 오픈 소스이고 둘째, 다수의 라우트와 풍부한 기능을 갖춘 Next.js 사이트의 대표적인 예시였기 때문입니다. 특히, 이 사이트에는 서드 파티 리소스가 포함되어 있지 않았습니다. 그래서 몇 가지 인기 있는 서드 파티 스크립트를 추가하면 어떤 일이 발생하는지 확인하고자 했습니다.
그 결과, 사이트의 총 차단 시간이 65배 증가하는 것을 발견했습니다. 총 차단 시간(Total Blocking Time, TBT)은 첫 번째 컨텐츠 페인트(FCP)부터 사이트가 상호작용 가능해질 때까지 메인 스레드가 차단된 시간을 측정합니다. 이는 페이지의 응답성을 평가하는 데 매우 유용한 지표입니다.
기능이 풍부한 이 웹사이트에는 서드 파티 리소스가 포함되어 있지 않아서 몇 가지 인기 있는 서드 파티 스크립트를 추가했을 때 어떤 일이 발생하는지 확인해 보고 싶었습니다. 결과적으로 사이트의 총 차단 시간(TBT, Total Blocking Time)이 65배 증가하는 것을 발견했습니다. 총 차단 시간은 첫 번째 컨텐츠 페인트(FCP, First Contentful Paint)부터 사이트가 상호작용 가능해질 때까지 메인 스레드가 차단된 시간을 측정합니다. 이는 페이지가 사용자 상호작용에 얼마나 응답할 수 있는지를 평가하는 데 매우 유용한 지표입니다.
여기서 알 수 있듯이 서드 파티 스크립트를 포함할 때 메인 스레드가 쉽게 차단될 수 있습니다. 이를 더 높은 수준에서 바라보면 두 가지 문제가 있습니다. 첫째, 지금까지 본 모든 데이터는 애플리케이션에 서드 파티를 더 많이 로드할 때 개발자들이 심각한 사용자 경험 문제에 직면하게 된다는 것을 보여줍니다. 둘째, 개발자 경험 문제도 있습니다. 많은 개발자가 서드 파티 리소스를 어떻게 로드해야 할지 잘 모른다는 점입니다.
인기 있는 서드 파티 스크립트를 사용하면 성능 문제를 어떻게 처리해야 하는지, 또는 새로운 맞춤 기능을 추가하는 방법을 모르는 경우가 많습니다. 다음은 이에 대한 몇 가지 사례입니다. 이러한 문제들은 Stack Overflow와 같은 사이트에서 자주 나타납니다. Next.js 개발자들은 서드 파티의 성능 영향으로 자주 고생합니다.
예를 들어, 한 사용자는 Next.js 사이트에 Google 태그 매니저(GTM)를 포함했더니 Lighthouse 점수가 38로 떨어졌다고 합니다. 이는 정말로 도움을 요청하는 상황입니다. GitHub에서도 비슷한 예시가 있습니다. 한 사용자는 "Google 태그 매니저가 Lighthouse 점수를 낮추고 있으며, 이를 개선할 방법을 모르겠다"고 말하고 있습니다.
또한, 개발자 경험 측면에서도 비슷한 문제를 많이 볼 수 있습니다. 최근에 Next.js 앱에 Google 태그 매니저를 로드하려는 개발자들이 어떻게 하는지 알아보려고 검색했을 때, 한 기사를 발견했습니다. 이 사람은 GTM의 문서를 보고 따르지 않기로 결정했습니다.
이러한 사례들은 서드 파티 스크립트가 사용자 경험과 개발자 경험 모두에 얼마나 큰 영향을 미칠 수 있는지 보여줍니다. 서드 파티 스크립트를 효과적으로 관리하는 방법을 배우는 것이 중요합니다. 여기에는 성능 최적화, 로딩 전략 개선, 불필요한 스크립트 제거 등이 포함됩니다.
결론적으로, 서드 파티 스크립트의 올바른 사용과 관리가 LCP 및 INP와 같은 성능 메트릭에 큰 차이를 만들 수 있습니다. 성능 문제를 미리 인식하고 적절한 조치를 취하는 것이 중요합니다.
개발자들은 서드 파티 스크립트를 포함하는데 있어 관용적인 접근 방식을 찾으려 하다 보니, 유지 관리가 더 이상 되지 않을 수 있는 별도의 오픈 소스 라이브러리를 사용하는 경우가 많습니다. 그렇다면 해결책은 무엇일까요? 좋은 질문 중 하나는 프레임워크 유틸리티를 도입하려고 하기보다는 서드 파티가 소스에서 성능을 개선할 수는 없는지 묻는 것입니다. 일부 서드 파티의 경우 이는 가능할 수 있지만, 많은 시간이 걸릴 수 있습니다. 이러한 서드 파티 리소스는 웹의 대다수에서 사용되기 때문에 사용자 경험에 대한 점진적인 개선도 매우 오랜 시간이 걸릴 수 있습니다.
개발자 경험 측면에서, 왜 서드 파티 제공자들이 프레임워크 유틸리티를 직접 구축하지 않을까요? 왜 그들은 React 유틸리티나 Angular 유틸리티, Next.js 유틸리티 등을 구축하지 않는 걸까요? 이것이 가능하면 좋겠지만, 현실적이지 않습니다. 프레임워크 생태계는 매우 자주 변화하기 때문에 서드 파티 제공자들이 일관된 솔루션을 구축하는 것이 훨씬 더 쉬운 방법입니다.
우리가 몇 년 전에 스크립트 컴포넌트를 만들 때, 서드 파티 스크립트를 빠르고 효율적으로 로드하기 쉽게 만들고자 했습니다. Next.js에서 스크립트 컴포넌트의 기본 경험은 애플리케이션의 일부 또는 전체가 하이드레이션된 후에 로드되도록 하는 것입니다. 그러나 우리는 개발자들에게 서드 파티 리소스를 언제 로드할지에 대한 세밀한 제어를 제공하기 위해 strategy 속성을 추가했습니다. 이 속성을 사용하여 하이드레이션이 발생하기 전에, 하이드레이션이 발생한 후 또는 브라우저 유휴 시간 동안 lazy 값을 사용하여 로드하도록 결정할 수 있습니다.
그러나 단일 스크립트에 대해 스크립트 컴포넌트를 사용하는 것은 비교적 쉬울 수 있지만, 예를 들어 Google 태그 매니저를 사용하려고 할 때는 상황이 복잡해집니다. Google 태그 매니저 문서를 살펴보면 큰 인라인 스크립트를 포함해야 한다는 것을 알게 되고, 이를 스크립트 컴포넌트를 사용하여 어떻게 구현할지 고민하게 됩니다.
이를 구현하는 방법을 알아내고 나면, 가장 좋은 로딩 전략은 무엇인지, 기본 접근 방식을 유지할지 아니면 다른 방식을 시도할지 등의 문제에 직면하게 됩니다. 또한, 레이아웃 컴포넌트에 이 스크립트를 포함해야 하는지, 특정 페이지에 포함해야 하는지, 그리고 맞춤 이벤트를 전송하는 방법은 무엇인지와 같은 다른 질문들도 생깁니다.
Google 태그 매니저를 예로 들었지만, 이 패턴은 모든 인기 있는 서드 파티에 적용될 수 있습니다. 많은 Next.js 애플리케이션이 Google 태그 매니저와 같은 서드 파티를 사용하기 때문에, 이러한 문제를 해결하기 위해 스크립트 컴포넌트를 기반으로 별도의 표준 라이브러리를 도입하면 이 과정이 훨씬 더 쉬워질 수 있습니다.
Next.js의 성능 메트릭(LCP 및 INP)에 대한 서드 파티 리소스의 영향과 최적화 방법
요약
- NextJS에서는 성능 문제를 해결하기 위해 부분 pre-rendering, streaming 과 같은 기능을 개발하였습니다.
- 하지만 아직 해결하지 못한 문제가 서드 파티 리소스입니다. 인기 있는 서드파티 리소스는 용량이 크며 성능 저하로 이어집니다.
- 서드 파티 리소스는 성능 뿐만 아니라 사용하며 많은 고민도 해야합니다.
고민해야할 것들
- Google 태그 매니저 문서를 살펴보면 큰 인라인 스크립트를 포함해야 합니다.
- 인라인 스크립트가 크다면 어떻게 구현해야할지 고민하게 됩니다.
- 레이아웃 컴포넌트에 스크립트를 포함해야할지?
- 특정 페이지에 포함해야 하는지?
……
- 이러한 고민을 없애고자 가장 인기있는 서드 파티 리소스를 Next에서 직접 지원하기로 했습니다.
서드 파티 리소스가 성능 매트릭에 미치는 영향
Next.js 팀의 설명 및 기능 개발 계기
Next.js 팀은 성능을 향상시키기 위해 부분적인 프리 렌더링과 스트리밍 같은 기능을 개발했습니다. 그러나 서드 파티 리소스의 문제는 해결하지 못했습니다.
Next.js 팀은 성능 메트릭(LCP와 INP)을 통해 이러한 리소스가 성능에 미치는 영향을 검증하고 이를 개선하기 위해 어떻게 할지 고민하게 됩니다.
성능 메트릭 및 서드 파티 리소스
- LCP (Largest Contentful Paint) : 사용자가 페이지에서 가장 큰 컨텐츠 요소가 로드되는 시간
사용자에게 중요한 지표로, 서드 파티 리소스가 이를 지연시킬 수 있습니다.
- INP (Interaction to Next Paint):사용자 상호작용 후 화면이 업데이트되는 시간을 측정
상호작용(클릭, 탭, 키보드 입력),
좋은 INP 점수는 200밀리초 이하로, 서드 파티 리소스가 이를 저해할 수 있습니다.
- INP 사이트에서 더 많은 서드 파티 리소스를 로드하면 응답성 측면에서 성능이 저하되는 경향이 있습니다.
- FCP(First Contentful Paint) : 첫 번째 컨텐츠 페인트
- TBT(Total Blocking Time) - 총 차단 시간 :
첫 번째 컨텐츠 페인트(FCP)부터 사이트가 상호작용 가능해질 때까지 메인 스레드가 차단된 시간을 측정합니다.
무조건 서드파티 리소스의 문제라고 볼 수는 없지만 과거의 연구 데이터를 보면 서드 파티 리소스가 성능 저하에 어느 정도 기여한다고 합니다.
서드 파티 리소스의 문제라는 것을 검증(성능 저하)
Next팀은 서드파티 리소스가 없는 오픈 소스 웹사이트에 몇 가지 인기 있는 서드 파티 스크립트를 추가하였습니다.
그 결과, 사이트의 총 차단 시간이 65배 증가하는 것을 발견했습니다.
출처 : https://www.youtube.com/watch?v=zZPNwx0m07U&t=659s
https://pagespeed.web.dev/?hl=ko
- pageSpeed Insights를 사용하면 평가 가능합니다.
인기 있는 서드 파티 스크립트를 사용하면 성능 문제를 어떻게 처리해야 하는지, 새로운 기능을 추가하는 방법을 모르는 경우가 많습니다. 이에 대한 몇 가지 사례를 보여드리겠습니다.
서드 파티 리소스의 문제 사례
Stack Overflow
한 사용자는 Next.js 사이트에 Google 태그 매니저(GTM)를 포함했더니 Lighthouse 점수가 38로 떨어졌다고 합니다.
출처 : https://www.youtube.com/watch?v=zZPNwx0m07U&t=659s
GitHub
한 사용자는 "Google 태그 매니저가 Lighthouse 점수를 낮추고 있으며, 이를 개선할 방법을 모르겠다"고 말하고 있습니다.
출처 : https://www.youtube.com/watch?v=zZPNwx0m07U&t=659s
서드 파티 리소스의 개발자 경험 측면
- 최근에 Next.js 앱에 Google 태그 매니저를 로드하려 했지만 잘 되지 않는 이슈가 있었습니다.
- 이러한 사례들은 서드 파티 스크립트가 사용자 경험과 개발자 경험 모두에 얼마나 큰 영향을 미칠 수 있는지 보여줍니다.
- 서드 파티 스크립트를 효과적으로 관리하는 방법을 배우는 것도 중요합니다
- 효과적으로 관리하는 방법은 성능 최적화, 로딩 전략 개선, 불필요한 스크립트 제거 등이 있습니다.
서드 파티 리소스의 문제 검증 결과.
- 개발자의 생산성을 저하시킵니다.
- LCP & INP 측정을 통해 유저 경험 저하도 증명되었습니다.
Third Party 리소스의 문제를 해결하는 방법은 무엇일까?
- 서드 파티 소스에서 성능을 개선하는 것.
일부 서드 파티의 경우는 가능할 수 있습니다.(일부입니다.)
소스에서 성능 개선이 가능하더라도 많은 시간이 걸립니다.
- 프레임워크 유틸리티를 도입하는 것.
서드 파티 제공자들이 프레임워크 유틸리티를 제공해 주는 것입니다.
1번의 경우 가능한 경우도 드물고 가능하더라도 많은 시간이 걸리기 때문에 2번의 경우가 가장 적합할 것입니다.
그렇다면 왜 서드 파티 제공자들이 프레임워크 유틸리티를 직접 구축하지 않을까요?
Google 태그 매니저(GTM)와 같은 서드 파티 제공자들은 왜 React, Angular, Next.js 유틸리티를 구축하지 않을까요?
Third Party Utilty를 구축하지 않는 이유
사실 이 부분은 현실적이지 않습니다. 프레임워크 생태계는 매우 자주 변화하기 때문에 GTM과 같은 서드 파티 제공자들에게는 일관된 솔루션을 구축하는 것이 쉬운일이죠.
NextJS팀의 노력과 결과
Next13
- NextJS팀은 서드 파티 스크립트를 빠르고 효율적으로 로드하기 쉽게 만들고자하였고 <Script>를 만들었습니다.
- 기본적으로 애플리케이션의 일부 또는 전체가 하이드레이션된 후에 로드되도록
그러나 개발자들에게 서드 파티 리소스를 언제 로드할지에 대한 세밀한 제어를 제공하기 위해 strategy 속성을 추가했습니다.
이 속성을 사용하여
- 하이드레이션이 발생하기 전에
- 하이드레이션이 발생한 후
- 브라우저 유휴 시간 동안
lazy값을 사용하여 로드하도록 결정할 수 있습니다.
하지만 문제가 생깁니다.
Google 태그 매니저를 사용한다고 예를 들면 상황이 복잡해집니다.
- Google 태그 매니저 문서를 살펴보면 큰 인라인 스크립트를 포함해야 합니다.
- 인라인 스크립트가 크다면 어떻게 구현해야할지 고민하게 됩니다.
- 구현 방법을 알아낸다면? 가장 좋은 로딩 전략은 무엇인지, 기본 접근 방식을 유지할지 아니면 다른 방식을 시도할지 등의 문제에 직면하게 됩니다
- 레이아웃 컴포넌트에 스크립트를 포함해야할지?
- 특정 페이지에 포함해야 하는지?
- 맞춤 이벤트를 전송하는 방법은 무엇인지?
등등 여러 고민에 빠지게됩니다.
- 이러한 문제를 해결하기 위해 스크립트 컴포넌트를 기반으로 별도의 표준 라이브러리를 도입하면 이 과정이 훨씬 더 쉬워질 수 있습니다.
문제 해결 1 : Google 서드 파티 지원
만약 Google 태그 매니저 컴포넌트를 import하면 자동으로 가장 성능 좋은 방식으로 로드된다는 것을 알게 된다면 어떨까요?
- 스크립트 컴포넌트를 사용하지만, 언제 로드할지에 대한 연구는 NextJS에서 고민합니다.
- 개발자는 여러 고민을 할 필요가 없게 되었습니다.
문제 해결2 : 지원하는 서드 파티의 이벤트 전송 지원
"Google 태그 매니저로 이벤트를 전송하고 싶다"라고 생각할 경우, 이벤트를 전송하기 위한 작은 유틸리티 함수도 있습니다.
문제 해결3 : 서드 파티에 대한 개발자의 고민
YouTube 임베드 컴포넌트, Google Maps 임베드 컴포넌트도 존재합니다. 하지만 아직 풀리지 않은 문제가 있습니다. 그럼 성능은? Google Maps의 경우 필요하지 않을 때에도 자동 로드 됩니다.
NextJS팀은 이러한 성능 문제를 어느정도 해결해주어 개발자의 고민을 덜어줍니다.
Google Maps를 디바이스 뷰포트 아래에서 lazy load하도록 설정해놓았습니다. lazy load일 경우 페이지의 다른 리소스를 차단하지 않게됩니다.
Youtube의 경우에도 Light YouTube Embed를 사용하여 더 빠르게 로드 되도록 하였습니다.
후기
개발자들이 제시하는 문제를 NextJS팀에서 유심히 보고 개선하여 개발자 경험을 증가 시키는 것이 놀라웠습니다. 과연 NextJS만큼 개발자 경험을 중요하게 생각하는 팀이 있을 지 궁금할 지경입니다. NextJS를 사용하는 개발자 로서는 굉장히 신뢰가 가는 행동이라고 생각이 듭니다.
NextJS 14를 도입하기 위해 공부하는 만큼 해당 프레임워크 혹은 개발팀에 대한 신뢰도도 굉장히 중요한 요소라고 생각합니다. 개발자 경험을 중시하고 빠른 피드백 수용과 빠른 업데이트에 대해 생각하니 신뢰도의 걱정은 덜게 되었습니다.
출처 :
https://www.youtube.com/watch?v=zZPNwx0m07U&t=659s
https://nextjs.org/docs/app/building-your-application/optimizing/third-party-libraries

