몇 달 전인가, 이걸 발견하기는 했는데 제대로 활용할 데가 없어서 안 사용하고 있다가,

비교적 최근에 연구실에서 하는 프로젝트 관련해서 사이트를 만들 필요가 있어서, 마침 이 녀석이 생각나서 사용하게 되었다. 그리고 꽤 괜찮더라.

Next.js는 기본적으로 React를 이용한 서버 사이드 렌더링(Server Side Rendering, 이하 SSR) 프레임워크이다. 그 말인 즉슨, React 자체가 기본적으로 SPA(Single Page Application)으로서, 서버에서 HTML을 반환한 후에 데이터만을 주고 받아서 클라이언트에서 렌더링을 진행하는, 클라이언트 사이드 렌더링 프레임워크 인데, SSR은 클라이언트에서도 렌더링하고, 서버에서도 렌더링하겠다는 의미이다. 그럼으로써 얻는 이득은 역시나, 클라이언트에게 있어서 서버의 자원을 빌려서 연산을 할 수 있다는 점!

이 SSR의 개념은 한편으로는 멋있으면서도 과도하게 복잡했다. 가령 Angular의 SSR은 굉장히 복잡하다. Next는 Zeit 팀에 의해 작년 10월 즈음에 나온 아직 1년도 안된 녀석이지만, SSR의 복잡성을 다 없애버렸고 간단하게 구현할 수 있다는 멋있는 점 때문에 나오자마자 폭풍적인 인기를 받아, 현재 안정 버전 2, 베타 버전 3 으로 폭풍 버전 업을 이루고 있다. (여담이지만 Vue에도 Next.js의 영향을 받아 파생된 프로젝트인 Nuxt.js 라는 녀석이 있다.)

몇 달 전에 이 녀석을 봤을 때는 버전 3이 없었는데, 버전 3이 나오면서 멋진 기능이 나와버려서 이를 간단하게 소개하고, 이를 이용해서 프로젝트를 진행하는 방법을 소개하려한다.


잠시 들어가기에 앞서, SSR에 대한 몇 가지 상식을 소개하려 한다.

SSR은 양날의 검이다

SSR은 뭔가 새로운 기술 같고, 기존 프레임워크(예를 들어 Angular나 React, Vue)의 한계점을 끌어 올려 사용할 수 있는 것처럼 보인다.

일면 맞고, 일면 틀리다.

맞는점

  • 한계점을 끌어올릴 수 있다 (클라이언트에서의 초기 렌더링 속도 향상)

틀린점

  • SSR은 기존의 PHP나 JSP, ASP 이 서버에서 하던 작업을 하던 것과 동일한 개념이다
    • 따라서 서버에 과도하게 부담을 줄 수 있는 경우에는 사용을 피하는 것이 좋다.

**SSR은 (전용)어플리케이션 서버가 필요하다**

내가 생각했을 때 SPA의 멋진 점은 딱히 서버가 필요 없다는 점이었다. 가령 나도 몇 번 해보았지만, 뭐 발표자료를 만든다던가, 간단한 웹 어플리케이션을 만들어서 배포할 때 그 배포를 해주는 서버를 내가 관리를 안 해도 됐다. AWS의 S3을 이용한다던가 Firebase의 Storage 를 이용한다던가, Github의 Github Page를 이용한다던가 하물며 한때는(지금은 안되지만) Google Drive를 사용할 수도 있었다. 단순하게 웹 서버의 기능을 해주는, HTTP의 기능을 해주는 서버만 있어도 되었고, 이는 유명 벤더들도 많이 지원하기 때문에 굳이 내가 안 만들어도 되었다.

SSR은 기존의 PHP나 JSP 처럼 서버에서 하던 작업을 해주는 서버가 필요하다. 즉 웹 서버의 역할을 해주는 부분과 렌더링의 역할까지 둘 다 해주는, 어플리케이션을 위한 전용 서버가 따로 필요하다.


**SSR은 기존 소프트웨어에 (때로는 과도한)복잡성을 추가한다**

이 역시 SSR에 익숙하지 않은 사람들에게는 주의해야 하는 부분인데, 서버에서 웹 서버의 역할을 해 주는 부분과 렌더링의 역할까지 해 주는 부분까지 따로 나누어서 라우터를 설계해야 한다. 뭐 익숙해지면 그리 복잡하지도 않을 수도 있지만, 엄연히 약간의 성능 향상을 위해서 투자해야 하는 시간이 굉장히 많으므로, 차라리 기존의 어플리케이션을 더 완벽하게 만드는 것이 훨씬 낫다.



