[번역] Rendering on the Web (진행중..)

k.·2020년 8월 26일
0

이 글은 Rendering on the Web 을 번역한 것입니다.

개발자들은 애플리케이션 전체 아키텍처에 영향을 미치는 결정을 해야 할 때가 있습니다. 웹 개발자가 하는 핵심적인 결정 중 하나는 로직과 렌더링을 어디서 구현할지에 대한 것입니다. 웹사이트를 빌드하는 다양한 방법이 있기 때문에 이것은 어려울 수 있습니다.

이 영역에 대한 이해는 지난 몇 년 동안 크롬에서 우리의 작업이 대규모 사이트와 상호작용을 하면서 알려졌습니다. 우리는 개발자들이 rehydration 접근법에 대해 적절한 server rendering 또는 static rendering을 고려하도록 권장할 것입니다.

이러한 결정을 할 때, 선택한 아키텍처를 더 잘 이해하기 위해서는 각각의 접근법에 대해 확실하게 이해하고, 사용할 일관된 용어들이 필요합니다.

용어

Rendering

  • SSR: Server-Side Rendering - 서버에서 HTML로 client-side 또는 유니버셜 앱을 렌더링
  • CSR: Client-Side Rendering - 브라우저에서 렌더링(일반적으로 DOM 사용)
  • Rehydration: 서버에서 렌더링된 HTML의 DOM 트리와 데이터를 재사용하기 위해, 클라이언트에서 JavaScript view를 "booting up"
  • Prerendering: 빌드시에 client-side 애플리케이션을 실행하여 초기 상태를 정적 HTML로 캡처

Performance

  • TTFB: Time to First Byte - 링크를 클릭하고 콘텐츠의 첫 번째 bit가 도착하기까지의 시간
  • FP: First Paint - 사용자가 픽셀을 처음 볼 수 있는 시간
  • FCP: First Contentful Paint - 요청한 컨텐츠(article body 기타 등등)를 볼 수 있는 시간
  • TTI: Time To Interactive - 페이지가 양방향으로 연결되는 시간(이벤트가 연결된)

Server Rendering

Server Rendering은 응답을 위한 페이지 전체 HTML을 서버에서 생성합니다. 이것은 브라우저가 응답을 받기 전에 처리되기 때문에, 클라이언트에서 데이터를 가져오거나 템플릿을 만들기 위한 추가적인 라운드 트립을 방지합니다.

Server Rendering은 일반적으로 빠른 FP(First Paint)FCP(First Contentful Paint)를 생성합니다. 서버에서 로직과 렌더링을 실행하면, 클라이언트에 많은 JavaScript를 보내는 것을 피할 수 있어 빠른 TTI(Time to Interactive)에 도움이 됩니다. 이 경우, 텍스트와 링크를 사용자의 브라우저로 보내는 것이 일반적입니다. 이 접근 방식은 다양한 장치와 네트워크 조건에서 잘 작동할 수 있습니다.

Server Rendering을 사용하면, 사용자가 사이트를 사용하기 전에 CPU에 바인딩 된 JavaScript가 처리되기를 기다리지 않아도 됩니다. third-party JS를 피할 수 없는 상황에서도, first-party JS 비용을 절감할 수 있으면 이것은 충분히 효율적입니다. 하지만, 중요한 단점은 서버에서 페이지를 생성하는 데 시간이 걸리고, 이것은 종종 TTFB(Time to First Byte)를 느리게 할 수도 있습니다.

Server Rendering이 애플리케이션에 적절한지는 주로 어떤 유형의 경험을 쌓느냐에 따라 결정됩니다. Server Rendering vs Client-side Rendering, 올바른 적용에 대한 많은 논쟁이 있지만, Server Rendering을 일부 페이지에 사용할 수 있다는 것을 알아야 합니다. 일부 사이트는 hybrid rendering을 성공적으로 채택했습니다. Netflix는 비교적 정적인 페이지는 서버에서 렌더링하고, 상호작용이 많은 페이지에는 JS를 프리 패치해서 무거운 클라이언트 렌더링 페이지를 빠르게 로드할 수 있게 했습니다.

많은 최신 프레임워크, 라이브러리 및 아키텍처는 클라이언트와 서버 모두에서 동일한 애플리케이션을 제공할 수 있게 합니다. 이러한 기법은 Server Rendering에 사용될 수 있지만, 렌더링이 서버와 클라이언트 모두에서 발생하는 아키텍처는 성능 특성과 tradeoff가 매우 다른 자체 솔루션 클래스라는 점에 유의해야 합니다. React 사용자는 renderToString()Next.js와 같은 것들 위에 구축된 솔루션을 사용할 수 있습니다. Vue 사용자는 Vue의 서버 렌더링 가이드Nuxt 를 볼 수 있습니다. Angular는 Universal이 있습니다. 대부분의 유명한 솔루션들은 hydration을 사용할 수 있고, 이들을 선택하기 전에 각 특징들을 잘 알아야 합니다.

