본문 바로가기
Programming/13. Book

모던 리액트 Deep Dive - 4장

by @sangseophwang 2024. 3. 2.

SSR이란?

SPA

  • 렌더링, 라우팅에 필요한 대부분의 기능을 서버가 아닌 브라우저의 자바스크립트에 의존하는 방식
    • 최초에 서버에서 최소한의 데이터를 불러온 이후 이미 가지고 있는 JS 리소스와 브라우저 API 기반으로 동작
  • 최초 첫 페이지에 데이터를 불러온 후 페이지 전환은 history.pushState, replaceState로 이뤄진다.
  • body에는 아무런 내용이 없다.

스택의 종류

  • LAMP
    • Linux, Apache, MySQL, PHP/Python
  • JAM
    • JS, API, Markup
  • MEAN
    • MongoDB, Express.js, Angular.js, Node.js

새로운 패러다임의 웹서비스를 향한 요구

  • 웹페이지를 불러오는데 필요한 부분을 사용자에게 전가해도 기기나 환경의 발전으로 괜찮을거라 생각
  • 그에 따른 JS 리소스의 크기와 양도 증가
  • 하지만 기기의 발전에도 사용자 체감(로딩 속도 등)은 여전히 크게 개선되지 않았다.

SSR

  • 최초에 사용자에게 보여줄 페이지를 서버에서 렌더링해 빠르게 사용자에게 화면을 제공하는 방식
  • SPA는 사용자에게 제공되는 JS 번들에서 렌더링 담당 → SSR은 서버에서!
  • 장점
    • 최초 페이지 진입(FCP)이 빠르다. → 서버에서의 HTTP 요청, HTML 그리는 작업이 서버가 더 빠르다
    • SEO → 로봇은 HTML을 가져가 OG, meta 정보로 검색 엔진에 저장하기 때문
    • 누적 레이아웃 이동(CLS)이 적다
      • 사용자에게 페이지를 보여준 후 뒤늦게 어떤 HTML 정보가 추가, 삭제되어 마치 화면이 덜컥거리는 것과 같은 부정적인 사용자 경험 → API 로딩에 따른 레이아웃 이동
    • 사용자의 디바이스 성능에 비교적 자유롭다
    • 보안에 조금 더 안전하다
      • 인증과 같은 민감한 작업을 서버에서 수행
  • 단점
    • 소스코드 작성 시 서버 고려
      • 브라우저 전역 객체인 window, sessionStorage 등
    • 적절한 서버 구축 → 서버가 모든걸 담당하기 때문에 가용량, 복구 전략, 요청 분산 등 고려 필요
    • 서비스 지연에 따른 문제
  • 여러 페이지 전환 기법
    • Paint Holding: 같은 출처에서 라우팅이 일어날 경우 이전 페이지의 모습을 잠깐 보여주는 기법
    • back forward cache: 브라우저 앞으로 가기, 뒤로가기 실행 시 캐시된 페이지 보여주는 기법
    • Shared Element Transitions: 페이지 라우팅 시 컨텍스트를 유지해 부드럽게 전환하는 기법
  • 최근의 SSR은 SPA의 장점을 흡수한 방식이다.
    • 최초 웹사이트 진입 시에는 SSR로 서버에서 완성된 HTML 제공
    • 이후 라우팅에서는 서버에서 내려받은 JS를 바탕으로 SPA처럼 동작

SSR을 위한 react API

renderToString

  • 인수로 넘겨받은 리액트 컴포넌트를 렌더링해 HTML 문자열로 변환하는 함수
    • 인수는 오직 리액트 컴포넌트
  • 클라이언트에서 실행되는 JS 코드를 포함시키거나 렌더링하는 역할 x → 빠른 HTML 제공이 목적
  • 사용자 인터랙션은 이후 진행 (최초 HTML을 빠르게 그려주는게 목적)

renderToStaticMarkup

  • renderToString과 다른 점은 루트 요소에 data-reactroot과 같은 리액트에서만 사용하는 추가적인 DOM 속성을 만들지 않는다는 점
    • data-reactroot은 hydrate 함수에서 루트를 식별하는 기준점으로 사용
  • 순수한 HTML 리턴 → 이 경우 리액트에서 제공하는 useEffect와 같은 브라우저 API 사용 불가
  • 따라서 블로그 글이나 상품 약관 정보와 같이 아무런 브라우저 액션이 없는 정적인 내용만 필요한 경우 유용

renderToNodeStream

  • 브라우저에선 사용 불가
  • 함수 결과물 : Node.js의 ReadableStream → utf-8로 인코딩된 바이트 스트림
  • 응답으로 오는 HTML을 여러 청크로 분할해 조금씩 전달
  • 대부분의 널리 알려진 리액트 SSR 프레임워크는 이걸 채택하고 있다

renderToStaticNodeStream

  • hydrate가 필요없는 순수 HTML을 스트림 방식으로 렌더

hydrate

  • renderToString, renderToNodeStream으로 생성된 HTML 콘텐츠에 JS 핸들러나 이벤트를 붙이는 역할
  • render 함수
    • 컴포넌트와 HTML 요소를 인수로 받는다
    • 두 정보를 바탕으로 HTML 요소에 해당 컴포넌트를 렌더링하며, 여기에 이벤트 핸들러를 붙이는 작업까지 모두 한 번에 수행
  • hydrate
    • 이미 렌더링된 HTML이 있다는 가정하에 작업 수행
    • 렌더링된 HTML을 기준으로 이벤트를 붙이는 작업만 실행
    • 따라서 서버에서 제공해준 HTML이 클라이언트의 결과물과 같지 않을 때 다음 에러 노출
      • Warning: Expected server HTML to contain a matching …

Next.js 톺아보기

next/link

  • SSR이 아닌 클라이언트에서 필요한 JS만 불러온 뒤 라우팅하는 CSR 방식으로 동작
  • 자연스러운 라우팅 제공
  • 속성
    • scroll: 페이지 이동 시 스크롤 유지 여부
    • replace: 브라우저 기록을 URL에 추가하는 대신 현재 기록을 대체
    • prefetch: link 컴포넌트가 뷰포트에 보이면 해당 경로를 미리 페칭할지 말지 여부 결정

getStaticProps

  • 정적 페이지
  • 미리 빌드해놓고 빠르게 렌더링
  • 블로그 글이나 약관 같이 단순한 콘텐츠를 빠르게 제공하기만 하는 경우

getServerSideProps

  • 서버에서 실행
    • 클라이언트에서만 실행 가능한 변수, 함수, 라이브러리 실행 불가
  • 사용자가 매 페이지를 호출할 때마다 실행
  • 이 실행이 끝나기 전까지는 사용자에게 어떠한 HTML도 보여줄 수 없다.

getInitialProps

  • 때에 따라 서버, 클라이언트 모두 실행
  • getServerSideProps, getStaticProps 나오기 이전에 사용하던 페이지 데이터 페칭 수단
  • _app.tsx와 같이 일부 페이지에서는 getInitialProps밖에 사용 불가

scss

  • scss에서 제공하는 variable을 컴포넌트에서 사용하고 싶다면 export 문법을 사용하면 된다.
반응형

댓글