1. NVM을 이용한 Node 버전 업데이트

    1. 일단 문제 : NVM이 깔려있는지 몰랐다. 그래서 n이라는 패키지로 설치하려고 했다.
    // 현재 컴터에 설치되있는 Node 버전들을 보여준다.
    nvm list 
    
    // 설치 하고 싶은 Node 버전을 적고 install
    nvm install 16.17.0
    
    // 원하는 Node 버전 사용
    nvm use 16.17.0
    
    // 기존 Node 버전 삭제 하고 싶다면?
    nvm uninstall 14.17.6
    

    스크린샷 2022-09-13 오전 10.11.51.png

  2. Next.js는 클라이언트에게 웹 페이지를 보내기 전에 Server side 단에서 미리 웹페이지를 pre-render한다.

    1. 서버는 pre-rendering으로 인해 생성된 HTML Document를 클라이언트에게 전송한다.
    2. 클라이언트에서 받은 웹 페이지는 단순히 웹 화면만 보여주는 HTML 일 뿐이다. (JS 요소는 없다) === 웹 화면을 보여주고 있지만, 특정 JS 모듈 뿐 아니라 이벤트 리스너 들이 DOM에 적용되지 않은 상태
    3. Next.js Server에서는 Pre-rendering된 HTML만 있는 웹 페이지를 클라이언트에게 보내고 나서, 리액트가 번들링된 자바스크립트 코드를 클라이언트에게 전송한다.
    4. 증거자료

    rendering.png

    e. 브라우저를 열어보면 맨 처음 응답 받는 요소가 document Type 파일이고, 이후에 React 코드들이 렌더링된 JS 파일들이 Chunk 단위로 다운로드 된다.

    1. 이 자바스크립트 코드들이 이전에 보내진 document Type의 HTML DOM 요소 위에서 한 번더 렌더링을 하면서 각자 자리를 찾아가며 매칭되는것을 Hydrate 라고 한다.
    2. 증거 자료

    Hydration.gif

    새롭게 로딩할때 마다 약간 뒤늦게 스타일이 적용, HTML DOM 요소에 뒤늦게 자바스크립트가 동작하고 Hydration 현상

    server에서 한번 렌더링하고, Client에서 한번 더 렌더링 하면 비효율적인 렌더링 방식 아닌가요?

  3. Next.js의 _app.js_document.js 의 역할

    1. 공통점 : server only file 즉 client 로직 eventListener, window, dom 로직을 사용하면 안된다.
    2. _app.js : _app은 로직, 전역 스타일 등 컴포넌트에 공통 데이터를 다룬다.
    // /pages/_app.js
    
    // MyApp이 props로 받은 'Component'는 요청한 페이지이다. /pages/index.js 파일이 props로 내려온다.
    function MyApp({ Component, pageProps }) {
      return (
        <Layout>
        	<Component {...pageProps} />
    	  </Layout>
      );
    }
    
    export default MyApp;
    
    1. _document 는 공통적으로 적용할 HTML 마크업을 중심으로 다룬다. static html을 구성하기 위한 _app.js에서 구성한 컴포넌트가 html body가 어떤 형태로 들어갈지 구성 하는곳.
    // /pages/_document.js
    
    import Document, { Html, Head, Main, NextScript } from 'next/document'
    
    class MyDocument extends Document {
      
      render() {
        return (
          <Html>
            <Head />
            <body>
              <Main />
              <NextScript />
            </body>
          </Html>
        )
      }
    }
    
    export default MyDocument
    

    getInitialProps

    웹 페이지는 각 페이지마다 사전에 불러와야할 데이터들이 있다. CSR에서는 보통 useEffect 훅 안에 Data fetching 로직을 넣는다.

    그렇게 되면 컴포넌트가 마운트 되고나서 데이터를 가져오게 된다.

    <aside> 💡 SSR에서는 이 과정을 서버에서 미리 처리하도록 도와준다.

    </aside>

    Data fetching을 서버에서 하게되면 생기는 이점

    1. 속도가 빨라진다.
      1. 기존 브라우저에서 실행하던 로직을 서버가 하므로 브라우저는 렌더링만 하면된다.
    2. 코드 상의 처리가 깔끔해진다.
      1. 데이터가 꼭 필요한 페이지의 경우에는 (data-fetching을 해야지 페이지가 보이는) 브라우저가 데이터를 가져올 때까지 화면 렌더링을 잠시 null 처리하는 경우가 있다. 이 과정이 없어지고, Initial한 데이터가 들어오는 과정을 전제로 코드 작성 가능.

사용법

/pages/필요한 페이지

import axios from 'axios';

const Page = ({ stars }) => {
  
  return <div>Next stars: {stars}</div>;
};

// getInitialProps 내부 로직은 서버에서 실행된다.
Page.getInitialProps = async ctx => {
  const { data } = await axios.get('...url');

  return { stars: data };
}

export default Page;
export default class MyApp extends App {

	static async getInitialProps({ Component, ctx }) {
		let pageProps = {};
    
    // 실행하고자 하는 component에 getInitialprops가 있으면 실행하여 props를 받아올 수 있다.
		if (Component.getInitialProps) {
			pageProps = await Component.getInitialProps(ctx);
		}

		return {
			pageProps
		};
	}

	render() {
		const { Component, pageProps, router } = this.props;
    
		return (
			<div>
				<Component {...pageProps} />
			</div>

		);
	}
};

_app.js에서 getInitialProps 실행후 pageProps를 받아와서 하위 페이지에 pageProps로 데이터 전달하는 방식.

Next.js의 작동방식 정리

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