Next.js

Yooncastle·2022년 6월 2일
0

CSR

  • 처음에 빈 html 파일과 static 파일 요청(render) 후
    다시 서버에 리소스 요청(useeffect) >> 처음 로딩 속도가 느림
  • 이후에 필요한 데이터만 rendering >> 반응속도 빠름
  • seo 문제

SSR

  • 처음에 필요한 html 파일만 요청하여 바로 view >> 처음 로딩 속도가 빠름
  • 이후에 필요한 페이지도 지속적으로 요청하여 새로고침>> 느린 반응속도 & 서버 과부화
  • seo 가능


Next.js 는 SSR을 기반으로 하지만, 페이지가 로드된 이후엔 React에서 CSR을 이용하는 방식

  1. 페이지는 서버가 그림

    • pages 안에 폴더를 만들면, 해당 라우팅 페이지들은 서버측에서 먼저 로드
  2. 페이지 내부 동적인 데이터를 패치하는 과정은 CSR

    • 이때의 데이터들은 일단 페이지가 로드된 이후에 클라이언트 측에서 다시 렌더됨
    • SEO에 걸리지 않음

    그렇기 때문에 만약 페이지가 로드될 때 함께 데이터가 패칭되어야 하는 상황이라면(pre-rendering)
    next.js의 데이터 패칭 방식 (getInitialProps, getStaticProps, getStaticPath, getServerSideProps)을 이용해 첫 렌더에 데이터가 패칭될 수 있도록 처리


ServerSide Cycle

  1. Next tjqjrk GET 요청을 받음
  2. 요청에 맞는 Page를 찾음
  3. _app.js 의 getInitialProps가 있으면 실행
  4. Page Component의 getInitialProps가 있으면 실행. pageProps들을 받아온다.
  5. document.js의 getInitialProps가 있으면 실행. pageProps들을 받아온다.
  6. 모든 props들을 구성, _app.js >> page Comopnent 순서로 rendering
  7. 모든 Content를 구성하고 _document.js를 실행하여 html형태로 출력

_app.js에서 전역적으로 데이터 패칭을 할 경우, getStaticProps나 getServerSideProps를 지원하지 않기 때문에 getInitialProps를 이용해야 합니다. 사실 지원하지 않는 것에는 그럴 만한 이유가 있기 때문이지만, 혹시나 사용할 수도 있으니 두 가지 방법을 모두 정리해보았습니다.

1. pages/_app.tsx에서 전역적 데이터 패칭하기 (getInitialProps)

⚠️ 주의 ⚠️ : _app에서 getInitialProps를 사용해 모든 페이지에서 사용할 공통 속성값을 지정할 수 있으나, 이럴 경우 자동 정적 최적화(Automatic Static Optimization)이 비활성화되어 모든 페이지가 서버 사이드 렌더링을 통해 제공됩니다.
출처: 공식문서

Next는 기본적으로 데이터 요구 사항이 없는 경우 페이지가 정적인지 자동으로 확인하고, getInitialProps나 getServerSideProps를 사용하지 않는다면 페이지를 정적 HTML로 사전에 렌더링하여 자동으로 페이지를 최적화합니다.

자동 정적 최적화 : getInitialProps가 없으면, 페이지를 정적 HTML 으로 사전렌더링 해서 정적 최적화를한다. SSR 계산이 없기 때문에 사용자에게 즉시 뿌려지는 ultra fast 로딩이다.

그러나 전역적으로 getInitialProps를 사용하게 되면, 이러한 최적화과정이 일어나지 않습니다. 때문에 Next.js 9.3버전 이후엔 이런 것을 방지하고자 SSR과 SSG를 분리해 getStaticProps / getServerSideProps로 나눠졌으며, 전역적인 데이터 패치 기능을 지원하지 않습니다. 따라서 전역적으로 SSR의 데이터 패칭을 해야만 하는 경우라면 getInitialProps를 써야만 전역적인 패치가 가능합니다. (Next에서 추천하는 방식 x )

기본적으로 getInitialProps를 비롯한 데이터 패칭 메소드들은 리턴한 값을 해당 컴포넌트의 props로 보냅니다. getinitialProps는 context를 기본 props로 받는데, 그 내부엔 ctx객체와 Component가 존재합니다. Component는 해당 컴포넌트를 의미하며, Component로 보내는 ctx 객체의 구성은 다음과 같습니다.

pathname - 현재 pathname /user?type=normal page 접속 시에는 /user
query - 현재 query를 object형태로 출력 /user?type=normal page 접속 시에는 {type: 'normal'}
asPath - 전체 path /user?type=normal page 접속 시에는 /user?type=normal
req - HTTP request object (server only)
res - HTTP response object (server only)
err - Error object if any error is encountered during the rendering

⚠️ 주의 ⚠️

  1. getInitialProps 내부 로직은 서버에서 실행되기 때문에 Client에서만 가능한 로직은 피해야 합니다. (Window, document 등)

  2. 한 페이지를 로드할 때, 하나의 getInitialProps 로직만 실행됩니다. 예를 들어 _app.js에 getInitialProps를 달아서 사용한다면 그 하부 페이지의 getInitialProps는 실행되지 않습니다.
    따라서 커스터마이징을 통해 따로 처리해줘야 합니다.

이런 것들을 고려해보았을 때, 이렇게 _app.tsx를 건들여서 데이터 패칭을 하는 것은 모든 페이지에서 전역적으로 가져와야 하는 데이터가 일괄적일 때 이외엔 지양하는 편이 좋다는 것을 알 수 있습니다.

2. 페이지 별로 데이터 패칭

사실 페이지 별로 데이터 패칭하는 것도 getInitialProps로 가능합니다. 그러나 그것이 정적데이터인지, 페이지 요청마다 렌더되는 데이터인지에 따라 그 방식을 분리한 것이

  • getStaticProps : 빌드시 고정되는 값으로 빌드 이후에는 수정 불가
  • getStaticPath : 동적라우팅 + getStaticProps를 원할 때 사용
  • getServerSideProps : 빌드와 상관없이, 매 페이지 요청마다 데이터를 서버로부터 가져옴

이며, 9.3버전 이후 Next에선 이 세 가지를 이용하는 것을 권고하고 있습니다. 따라서 getInitialProps가 아닌, 이 셋을 이용하는 방식을 정리해보았습니다.

getServerSideProps가 props로 받는 context 객체의 구성

params: 다이나믹 라우트 페이지라면, params를 라우트 파라미터 정보를 가지고 있다.
req: HTTP request object
res: HTTP response object
query: 쿼리스트링
preview: preview 모드 여부 >공식문서
previewData: setPreviewData로 설정된 데이터

Reference

profile
기억보단 기록을

0개의 댓글