[DreamChain DApp] #20 Dynamic Routing 1

in #kr6 years ago (edited)

이전글 - [DreamChain DApp] #19 New Dream Story 페이지

본 내용은 Ethereum and Solidity: The Complete Developer's Guide을 참고해서 작성되었습니다.


이전글에서 new_story 페이지를 완성했었습니다. 그러나 엄밀히 완성은 아닙니다. 페이지는 꾸며져서 동작하나 헤더의 다른 페이지로 이동하는 것이 구현되지 않습니다. 또 헤더의 네비게이션 기능이 미구현 상태입니다.

오래전에 아래와 같은 라우팅 맵을 그린 적이 있습니다.

가만 보면, 라우팅에 컨트랙트 주소가 끼어 들어가 있습니다. 즉, 동적으로 라우팅을 해야 합니다. 불행하게도 Next.js는 기본적으로 동적 라우팅을 지원하지 않습니다. 따라서 몇가지 고생을 해야 합니다.

사용자 라우팅 설정

고생한다는 것은 Next의 기본 라우팅 방식을 사용하지 않고, 사용자 입맛에 맛게 라우팅을 하기 위해 작업해야 한다는 뜻입니다. 이번글에서는 동적 라우팅까지는 다루지 않고, 기존에 Next 라우팅으로 하던 것을 사용자 라우팅 방식으로 변경해서 해보는 것까지 해보겠습니다.

next-routes 설치

Next에서 동적 라우팅을 하기 위해서는 다음과 같은 패키지를 설치해야 합니다.
https://github.com/fridays/next-routes

$ npm install --save next-routes

자세한 내용보다는 사용하는 방법 위주로 설명해보겠습니다. 자세한 내용이 보고 싶은 분은 next-routes 페이지를 방문해 보세요.

이 패키지를 설치하고 나서 다음 두 개의 파일을 별도로 만들어야 합니다.

  • routes.js: 정적 라우트를 포함하여 동적 라우트들을 기술한 파일
  • server.js: Next가 부팅될 때, Next에게 routes.js를 이용하라고 알려주는 역할

위 두 파일 모두 프로젝트의 루트에 생성합니다. routes.js는 라우트들을 기술하기도 하지만, 다른 역할도 하는데, 그것은 동적 라우팅에 용이하도록 몇가지 Helper 모듈을 제공합니다.

routes.js 생성

그럼 먼저 routes.js 파일을 작성합니다. 생성 위치는 프로젝트 루트 입니다.

// the require returns a function,
// so we need to () to invoke the function
const routes= require( 'next-routes' )();

// export some helpers
module.exports= routes;

우선은 별 내용이 없습니다. 동적 라우팅을 위한 내용은 나중에 넣도록 하겠습니다. 우선 routes.js를 이용하여 페이지간의 네비게이션을 보여 드릴 것입니다.
routes.js 코드에서 next-routes 라이브러리를 사용할 때, 마지막에 ()가 들어가는 것을 주의하세요. next-routes의 리턴 결과가 함수가 되어 함수를 실행시키기 위해 ()가 필요합니다.

server.js 생성

server.js 코드는 다음과 같습니다. 그런데 server.js코드도 동적 라우팅 부분이 나중에 추가될 예정이라 아래 코드에서 많은 변화가 있을 것입니다. 그러나 일단 next의 기본 라우팅이 아니라 사용자 라우팅을 테스트 하려고 합니다.

// get createServer from http library
const { createServer }= require( 'http' );
// get next library
const next= require( 'next' );

// run the server as dev mode.
const app= next({
  // so check if production mode
  dev: process.env.NODE_ENV !== 'production'
});

// import routes that we made
const routes= require( './routes' );
// get handler
const handler= routes.getRequestHandler( app );
// setup app
app. prepare().then( () => {
  createServer( handler ).listen( 3000, (error)  => {
    if( error ) throw error;
    console.log( "Ready on localhost:3000" );
  });
});

pakage.json 수정

기억하실지 모르겠지만 Next로 웹서버를 기동하는 명령 npm run dev입니다. 이렇게 하면 Next의 기본 라우팅 방식이 사용됩니다. 사용자 라우팅을 적용하려면 package.json 파일에서 해당 부분을 사용자 라우팅이 실행되도록 수정해야 합니다.

scripts의 "dev": "next dev"라고 되어 있는 것을 위 그림처럼 바꿉니다. 그러면 npm run dev 실행했을 때, 우리가 만든 routes.js 파일이 실행되게 됩니다.

사용자 라우팅 테스트