Static Rendering

Static Rendering은 빌드시에 발생하고, 빠른 FP, FCP, TTI를 제공합니다(클라이언트 측의 JS가 제한적이라고 가정했을 경우). Server Rendering과 달리, 페이지의 HTML이 즉시 생성될 필요가 없기 때문에, 지속적으로 빠른 TTFB를 달성할 수 있습니다. 일반적으로 Static Rendering은 각 URL에 대해 별도의 HTML 파일을 미리 생성하는 것을 의미합니다. HTML 응답을 미리 생성하면, 여러 CDN에 deploy해 edge-caching을 활용할 수 있습니다.

Static Rendering 솔루션은 다양한 형태와 크기가 있습니다. Gatsby와 같은 툴은 개발자들이 그들의 애플리케이션이 빌드 시에 생성되기보다는 더 역동적으로 렌더링 되는 것처럼 느끼게 하기 위해 설계되었습니다. JekyllMetalsmith와 같은 것들은 그것의 static 특징을 아울러, 더 템플릿 중심적인 접근법을 제공합니다.

Static Rendering의 단점 중 하나는 모든 가능한 URL에 대해 개별 HTML 파일을 생성해야 한다는 것입니다. URL을 미리 예측할 수 없거나 고유 페이지 수가 많은 사이트의 경우, 이것은 어려울 수도 있고 불가능할 수도 있습니다.

React 사용자는 Gatsby, Next.js static export, Navi에 익숙할 수 있습니다. Static Rendering과 Prerendering의 차이를 아는 것은 중요합니다. Static Render된 페이지는 많은 클라이언트 측 JS를 실행할 필요 없이 상호작용합니다. 반면에, Prerendering은 SPA(진정한 상호작용을 위해 페이지가 클라이언트에서 boot 되어야 하는)의 FP, FCP를 개선합니다.

주어진 솔루션이 Static Rendering 인지 Prerendering 인지 확실하지 않을 경우, JavaScript를 사용하지 않도록 설정하고 웹 페이지를 로드해보면 됩니다. Static Render된 페이지의 경우, 대부분의 기능이 JavaScript가 활성화되지 않은 상태로 여전히 존재할 것입니다. Prerendering된 페이지의 경우, 링크와 같은 기본적인 기능이 여전히 있을 수 있지만 대부분의 페이지는 비활성 상태가 될 것입니다.

또 다른 유용한 테스트는 크롬 DevTools 을 사용해 네트워크 속도를 늦추고 페이지가 대화형으로 전환되기 전에 JavaScript가 얼마나 다운로드 되었는지 보는 것입니다. Prerendering은 일반적으로 상호작용을 위해 더 많은 JavaScript를 필요로 하며, JavaScript는 Static Rendering에 의해 사용되는 Progressive Enhancement 접근법보다 더 복잡한 경향이 있습니다.

Server Rendering vs Static Rendering

Server Rendering은 상당한 오버헤드를 만들 수 있습니다. 많은 Server Rendering 솔루션은 TTFB를 지연시키거나 전송되는 데이터가 두 배가 될 수 있습니다(예. 클라이언트에서 JS가 사용하는 inlined state). React에서 renderToString()은 동기식 및 단일 스레드 방식으로 인해 느릴 수 있습니다. Server Rendering이 "적절하게" 쓰이려면, 컴포넌트 캐싱, 메모리 관리, 메모이제이션 기술 및 다른 많은 우려 사항을 위한 솔루션을 찾거나 구축해야 합니다. 일반적으로 당신은 동일한 응용 프로그램을 여러 번 처리/재구축합니다(클라이언트에서 한 번, 서버에서 한 번). 서버 렌더링이 무언가를 더 빨리 보이게 할 수 있다고 해서, 갑자기 할 일이 줄어든 것은 아닙니다.

Server Rendering은 각 URL에 대해 on-demand 방식으로 HTML을 생성하지만, Static Render된 콘텐츠를 제공하는 것보다 느릴 수 있습니다. 만약 추가적인 leg-work를 할 수 있다면, 서버 렌더링 + HTML 캐싱은 server render time을 엄청나게 줄일 수 있습니다. Server rendering의 장점은 Static Rendering 보다 더 많은 "실시간" 데이터를 가져오고, 더 완전한 request에 응답하는 것입니다. 개인화가 필요한 페이지는 Static Rendering이 적절하지 않은 구체적인 예시입니다.

