Next.js 구동방식

김태완·2022년 9월 23일
12

React

목록 보기
16/24

Next.js 공부를 하기앞서, Next.js가 어떤식으로 동작하는지 알아보자

Server Side

Next 서버로 요청이 들어오면 Next서버에서 요청이 들어온 페이지에 들어갈 데이터를 Fetch하고 (서버측에서 Fetch를 한다는점이 기존과 다르다) Html을 구성하여 Client로 보내준다.

_app.js와 _document.js ??

  • 가장 최초로 실행되는 파일인데 커스터마이징이 필요시 이 2개의 파일을 통해 커스터마이징을 해줘야한다.
  • 커스터마이징이라하면 styled-components layout meta등등 옵션이 있다.
  • pages 폴더 안에 있다.
  • Next server logic에 사용되는 server only file이므로 Client에서 사용되는 로직을 사용해서는 안된다. 만약 사용한다면 window is not defined라는 에러를 뿜을것이다
  • _app.js -> _document.js 순으로 실행된다.

_app.js

  • _app.js가 가장 먼저 실행되며 이 파일은 전체 컴포넌트의 레이아웃에 해당된다
  • 공통 레이아웃이므로 최초 실행되어 내부에 들어갈 컴포넌트를 실행한다.
function MyApp({ Component, pageProps }) {
  return (
    <Layout>
    	<Component {...pageProps} />
	  </Layout>
  );
}

export default MyApp;

여기서 props로 받는 Component는 요청한 페이지이다.
pageProps는 getInitialProps를 통해 내려받은 props를 말한다.

_document.js

  • _app.js에서 구성한 Html Body가 어떤 형태로 들어갈지 구성해주는 파일이다.
  • content들을 브라우저가 html로 이해하도록 구조화 시켜주는 파일로 이해하면된다
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

_app.js에서 만들어진 content들은 Main 컴포넌트 아래에 실행된다.

_document.js에 클라이언트 로직을 넣으면 안된다.
브라우저는 Main컴포넌트를 제외한 다른 컴포넌트를 initialize하지 않는다.
공통된 로직이 필요하다면 _app.js를 활용하라.

getInitialProps

  • 페이지가 렌더링 되기전에 사전으로 불러와야할 데이터를 명시하는곳이다. 즉 data Fetch를 미리 한다는등의 작업을 서버측에서 미리 할 수 있다.
  • getInitialProps는 레거시이고 getStaticProps, getStaticPaths, getServerSideProps를 사용한다
  • 서버에서 데이터를 처리하기때문에 속도가 빨라지고, loading... 처리가 필요없이 데이터를 신속하게 보여 줄 수 있다.
  • 만약 모든 컴포넌트에서 동일한 데이터가 필요하다면 _app.js에서 getInitialProps를 가져오면 되고, 각각의 컴포넌트마다 다른 데이터가 필요하면 해당 컴포넌트마다 알맞은 getInitialProps를 가져오면 된다.

사용시 주의사항

  • getInitialProps 내부로직은 서버에서 실행되기 때문에 windowdocument같은 Client에서의 로직은 피해야한다.
  • 또한 한 페이지에 하나의 getInitialProps 로직만 실행된다. 따라서 _app.js에 getInitialProps이 있다면 페이지에 있는 getInitialProps는 실행되지 않을거다. 다만 아래처럼 커스터마이징을 한다면 최종 결과를 pageProps에 담을 수 있다
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>

		);
	}
};

default Props

getInitialProps는 기본으로 받는 Context(ctx)라는 props가 있다.

Context의 기본구성은 아래와 같다

  • pathname : 현재 pathName
  • query : 현재 query를 object형태로 출력
  • asPath : 전체 path
  • req
  • res
  • err

ServerSide Cycle

  1. Next Serve가 GET 요청을 받는다
  2. 요청에 맞는 page를 찾는다
  3. _app.js의 getInitialProps가 있다면 실행
  4. Page Component의 getInitialProps가 있다면 실행
  5. _document.js의 getInitialProps가 있다면 실행
  6. pageProps를 구성하여 _app.js 를 통해서 page Component를 렌더링한다.
  7. 모든 Content들을 구성하여 _document.js를 실행하여 html형태로 출력한다

결론

_app.js는 서버로 요청이 들어왔을때 가장 먼저 실행되고 공통 레이아웃 역할을 해준다.
_document.js는 다음으로 실행되며 공통으로 활용할 <head> <body> 안의 내용을 커스텀할때, font 임포트, 웹접근성, charset, styled-components 등을 커스텀하는 역할이다

profile
프론트엔드개발

1개의 댓글

comment-user-thumbnail
2022년 9월 23일

유익한 내용인 것 같습니다. 잘 읽고갑니다.

답글 달기