ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Next.js Hydrate를 최적화 시킬 수 있을까 (Partial Hydration)
    개발 블로깅/Next.js 2021. 8. 12. 21:46

     

    요즘 SEO 향상을 위해서 웹 성능 개선을 계속해서 연구 중이다.
    (흔히 웹 성능 최적화시킬 수 있는 요소들은 거의 다 진행한 것 같으면서도, 신기하게도 할 것이 계속 나온다...)

    요즘에는 프론트엔드 단에서 LCP(Largest Contentful Paint)TBT(Total Blocking Time)를 어떻게 더 개선시킬 수 있을지 연구 중인데, 며칠 전 Performance 탭에서 흥미로운 요소를 발견했다.

     

     

    위 이미지의 하단 쪽을 보면, FP(First Paint)가 일어나기 전까지 Next.js Hytration 작업이 Long Task로 보여지는 것이다.
    (정확히는 Next.js-before-Hydration이니까, 실제 Hydration 하기 전의 특정 작업으로 볼 수 있다.)

     

    우선 Hydrate가 무엇인지 모른다면, Hydrate이 무엇인지 정리했던 이전 블로그 글을 한번 읽어보면 좋을 것 같다.

     

    Next.js의 Hydrate란?

    Next.js 프레임워크의 동작원리를 제대로 파악하고 있는 개발자라면 Hydrate에 대해선 이미 익숙한 용어일 것이다. 그러나 Next.js의 주요 동작 방식 중 하나지만, 눈에 잘 띄지 않아 놓치기도 쉬운 개

    helloinyong.tistory.com

     

    Hydrate 동작 원리대로, 클라이언트에게 정적 페이지를 우선 내려주고 이후 JS 파일들을 보내준 뒤 DOM 요소와 JS 코드들이 매칭하게 된다.

    SSR(Server Side Rendering) 동작 방식은 웹 서버 단에서 미리 렌더링을 해서 빠르게 브라우저에 화면을 나타내게 할 수 있고, 이후에는 실제 자바스크립트에 의한 웹 페이지 동작이 필요하므로 Hydration 과정이 필요한 것임은 분명하다.

     

    그러나  현재 이러한 Hydration 방식은 지나친 Over Task이다.

     

    Next.js에서는 Hydration을 하기 위해, 현재 웹 페이지를 구성하고 있는 모든 자바스크립트 파일을 브라우저 단으로 보내게 된다.
    모든 웹 페이지의 자바스크립트 코드를 브라우저로 보내기 위해 그만큼 JS Chunk 파일 사이즈도 커지는 것은 물론, JS 파일 개수가 늘어나는 만큼 네트워크 대역폭도 차지하게 된다.

    또한, 이미 그려져 있는 DOM 요소임에도 굳이 자바스크립트 동작이 필요하지 않은 요소들의 JS 코드들도 Hydration을 하기 위해 어쩔 수 없이 모두 불러와 필요 이상으로 HTML DOM과 Parsing 작업을 하게 된다.

     

    더 자세한 이해를 위해 Next.js로 구현된 아래 웹 페이지를 예시로 봐보자.

     

    해당 웹 페이지가 SSR이 일어나면, 우선 웹 페이지에서 자바스크립트가 빠진 상태로 DOM 화면으로만 구성된 Doucment를 브라우저에 노출된다.
    (뭔가 마치 빈 껍데기 같은 느낌이다.)

    이후에, 보여지고 있는 이 모든 DOM 요소에 대한 자바스크립트 코드를 모두 불러와서 Hydation을 할 것이다.
    (여기서 자바스크립트 코드란, 리액트로 짠 코드를 Build 및 번들링 한 코드를 말한다.)

     

    중요한 부분은 여기다.

     

    실제론 위 웹 페이지 상에서 자바스크립트 코드가 필요한 부분, 즉 실제 Hydration이 필요한 부분은 Input, Button 등 유저 인터렉션이 일어나는 요소뿐이다.

     

    이 외 나머지 요소들은 단순히 화면 표시만 해주면 되고, SSR 단계에서 이미 제대로 화면을 그려주고 있으니 자바스크립트 코드를 가져올 필요도 없고 Hydration 과정을 거칠 필요도 없다.

     

    그래서, 실제 Hydration이 필요한 DOM 요소에 대한 자바스크립트 코드만 가져와, 부분적 Hydration을 할 수 있다면 필요 이상으로 Hydration을 하는 Long Task를 줄일 수 있을 것이다.

     

    이에 관한 방법이 있는지 리서치를 해보니, 아니나 다를까 나와 같은 고민을 해본 사람들이 과거에도 있었으며 이에 대한 해결책을 제안한 글이 있었다.

     

    How we achieved the best Web Performance with Partial Hydration

    Why would you send a whole application to your users when all they need is a few widgets?

    medium.com

     

     

    Partial Hydration

    정적 DOM Document를 내보낸 뒤, 실제 Hydration이 필요한 부분만 브라우저에게 JS 코드를 보내고 Hydrate를 한다고 설명되어있다.

    PReact에서 제공하는 pool-attendant-preact라는 라이브러리를 활용하면 이러한 Partial Hydration 과정을 처리할 수 있다는 내용이다. 그리고 next-super-performance 라는 오픈소스 라이브러리로 런칭하여 HOC 패턴으로 Next.js Config 요소를 튜닝시켜서 이 Partial Hydration을 과정을 직접 구현시킬 수 있도록 만들어 놓았다.

     

    그래서 흥분한 상태로 이 방법을 열심히 시도해 봤지만... 아쉽게도 결국 성공하진 못했다.

     

     

    Partial Hydration을 성공하지 못한 이유

    우선 내가 PReact라는 녀석에 대해 이해도가 부족한 편이다.
    PReact가 일반 웹 페이지를 구현하는 것에 대해선 React랑 비슷하나, pool-attendant-preact 같은 내부 모듈을 직접 이용하려면 PReact의 동작원리를 직접 이해해야 하는 듯하다.

    직접 활용해 볼 수 있는 next-super-performance 오픈소스는 최근 업데이트가 2년 전이며, Next.js가 계속 업데이트되는 것에 반해 이 라이브러리는 이제는 따로 관리가 안되고 있는 듯하여 지금은 제대로 작동하지 않는다.

     왜 더 이상 관리를 안 하는지 무척 궁금해서 찾아봤더니 아래와 같은 사유가 있었다...🥲

     

    출처: https://github.com/LukasBombach/next-super-performance/issues/4

     

     

    또한 아직까지는 Next.js에서 Partial Hydration에 대해 공식적으로 지원해주고 있는 것은 없는 상황이다.
    그러나 Vercel 측에서도 이 부분에 대해서는 이미 인지하고 있는 것 같다. 

     

    Supporting partial rehydration on server side rendered pages · Issue #10344 · vercel/next.js

    The problem While SSR in NextJS works well with hybrid pre-rendering targets by page, it would be much more effective if this option was available on a component level rather than just by page. Con...

    github.com

     

     

     

    아쉽지만 기다려 볼 수밖에..

    실제로 Hydration이 필요한 요소에 대한 JS 파일만을 요청해서 가져올 수 있다면, 파일 요청 수 감소, 번들 파일 사이즈 감소, 렌더링 최적화 등등으로 거의 모든 방면으로 웹 성능 최적화가 가능할 것임이 분명하다.

    아마 이게 된다면 FP(First Paint)는 물론 LCP(Largest Contentful Paint), TBT(Total Blocking Time) 수치도 많이 개선시킬 수 있을 것 같다.

    next-super-performance 요건 정말 대단한 라이브러리라고 생각이 드는데, 그에 반해 Star 개수가 많지 않아서 사실 좀 놀랐다...
    (내가 직접 파보고 싶긴 하지만.. 난 아직 해야 할 다른 것들이 너무 많...)

    아쉽지만... Next.js가 공식적으로 지원해 줄 때까지 기다려볼 수밖에..
    (뭔가 그림의 떡인 느낌...)

     

     

     

    반응형

    댓글

Designed by Tistory.