Server Rendering은 또한 PWA를 구축할 때, 흥미로운 결정을 내릴 수 있습니다. 전체 페이지에 service worker caching을 사용하는 것이 더 낫습니까, 아니면 서버에서 개별 콘텐츠를 렌더링 하는 것이 더 낫습니까?

Client-Side Rendering (CSR)

Client-side rendering은 브라우저에서 자바스크립트를 사용해 직접 페이지를 렌더링 하는 것입니다. 모든 로직, 데이터 패치, templating, 라우팅은 서버가 아닌 클라이언트에서 처리됩니다.

Client-side rendering은 빠르게 가져오고 유지하는 것이 모바일에서 어려울 수 있습니다. 최소한의 작업을 하고, tight JavaScript budget을 유지하고, 최소한의 RTTs를 전달함으로써 순수하게 server-rendering만 하는 성능에 다다를 수 있습니다. HTTP/2 Server Push 또는 <link rel=preload>를 사용해 중요한 스크립트와 데이터를 더 빨리 전달할 수 있고, 이는 parser가 더 빨리 작동하게 해줍니다. PRPL과 같은 패턴은 초기와 그다음 탐색이 즉각적으로 느껴지도록 하기 위해 고려해 볼 가치가 있습니다.

주요 단점은 애플리케이션이 커짐에 따라, 필요한 JavaScript의 양도 커지는 경향 있는 것입니다. 특히, 컴퓨터 성능을 차지하기 위해 경쟁하고, 페이지의 컨텐츠가 렌더링 되기 전에 종종 처리돼야 하는 새로운 JavaScript 라이브러리, polyfills, third-party 코드가 더해져 어려워집니다. 대형 JavaScript 번들에 의존하는 CSR로 구축된 프로젝트는 공격적인 code-splitting을 고려해야 하며, JavaScript를 lazy-load 해야 합니다(필요할 때 필요한 것만 서비스하도록). 상호작용이 거의 없거나 전혀 없는 경우, Server Rendering은 이러한 문제에 대해 좀 더 확장 가능한 솔루션을 대표할 수 있습니다.

SPA(Single Page Application)를 만드는 경우, 대부분의 페이지에서 공유하는 사용자 인터페이스의 핵심 부분을 식별하는 것에 Application Shell caching을 적용할 수 있습니다. Service worker와 결합하면, 재방문할 경우, 성능을 획기적으로 개선할 수 있습니다.

Rehydration을 통한 Server rendering과 CSR의 결합

흔히 Universal Rendering 또는 간단히 "SSR"이라 불리는 이 접근 방식은 Client-side rendering과 Server Rendering 사이의 장단점을 절충하기 위해 두 가지 방법을 모두 시도합니다. 전체 페이지 로드 또는 reloads와 같은 내비게이션 요청은 응용 프로그램을 HTML로 렌더링 하는 서버에 의해 처리되며, 렌더링에 사용되는 JavaScript와 데이터가 결과 문서에 내장됩니다. Server Rendering과 마찬가지로 빠른 FCP을 달성한 다음, (re)hydration이라는 기술을 사용해 클라이언트에서 다시 렌더링 하여 "계속해서 진행"합니다. 이것은 좋은 해결책이지만 성능 측면에서 상당한 단점이 있을 수 있습니다.

Rehydration에서 SSR은 FP를 개선하더라도, TTI에 상당한 부정적인 영향을 미칠 수 있는 단점이 있습니다. SSR된 페이지는 종종 믿을 수 없을 정도로 빨리 로드되는 것처럼 보이지만, 클라이언트 측 JS를 실행하고 이벤트 핸들러를 부착하기 전에는 입력에 응답할 수 없습니다. 이 작업은 모바일에서 몇 초 또는 몇 분 정도 걸릴 수도 있습니다.

아마도 당신은 직접 경험했을 것입니다. - 페이지가 로드된 것처럼 보이지만 클릭이나 탭 기능은 전혀 안 되는 것을. 이것은 금방 좌절감을 느끼게 됩니다. "왜 아무것도 안되고? 왜 스크롤이 안돼?"

Rehydration의 문제점: 2개 비용의 App 하나


Streaming server rendering and Progressive Rehydration

Partial Rehydration

Trisomorphic Rendering


SEO Considerations


Wrapping up...

참고
https://www.fasterize.com/en/blog/understand-and-improve-the-time-to-interactive/![](https://velog.velcdn.com/images%2Fsmkim2339%2Fpost%2F6a0554bc-2061-43d8-a138-c7bfdb1bba47%2Fimage.png)

0개의 댓글