그럼 기존에 Next 서버를 중지시킵니다. 그런 후 다시 실행시킵니다.

$ npm run dev

조금전에 package.json 파일에서 위 명령을 실행했을 때, 우리가 설정한 routes.js가 실행됩니다. 결과적으로는 차이가 없습니다. 아직 동적 라우팅을 하지 않았기 때문입니다.

간단한 테스트로 new_story 페이지에서 "Create" 버튼으로 DreamStroy가 만들어진 후 index 페이지로 자동으로 이동하는 기능을 넣어 보겠습니다. new_story에서 Create가 제대로 수행된 직후에 Router.pushRoute( '/' );를 넣어주면 됩니다. 이 기능을 사용하기 위해 작성한 routes.js에서 헬퍼인 Router를 불러들여야 합니다.

// import route helper
import { Router } from '../../routes';
(생략)
      await dream_factory.methods
      .createDreamStory( min_down_price_wei, this.state.title, this.state.story )
      .send({
        from: accounts[0]
      });
      // redirect to the index page
      Router.pushRoute( '/' );
    } catch (error) {
      this.setState( { error_msg: error.message } );
    }

이렇게 한 후 new_story 페이지에서 DreamStory 생성이 정상적으로 되면 컨트랙트가 블락체인에 배포된 직후, 페이지가 index 페이지로 이동하게 됩니다.

Header 네이게이션

그럼 사용자 라우팅 방식으로 모든 페이지 상단에 위치하는 헤더의 네비게이션 기능을 구현해 보겠습니다. 현재 Header는 Menu.Item으로 꾸며져 있는데, 이것들을 라우팅이 될 수 있도록 링크로 만들겠습니다.

header.js 파일의 내용을 다음과 같이 변경합니다.

// import react library
import React from 'react';
import { Menu, Input } from 'semantic-ui-react';
// import Link from routes.js
import { Link } from '../routes';

export default () => {
  return (
    <Menu style={{ marginTop: '10px' }}>
      <Link route='/'>
        <a className='item'>DreamChain</a>
      </Link>
      <Menu.Menu position="right">
        <Menu.Item>
          <Input icon='search' placeholder='Search...' />
        </Menu.Item>
        <Link route='/'>
          <a className='item'>Dream Stories</a>
        </Link>
        <Link route='/dream_stories/new_story'>
          <a className='item'>+</a>
        </Link>
      </Menu.Menu>
    </Menu>
  );
};  

위 코드 import { Link } from '../routes';에서는 routes의 Link 헬퍼를 사용하고 있습니다. 그리고 Menu.Item으로 되어 있던 것들을 <Link> 태그로 감쌌습니다. 사실 <Link> 태크는 페이지 이동을 담당하지 않고, 이벤트 핸들러를 연결하는 기능만 하기 때문에 실제 페이지 이동을 위해 태그 사용이 필요합니다.

Header의 "DreamChain"을 누르거나 "Dream Stories"를 누르면 index 페이지로 이동하게 됩니다. "+" 버튼을 누르면 새롭게 DreamStory를 작성할 수 있는 new_story 페이지로 이동하게 됩니다. 위와 같이 Header를 구현한 후 브라우저를 새로고침 해보면 헤더의 링크가 활성화 되는 것을 볼 수 있습니다. 링크를 포인팅 했을 때 아이콘이 변경되며, 색깔이 약간 회색으로 바뀝니다.

인터넷 접속

브라우저가 로컬 서버에 접속해서 도는 것이지만 다음과 같은 에러 메지가 나타날 때가 있습니다.

알아보니 인터넷 접속이 필요합니다. 그 이유는 서버실행 할 때, web3.js에서 Infura API를 통해서 provider를 구성하는 부분에서 인터넷 접속이 필요합니다. 웹 서버 실행할 때 web3 provider가 인터넷 접속이 안될 경우 제대로 설정되지 않아 에러가 발생한 거 같습니다. 혹시 유사한 에러가 발생하면 인터넷 연결을 확인해 보세요. 로컬에서 개발하고 있지만 Rinkeby 테스트넷 접속하여 스마트 컨트랙트와 인터페이싱 해야하므로 인터넷 접속이 필요합니다.


지금까지 한 것이 사용자 라우팅 방식을 설정하고 테스트한 것입니다. 동적 라우팅은 다음 글에서 이어서 쓰겠습니다.

오늘의 실습: 동적 라우팅은 왜 필요할까요?

Coin Marketplace

STEEM 0.24
TRX 0.11
JST 0.031
BTC 60936.15
ETH 2921.43
USDT 1.00
SBD 3.70