1. 라우터를 만들어보자.
Browser Router (History API)
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> </div> <script> // History API를 이용한 router function createRouter() { const callbacks = []; function observe(callback) { callbacks.push(callback); } function notify() { callbacks.forEach(callback => callback()); } function push(url) { history.pushState(null, null, url); notify(); } function getUrl() { return location.pathname.replace('/sipmle-router', '').replace('/index.html', '') || '/'; } function getQuery() { const searchParams = new URLSearchParams(location.search); return [ ...searchParams.entries() ].reduce((query, [key, value]) => { query[key] = value; return query; }, {}); } function init() { window.addEventListener('popstate', notify); } init(); return { observe, push, getUrl, getQuery, } } function render() { const $app = document.querySelector('#app'); const currentUrl = router.getUrl(); $app.innerHTML = ` <p>id: ${router.getQuery().id}</p> ${ currentUrl === '/' ? `Home` : currentUrl === '/editor/' ? `Editor` : '404 NotFound' } `; } const router = createRouter(); router.observe(render); render(); </script> </body> </html>
Hash Router
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> </div> <script> // Hash를 이용한 router function createRouter() { const callbacks = []; function observe(callback) { callbacks.push(callback); } function notify() { callbacks.forEach(callback => callback()); } function push(path) { location.hash = path; notify(); } function getUrl() { return location.hash.replace('#', ''); } function getQuery() { const search = location.hash .split('#').pop() .split('?').pop(); const searchParams = new URLSearchParams(search); return [ ...searchParams.entries() ].reduce((query, [key, value]) => { query[key] = value; return query; }, {}); } function init() { window.addEventListener('hashchange', notify); } init(); return { observe, push, getUrl, getQuery, } } function render() { const $app = document.querySelector('#app'); const currentUrl = router.getUrl(); $app.innerHTML = ` <p>id: ${router.getQuery().id}</p> <ul> <li><a href="#/editor">editor 페이지로 ㄱㄱ</a></li> <li><a href="#/sejin">sejin 페이지로 ㄱㄱ</a></li> <li><a href="#/jisung">jisung 페이지로 ㄱㄱ</a></li> <li><a href="#/sunbird">sunbird 페이지로 ㄱㄱ</a></li> <li><a href="#/seeyoujeong">seeyoujeong 페이지로 ㄱㄱ</a></li> <li><a href="#/jiinyy">jiinyy 페이지로 ㄱㄱ</a></li> </ul> ${ currentUrl === '/' ? `Home` : currentUrl === '/editor' ? `Editor` : currentUrl === '/sejin' ? `세진님의 페이지` : currentUrl === '/jisung' ? `지성님의 페이지` : currentUrl === '/sunbird' ? `혜성님의 페이지` : currentUrl === '/seeyoujeong' ? `찬욱님의 페이지` : currentUrl === '/jiinyy' ? `지현님의 페이지` : '404 NotFound' } `; } const router = createRouter(); router.observe(render); render(); </script> </body> </html>
Server Router
const express = require('express'); const { join } = require("path"); const app = express(); app.get('/foo', (req, res) => { res.send('foo 페이지 입니다.'); }) app.get('/home', (req, res) => { res.send('home 페이지 입니다.'); }) app.get('/*', (req, res) => { res.send('404 페이지 입니다.'); }) app.listen(3000, () => { console.log('서버가 실행되었습니다 : http://localhost:3000'); })
Browser Router + Server Router
const express = require('express'); const { join } = require("path"); const app = express(); app.get('/*', (req, res) => { res.sendFile(join(__dirname, 'index.html')) }) app.listen(3000, () => { console.log('서버가 실행되었습니다 : http://localhost:3000'); })
- router의 interface를 똑같이 정의한다.
- router를 사용하는 사람 입장에서는 그 내부 구현은 관심이 없다. 잘 동작하기만 하면 된다.
- hash로 되어있든
- history로 되어있든
- 관심 없고
- 현재 path를 잘 반환해주고, 이에 대한 렌더링 잘 해주고 → 라우터의 역할
- history api를 사용한 router의 경우 완전히 정상동작을 보장하려면, server 가 필요하다.
2. QnA
Q.