ㄷㅣㅆㅣ's Amusement
[React] Node.js + React -- 3. 라우팅(routing) 본문
[React] Node.js + React -- 3. 라우팅(routing)
목차
2017/04/13 - [Programming/React] - [React] Node.js + React -- 1. 초간단 프로젝트 만들기
2017/04/13 - [Programming/React] - [React] Node.js + React -- 2. 개발환경 구축
포스팅 1,2를 하는데에 30분이 채 걸리지 않았으리라 믿어 의심치 않는다.
일단 환경까지 구축했으니... 디폴트 뷰 말고 react를 이용해서 멋드러진(물론 비교대상은 디폴트뷰)를 만들어보자. 그럼 한시간쯤 될듯?
1. react-router
- routing은 문자 그대로 path를 설정해주는 것이다. 예를들어 ("localhost:3000/", "localhost:3000/about", "localhost:3000/404"등 주소에따라 페이지를 다르게 가져가고싶은 경우 설정한다. express로하면 이동할때마다 깜박깜박해서 react-router를 사용했다.
1 | $ npm install react-router@3 --save | cs |
- 위의 커맨드를 날리면 react-router를 어플리케이션에 설치하게되고, package.json에도 해당 모듈을 등록한다.
2. package.json
- package.json은 node로 만든 어플리케이션이 어떤 모듈을 필요로 하는가에 대해서 JSon 형태로 기술되어있는 파일이다. ("npm install"시 "--save"옵션을 주면 설치와 동시에 이 파일에도 써준다.)
- 현재 react-router는 v4까지 나온 상태지만, 아직 안정화가 되기에는 시간이 필요하므로 v3으로 제작해본다. ("@3"을 붙이면 알아서 v3중 최신을 설치한다)
- react-router v4는 나중에 따로 포스팅...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | { "name": "nodereact", "version": "0.1.0", "private": true, "dependencies": { "react": "^15.5.4", "react-dom": "^15.5.4", "react-router": "^3.0.5" }, "devDependencies": { "react-scripts": "0.9.5" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } } | cs |
3. 어플리케이션 구조
4. 컴포넌트 정리
- 우리는 점차 여러 페이지를 만들어 나갈 것이기 때문에 App.js를 ./src 바로 밑에 넣어는것은 바람직해보이지 않는다. 따라서 routing에 의해 결정되는 페이지는 ./src/routes 폴더 밑에 두도록 해보자.
- 이때, 폴더로 나누고 index.js로 하면 나중에 import할 때 폴더명까지만 써주면 된다. (./src/routes/home/index.js --> ./src/routes/home만 해도 됨)
1 2 3 4 | $ mkdir -p routes/Welcome $ mv App.js ./routes/Welcome/index.js $ mv App.css ./routes/Welcome/style.css $ mv logo.svg ./routes/Welcome/logo.svg | cs |
5. 라우팅
- App.js에 만들어진 react code를 렌더링할 수 있었던 이유는 다음과 같이 src/index.js에서 무조건 App을 렌더링하도록 되어있기 때문이다.
1 2 3 4 5 6 7 8 9 10 | // src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import './index.css'; ReactDOM.render( <App />, document.getElementById('root') ); | cs |
- 이제 상위 노드로서 존재하는 src/App.js를 새로 생성한다. (기존에 있던건 route폴더로 옮겼다.)
1 2 3 4 5 6 7 8 9 10 11 12 | // src/App.js import React, {Component} from 'react'; export default class App extends Component { render() { return ( <div> {this.props.children} </div> ); } } | cs |
- 그리고 '/'일 경우에는 기존의 Welcome페이지를, 그 외의 것은 NotFound를 출력하는 페이지를 띄우도록 src/index.js를 수정해준다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import { Router, Route, IndexRoute, browserHistory } from 'react-router'; import App from './App'; import Welcome from './routes/Welcome'; import About from './routes/About'; import NotFound from './routes/404'; import './index.css'; ReactDOM.render( <Router history={browserHistory}> <Route path="/" component={App}> <IndexRoute component={Welcome}/> <Route path="/about" component={About}/> <Route path="*" component={NotFound}/> </Route> </Router>, document.getElementById('root') ); | cs |
- 각자가 생각하는 주소에 (ex. /main, /login 등)라우팅하려면 15번째줄 다음에 등록하면 된다. (ex. <Route path="/main" component={Main}>)
- <IndexRoute>는 '/'이후에 아무 주소가 오지 않는 경우에 띄울 페이지를, <Route path="*",,,>는 상위에서 정의되지 않은 모든 주소에 공통으로 띄울 페이지를 나타낸다. (여기서는 정의되어있지 않는것은 없는 페이지라고 간주.)
- src/index.js의 8번째줄에 보이는 About과 NotFound는 직접 만들어줘야한다.
1 2 3 4 5 6 7 8 9 10 11 12 | // src/routes/404/index.js import React, { Component } from 'react'; export default class NotFound extends Component { render() { return ( <div > <h1> 404 Not Found </h1> </div> ); } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 | // src/routes/About/index.js import React, { Component } from 'react'; export default class NotFound extends Component { render() { return ( <div > <h1><a href="http://www.childc.co.kr" title="ㄷㅣㅆㅣ's Amusement로 가기">I am Childc, come to my blog!! </a></h1> </div> ); } } | cs |
6. 헤더를 만들어 예쁘게 라우팅
- react-router는 Link 기능도 제공한다. 때문에 컨테이너로 그 어떤 값도 전달할 필요 없이 무작정 사용해도 OK.
- 다음의 코드는 react 문법이 조금 들어갔는데, 이부분은 나중에 react문법을 포스팅 하면서 다룬다. (더이상의 자세한 설명은 생략한다)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | // src/Header.js import React, { Component } from 'react'; import { Link } from 'react-router'; import './Header.css'; export default class Header extends Component { MenuItem = function(children, target) { return ( <Link to={target} className="menu-item"> {children} </Link> ); } render() { return ( <div> <div className="title"> childc's react </div> <div className="menu"> {this.MenuItem('Welcome', '/')} {this.MenuItem('About', '/about')} {this.MenuItem('NotFound', '/*')} </div> </div> ); } } | cs |
- 헤더모양은 간단한 css작성만으로도 About에서 보이는 허접한 모양과 달리 그럴싸하게 표현할 수 있다. (나의 미적 감각은 일반적이지 않다는것은 함정)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // src/Header.css .title { width: 100vw; height: 3.5rem; line-height: 3.5rem; color: white; background-color: #222222; font-size: 1.5rem; font-family: monospace; font-weight: bold; text-align: center; } .menu { height: 2.5rem; background-color: #282F38; } .menu-item { display: inline-block; width: 33.3%; line-height: 2.5rem; color: white; font-size: 1.3rem; font-family: monospace; text-align: center; cursor: pointer; transition: background-color 0.5s; text-decoration: none; } .menu-item:hover { background-color: #495057; } .menu-item:active, .menu-item.active { background-color: #08123b; } | cs |
- 최종적으로 최상위 컨테이너(src/App.js)에 헤더를 추가한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // src/App.js import React, {Component} from 'react'; import Header from './Header'; export default class App extends Component { render() { return ( <div> <Header /> {this.props.children} </div> ); } } | cs |
6. 결과물
- 늘 그렇듯 커맨드를 날린다.
$ npm start | cs |
- 헤더의 그 무엇을 클릭하더라도 깜박임은 없다. (물론 브라우저에서 경로를 입력한 경우는 여전이 깜박인다. 그런데 이런 경우는 발생하지 않을 것이므로 처리하지 않음)
'Programming > React' 카테고리의 다른 글
[React] Node.js + React -- 2. 개발환경 구축 (0) | 2017.04.13 |
---|---|
[React] Node.js + React -- 1. 초간단 프로젝트 만들기 (0) | 2017.04.13 |
[React] props와 state (0) | 2016.04.22 |
[React] Component Lifecycle - 리액트 컴포넌트 생명주기 (0) | 2016.04.22 |