나도 예전에는 NextJS는 Server-side Rendering방식이야~ 라고만 생각하며 개발을 한적이 있다.
지금 생각해보면 NextJS가 유명하다고 무작정 따라하기만 했던거 같다... 😭
이번 기회에 공식문서를 정리를 해보며 NextJS의 강점인 pre-render에 대해 알아보자.
NextJS 프레임 워크를 쓰는 가장 큰 이유 중 하나는 pre-render 방식이라고 생각을 한다.
이 pre-render 방식은 무엇이고 기존 React의 render와 무엇이 다른지 알아보자.
Next JS에서는 페이지 단위로 어떠한 렌더링 방식으로 작동할 것인지 선택할 수 있다. 이는 SPA(Single Page Application) 방식을 사용하는 React 방식과 차별점이라고 볼 수 있다.
렌더링 이란? HTML,CSS, 자바스크립트 등 개발자가 작성한 문서가 브라우저에서 출력되는 과정을 말한다.
기존 CSR의 render 방식을 생각해 보자
사이트에 접속시 브라우저는 서버에게 HTML 및 JS 파일을 요청하게 된다.
HTML 파일에는 위 사진과 id가 root인 텅텅 빈 HTML 파일이 오게되고 이후 용량이 무거운 JS파일이 다운 후 DOM을 이 태그 안에 그리면서 rendering이 된다.
이렇게 rendering이 client에서 진행이 되면 속도가 느릴 뿐 아니라 웹 크롤러가 이 사이트가 어떤 사이트인지 알 수가 없어 SEO(검색 엔진 최적화)에 불리해 구글과 같은 검색엔진에 검색을 해도 노출이 잘 되지 않는다.
브라우저에 컴포넌트들이 rendering 되기 전 먼저 rendering 과정을 진행 하여 빠르게 화면에 보여주는 방식
NextJS에서는 Static Site Generation (SSG) 방식과 Server-side Rendering (SSR) 방식으로 pre-render를 진행한다.
아래 사진과 같이 DB에 게시글 정보가 있다고 시나리오를 설정 하자.
하나의 페이지가 SSG 를 사용한다면, 이 페이지의 HTML은 build time에 생성된다.
개발 -> 빌드 -> 배포 과정을 통해 유저가 웹사이트를 확인할 수 있다.
빌드를 하게 되면 코드를 수정하고 싶을 경우 다시 빌드 후 배포 과정을 밟아야 한다.
물론 블로그, 자기소개서나 소개페이지 같은 경우 자주 변경되는 페이지가 아니다 보니 이 SSG 방식을 쓰면 매우 유리하다. 그냥 완성되어 있는 HTML 정적 페이지 자체를 렌더링 시키는것은 브라우저 입장에서 별거 아니기 떄문에 매우매우 빠르기 때문이다.😎
매번 HTML 파일에다가 하드코딩을 해서 빌드 -> 배포 할 수도 있다.
하지만, 서버에 게시글 정보를 저장하고 그 데이터를 fetching해서도 정적 페이지
를 만들고 싶을때가 있을것이다.
그럴 경우에 getStaticProps
를 이용해보자.
위 코드의 경우 우리가 일반적으로 생각하는 정적페이지라고 생각해보자. 이때에는 서버로 부터 fetching 할 필요도 없으니 그냥 정적파일로 빌드 되어서 배포되면 된다.
하지만 게시글 정보가 서버로 부터 받아야 할 경우가 있을 것이다. 이때에는 getStaticProps
를 사용해보자.
이렇게 getStaticProps
를 사용하면 build Time때 이 데이터를 fetching하여 게시글을 받아오고 이 데이터를 기반으로 정적 파일을 만든다.
그렇기에 계속해서 정적파일을 유지할 수 있다. 하지만 Data base에 있는 게시글 정보가 수정 되면 어떻게 될까? 클라이언트 측에서는 빌드타임때 사용한 예전 게시글 정보를 기반으로 보여주기 때문에 새로 업데이트를 하기 위해서는 다시 빌드 후 배포를 진행해야 한다.
자주 변경되는 데이터의 경우 정적파일이 아무리 빠르게 렌더링이 되어서 좋다 하더라도 데이터가 바뀔때마다 빌드 -> 배포 과정을 진행해야 하니 얼마나 비효율 적인가...
그래서 데이터가 잘 바뀌지 않는 포트폴리오나 블로그에 사용하자.
한가지 더 추가하자면 NextJS Default는 SSG 이다.
만약 페이지에 데이터를 동적으로 작용하는 것이 없다면 그 페이지 자체는 정적 파일로 만들어도 충분하지 않을까? Next JS는 내부적으로 판단 하여 해당 페이지를 정적 파일로 만들어 버린다.
SSG 렌더링을 사용하기에는 데이터가 자주 변하는데 그럼 어떻게 할까?
이 때 SSR 방식을 사용하곤 한다. SSG의 경우 서버로 부터 데이터 요청을 빌드타임에 한다.
하지만, SSR의 경우 클라이언트가 프론트엔드 서버에게 Page request를 할때 프론트엔드 서버가 백엔드 서버에게 데이터를 요청한다.
대략적인 흐름을 보자.
- 클라이언트는 프론트 서버에게 브라우저에 보여줄 해당 페이지 자원(HTML,CSS,JS 등등)을 요청한다.
- Front 서버는 Back 서버에게 필요한 정보(게시글)를 요청하여 받는다.
- Front 서버는 이 데이터를 기반으로 HTML,CSS 등 필요한 자원을 만든다.
- Client에게 페이지에 필요한 자원를 제공한다.
SSG와 다른점이 무엇일까? 먼저 데이터를 서버로 부터 언제 받는가이다.
SSR은 새로고침을 할때마다 매번 Client는 프론트서버에게 해당 페이지 자원을 요청하고 게시글 정보를 새롭게 받아오기 때문에 서버의 데이터가 변경되었다 하더라도 새로 빌드 -> 배포 할 필요가 없다.
또한, CSR의 경우 클라이언트 렌더링 할때 데이터를 받아오는 반면 SSR의 경우 page request시 데이터를 요청하기에 빠르게 받아올 수 있다.
하지만, 데이터를 프론트서버로 부터 한번만 받아오기 떄문에 새로고침을 하지 않는 이상 데이터가 re-fetching이 되지 않는 것이 단점이다.
그렇기 때문에 자주 변경되는 정보들은 SSR 방식을 사용하면 현재 페이지에 보여지고 있는 정보와 실제 정보와 다를 수 있다.
사용법은 SSG와 거의 다르지 않다.
page 파일 내에서 getStaticProps -> getServerSideProps
로만 바꾸면 된다.
그럼 NextJS는 아하, 이 데이터는 빌드타임이 아니라 server-side에서 요청해야겠다 로 판단한다.
지금까지 SSG와 SSR에서 데이터를 언제 어떻게 fetching 하여 HTML 파일을 만들어 rendering을 하는지 알아 보았다. Next는 Page 단위로 rendering 방식을 결정하고 있음을 기억하자.
그럼 REACT의 CSR 방식에서는 데이터를 언제 어떻게 불러왔는가 생각을 해보며 글을 정리 해보자.
- 클라이언트가 프론트 서버로 부터 빈 HTML 파일과 JS 파일을 받는다.
- 클라이언트에서 렌더링이 시작되고 Mypage가 렌더링이 되면 post 상태는 null로 초기화가 된다.
- useEffect 훅을 통해 data를 fetching 한다.
- setPost를 통해 data가 백엔드 서버로 부터 받은 정보를 기반으로 post상태를 변화시킨다.
- 클라이언트는 게시글을 볼 수 있다.
차이점이 보이는가? SSG와 SSR의 경우 1번일 때 이미 서버로 부터 데이터를 다 받아온 상태이다.
REACT의 CSR의 경우 3번에서 데이터를 받아온다.
REACT의 경우에는 1번에서 용량이 큰 JS 파일을 한번만 다운 받으면 그 뒤에는 페이지를 옮기 더라도 1번이 생략되어 빠르게 작동한다.
SSR의 경우 페이지 이동시 1번(서버로 부터 페이지 자원을 받음)부터 시작하기에 속도측면에서 역전당한다.
하지만 NextJS에서도 useEffect를 통해 데이터를 Client-sdie에서 받을 수 있다.
좋은 글 감사합니다. NextJS를 바라보는 시야가 넓어졌어요!