ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [2019.08.18] Next.js - React의 Server Side Rendering 프레임워크
    개발 블로깅/Next.js 2019. 8. 18. 20:28

     

    우선 Next.js를 설명하자면, 리액트를 서버사이드 렌더링 방식으로 쉽게 구현할 수 있도록 환경을 제공해주는 프레임워크이다.

     

    # 서버사이드 렌더링이란?

     

    서버사이드 렌더링이란, 클라이언트 단에서 작업하던 View와 Controller를 서버에서 직접 작업하는 것이다.

     

    클라이언트 사이드 렌더링은, 리액트로 뷰를 만들고, 각 각 필요로 한 데이터를 서버 API에 요청하여 사용하는 방식으로, 클라이언트와 서버가 분리되어 가동되는 방식이다.

    서버사이드 렌더링은 클라이언트에서 하는 모든 작업을 서버에서 작업하여 뷰를 사용자에게 보여주는 방식이다.

    Next.js를 사용하면, 리액트에서 이러한 서버사이드 렌더링을 쉽게 구현할 수 있다.

     

    # Next.js 기본 세팅

    프로젝트 환경을 우선 구축한다. 

    프로젝트 폴더 생성과 next.js구현에 필요로 한 기본 패키지를 설치한다.

    $ mkdir helloNext
    $ cd helloNext
    $ yarn init -y
    $ yarn add react react-dom next

    next에서는 pages라는 폴더가 필요로 합니다. pages폴더에 들어있는 파일들이 View의 페이지가 될 것입니다.

    $ mkdir pages

    라우팅으로 페이지가 될 파일들을 해당 pages 폴더에서 사용합니다. 이외의 component로 쓰일 파일들을 'src/~' 방식으로 따로 관리한다.

    pakacge.json

    {
      "name": "hello-next",
      "version": "1.0.0",
      "license": "MIT",
      "scripts": {
        "dev": "next"
      },
      "dependencies": {
        "next": "^2.1.0",
        "react": "^15.4.2",
        "react-dom": "^15.4.2"
      }
    }

    next.js를 실행하기 위해 script 명령어로 next를 추가해준다. 

    next 실행을 하게되면, pages/index.js 파일이 서버 단에서 최초로 가동되어 실행된다.

     

    pages/index.js

    const Index = () => (
        <div>
            <h1>
                Hello inyong~!
            </h1>
        </div>
    );
    
    export default Index;

    pages 안의 페이지 파일은 import React from 'react'; 를 불러오지 않는다. (함수형이든 클래스든 상관없다.)

    Next.js 안에서는 Component 단위의 파일을 포함하여, pages 단위의 파일에서도 React를 선언하지 않고 바로 사용하도록 한다.

     

    그럼 초기 페이지인 pages/index.js를 실행시켜보자.

    $ yarn run dev

     

    결과 화면

    그러면 초기 페이지인 index.js 파일이 브라우저 파일이 화면에 나타는 것을 볼 수 있다.


    # 페이지 라우팅

    이번엔 next.js 파일에 내장되어 있는 라우팅을 이용해서, 여러 페이지를 불러와서 사용해보자.

    pages/about.js

    const About = () => (
      <div>
        <h2>안녕하세요. '이뇽'입니다.</h2>
      </div>
    );
    
    export default About;
    

    pages에 about.js라는 페이지 파일을 하나 더 생성한다. 

    그리고 index.js에서 about 페이지를 라우팅 할 수 있도록, 아래와 같이 수정한다.

    import Link from 'next/link';
    
    const Index = () => {
      return (
        <div>
          Hello inyong~!
    
          <Link href="/about">
            <a>소개</a>
          </Link>
        </div>
      )
    }
    
    export default Index;

     

    결과 화면

    '소개' 링크를 클릭하면, 위처럼 about 페이지가 라우팅 되어 나타는 것을 확인할 수 있다. 

     

    # 공용 컴포넌트 사용

    각 페이지에서 모두 보이는 Header 컴포넌트를 생성하여 사용해보자.

    components/Header.js

    import Link from 'next/Link';
    
    const linkStyle = {
      marginRight: '1rem'
    }
    const Header = () => {
      return (
        <div>
          <Link href="/"><a style={linkStyle}>홈</a></Link>
          <Link href="/about"><a style={linkStyle}>소개</a></Link>
        </div>
      )
    }

    헤더로 사용할 Header.js 파일을 생성한다. 

    Link태그로 페이지 라우팅을 한 부분을 보면, href로 index와 about을 걸어 놓은 거을 확인할 수 있다.

     

    components/Layout.js

    import Header from './Header';
    
    const Layout = ({children}) => (
      <div>
        <Header />
        {children}
      </div>
    );
    
    export default Layout;

    전체 페이지마다 레이아웃 구조를 적용해 줄 수 있도록 Layout.js 파일을 생성한다.

    해당 Layout 내에서, 공용으로 쓸 Header.js 파일을 불러와서 사용한다.

     

    pages/index.js

    import Layout from '../components/Layout';
    
    const Index = () => {
      return (
        <Layout>
          Hello inyong~!
        </Layout>
      )
    }
    
    export default Index;

     

    pages/about.js

    import Layout from '../components/Layout';
    
    const About = () => (
      <Layout>
        <h2>안녕하세요. '이뇽'입니다.</h2>
      </Layout>
    );
    
    export default About;

     

    기존의 pages 내에 있던 페이지 파일들에게, 레이아웃 구조를 적용한 Layout파일을 불러와서 사용하도록 한다.

     

    결과 화면

    모든 페이지에 Header가 적용되어 보여지는 것을 확인할 수 있다.

     

    # 쿼리 파라미터 가져오기

    쿼리 파라미터는 /search?keyword=something 의 형태를 가진다.

    페이지를 하나 생성하여, 쿼리 파라미터를 한번 받아보자.

     

    pages/search.js

    import Layout from '../components/Layout';
    
    const Search = ({url}) => (
      <Layout>
        당신이 검색한 키워드는 "{url.query.keyword}" 입니다.
      </Layout>
    )
    
    export default Search;

     

    그리고 주소창으로 직접 쿼리 파라미터를 날려본다~!

    결과 화면

    주소창을 통해 날린 쿼리 값이 화면에 보이는 것을 확인할 수 있다.

     

    # 외부 데이터 가져오기

    데이터를 가져올 때, 어떻게 동작하느냐에 따라 서버 사이드 렌더가 될 수도 있고, 클라이언트 사이드 렌더가 될 수도 있다.

    Next.js에서는 이러한 동작은 getInitialProps라는

    이러한 동작 기능을 살펴보기 위해, pages 디렉토리에 ssr-test.js라는 페이지 파일을 하나 생성한다.

     

    pages/ssr-test.js

    import Layout from '../components/Layout';
    
    class SSRTest extends React.Component {
      static async getInitialProps ({req}){
        return req ? {from: 'server'} : {from:'client'}
      }
      
      render() {
        return (
          <Layout>
            {this.props.from} 에서 실행이 되었어요~!
          </Layout>
        )
      }
    }

     

    getInitialProps 메소드에서 실행되어 반환되는 값이, 해당 컴포넌트의 props 값으로 전달된다.

    getInitialProps 메소드의 파라미터로는, 무조건 서버 측의 request 값이 들어가게 되므로, 클라이언트의 req 값은 undefined가 된다.

     

    components/Header.js

    import Link from 'next/Link';
    
    const linkStyle = {
      marginRight: '1rem'
    }
    const Header = () => {
      return (
        <div>
          <Link href="/"><a style={linkStyle}>홈</a></Link>
          <Link href="/about"><a style={linkStyle}>소개</a></Link>
          <Link href="/ssr-test"><a style={linkStyle}>SSR 테스트</a></Link>
        </div>
      )
    }
    export default Header;

    ssr-test.js 파일을 실행시킬 수 있도록, 공용 컴포넌트인 Header 파일에 Link를 하나 더 추가해준다.

     

    결과 화면

    주소로 직접 접속하면 'server에서 실행되었다'는 문구가 뜨고, Header 링크로 들어가게 되면 'client에서 실행되었다'는 문구가 뜨게 된다.

     

    이번에는 API로 요청해서 실제 데이터로 fetching을 해보자.

    우선 API요청을 하기 위해 axios를 설치한다.

    $ yarn add axios

     

    그다음에 ssr-test.js 파일을 수정한다.

    pages/ssr-test.js

    import Layout from '../components/Layout';
    import Axios from 'axios';
    
    class SSRTest extends React.Component {
      static async getInitialProps ({req}){
        const response = await Axios.get('https://jsonplaceholder.typicode.com/users');
        return {
          users: response.data
        }
      }
      render() {
        const {users} = this.props;
    
        const userList = users.map(
          user => <li key={user.id}>{user.username}</li>
        )
        return (
          <Layout>
            <ul>
              {userList}
            </ul>
          </Layout>
        )
      }
    }
    
    export default SSRTest;

     

    결과 화면

     

    # prefetch 기능 사용하기

    prefetch는 말 그대로, 라우팅이 일어나기 전, 데이터를 전부 불러온 후에 라우팅을 일으키는 것을 말한다.

    prefetch는 Link 컴포넌트를 사용해서 이뤄진다. 

     

    components/Header.js

    import Link from 'next/Link';
    
    const linkStyle = {
      marginRight: '1rem'
    }
    const Header = () => {
      return (
        <div>
          <Link href="/"><a style={linkStyle}>홈</a></Link>
          <Link href="/about"><a style={linkStyle}>소개</a></Link>
          <Link prefetch href="/ssr-test"><a style={linkStyle}>SSR 테스트</a></Link>
        </div>
      )
    }
    export default Header;
    
    

    세 번째 Link 태그에서 prefetch라는 키워드를 입력하게 되면, 해당 링크를 누를 때 prefetching이 된다.

     

    반응형

    댓글

Designed by Tistory.