이제, Next.js의 특징과 함께 Next.js에서 버전 3이 되면서 추가된 멋진 기능을 살펴보자.

Next.js에서는 SSR이 너무 너무 쉬워졌다

와, 이건 정말 감탄할 만한 일이다. 이건 Next.js 자체의 특징인데, 이전에도 있던 특징이었고, 그래서 사람들이 열광하기 시작했다.

얼마나 쉽냐면, 딱 다음의 세 과정만 거치면 (간단한)SSR을 구현할 수 있다.

  1. 의존 파일 설치 package.json 파일을 만들고, 설치를 해준다음에(npm install)
// package.json
{
  ...
  "scripts": {
    "start": "next start",
    "dev": "next"
  },
  "dependencies": {
    "react": "^15.5.4",
    "react-dom": "^15.5.4",
    "next": "beta"
  }
}
  1. 페이지 작성 페이지 파일을 만든 다음에
mkdir pages && vi pages/index.js

어플리케이션을 작성하고

// pages/index.js
import React, { Component } from 'react';

export default class IndexPage extends Component {
  render() {
    return (
      <div>Hello, World!</div>
    )
  }
}
  1. 실행 실행을 시키면 localhost:3000에 어플리케이션이 두둥
npm run dev

**Next.js는 어플리케이션 구조를 (반)강제한다**

약간의 자유도를 제한한 대신에 SSR을 쉽게 만들었으니 실보다는 득이 더 많고, 더군다나 Angular에 비해 자유로운 React의 특성 상 프로젝트의 코드가 개발자 개개인의 특성을 타기 쉬운데, Next는 비교적 이를 강제함으로써 기본적인 React의 문법을 가지고 몇 몇 패턴을 크게 벗어나지 않으면서 사용할 수 있다.

가령 각각의 페이지가 될 부분들은 pages 디렉토리 밑에 작성해야하고, index.html의 부분은 pages 디렉토리 밑의 _document.js 파일의 내용이 대체하는 둥, 약간의 제약이 있지만, 내 개인적인 생각으로는 이러한 몇 몇 패턴만 익히면 훨씬 더 자바스크립트의 자유도를 얻게 되서 좋은 것 같다.


**Next.js 버전 3부터는 (전용)어플리케이션 서버가 꼭 필요하지는 않다**

사실 이 이유 때문에 이 글을 쓰고 싶었다. Velopert님도 이미 4월 달인가 Next 관련한 글을 쓰신 게 있기에 다들 그 블로그에서 글을 볼 것임을 알고 있기에 그냥 개인적인 지식으로 정리하고 말려고 했는데, 버전 3에서 새로 생긴 ’export’ 기능이 끝내주기에 이를 꼭 정리하고 싶었다.

어플리케이션 서버가 어떻게 꼭 필요하지 않을 수 있을까? 그것은 바로, hugo나 hexo, jekyll 등의 정적 사이트 제너레이션 역할을 바로 Next.js 버전 3이 해주기 때문이다.

여기(next export (static builds) #604) 참조 «

SSR의 특성 상 서버에서 렌더링 되어야 할 부분도 있는가 하면, React 자체의 특성 상 꼭 서버에서 렌더링 될 필요는 없고 서버에서 렌더링 됨으로써 클라이언트에서 초기 렌더링 속도의 향상이라는 이득을 얻으려는 부분이 있는데, 이러한 경우 어플리케이션을 미리 HTML 파일로 만들어버림으로써 클라이언트에서는 단지 HTML을 렌더링하면 되니 속도가 굉장히 빠르며, 서버에서도 따로 렌더링 할 필요 없이 이미 렌더링 된 놈을 주기만 하면 되니 속도가 굉장히 빠르다!! SSR의 단점을 극복하며 React의 장점을 취한, 내가 생각했을때 웹 어플리케이션의 꽤나 궁극적인 목표에 다가선 녀석이라고 본다.

물론 여기에는 제한점도 있다. 서버에서는 미리 렌더링을 해야 하니까, 특정한 요청을 이용하여 페이지를 렌더링을 할 수는 없다 (props로 req, res 객체를 사용할 수 없다는 내용). 근데 이것은 생각해보면 아주 당연한 내용인 듯 하다.




여기까지는 Next.js의 간략한 소개였다.

이제 Next.js를 이용해서 간단한 예제를 만들어보도록 하자. (다음 글에 계속…!)