오도원입니다.

건강과 행복을 위하여

프로젝트/니랑내랑

Express 10. 라우터 분리하기

오도원공육사 2020. 2. 20. 15:31
반응형

https://github.com/ohdowon064/Node.js

 

ohdowon064/Node.js

for nodejs study. Contribute to ohdowon064/Node.js development by creating an account on GitHub.

github.com

 

조금씩 nodejs가 이해되기 시작한다. 생활코딩 정말 추천한다. 

라우터 분리 전 전체 코드

기존의 코드를 살펴보자. 

const express = require('express');
const app = express(); // express()함수는 application 객체를 반환한다.
const fs = require('fs'); // file system 모듈
const template = require('./lib/template.js');
const path = require('path');
const sanitizeHtml = require('sanitize-html');
const bodyParser = require('body-parser'); 
const compression = require('compression'); // 데이터 압축 송수신

app.use(express.static('public')); // public 디렉토리의 static file 등록
app.use(bodyParser.urlencoded({extended : false})); // request 객체의 body property를 생성한다.
app.use(compression());

app.get('*', (req, res, next) => {
	fs.readdir('./data', (err, filelist) => {
    	req.list = filelist;
        next();
    });
});
// get방식의 모든 주소(*)에서 요청이 들어오면 콜백함수로 fs.readdir을 호출하여
// request객체의 list property에 data 디렉토리의 파일목록을 저장하겠다.

app.get('/', (req, res) => {
	console.log('req.list => [\n\t', req.list, '\n]);
    var title = 'Welcome home!;
    var description = 'Hello, Node.js';
    var list = template.list(req.list);
    var html = template.HTML(title, list,
    	`<h2>${title}</h2>${description}
        <img src="/image/hello.jpg" style="width:300px; display:block; margin-top:10px">
        `,
        `<a href="/topic/create">create</a>`
    );
    res.send(html);
});

app.get('/topic/create', (req, res) => {
	var title = 'WEB - create';
    var list = template.list(req.list);
    var html = template.HTML(title, list
    	`
        <form action="/topic/create_process" method="post">
        <p><input type="text" name="title" placeholder="title"></p>
        <p>
            <textarea name="description" placeholder="description"></textarea>
        </p>
        <p>
            <input type="submit">
        </p>
        </form>
   		`, '');
        res.send(html);
});

app.post('/topic/create_process', (req, res) => {
	var post = req.body; // bodyParser 미들웨어를 통해서 post data가 request 객체의 body property에 할당된다.
    console.log('req.body =>', post);
    var title = post.title;
    var description = post.description;
    fs.writeFile(`data/${title}`, description, 'utf8', (err) => {
    	res.redirect(`/topic/${title}`);
    });
});

app.get('/topic/update/:pageId', (req, res) => {
	var filteredId = path.parse(req.params.pageId).base;
    console.log(req.params.pageId);
    fs.readFile(`data/${filteredId}`, 'utf8', (err, description) => {
    	var title = req.params.pageId;
        var list = template.list(req.list);
        var html = template.HTML(title, list,
        `
        <form action="/topic/update_process" method="post">
        <input type="hidden" name="id" value="${title}">
        <p><input type="text" name="title" placeholder="title" value="${title}"></p>
        <p>
        <textarea name="description" placeholder="description">${description}</textarea>
        </p>
        <p>
        <input type="submit">
        </p>
        </form>
        `,
        `<a href="/topic/create">create</a> <a href="/topic/update/${title}">update</a>`
        );
        res.send(html);
    });
});

app.post('/topic/update_process', (req, res) => {
	var post = req.body;
    var id = post.id;
    var title = post.title;
    var description = post.description;
    fs.rename(`data/${id}`, `data/${title}`, (err) => {
    	fs.writeFile(`data/${title}`, description, 'utf8', (err) => {
        	res.redirect(`/topic/${title}`);
        });
    });
});

app.post('/topic/delete_process', (req, res) => {
	var post = req.body;
    var id = post.id;
    var filteredId = path.parse(id).base;
    fs.unlink(`data/${filteredId}`, (err) => {
    	res.redirect('/');
    });
    console.log('[', post.id, 'file is deleted.]');
});

// 생성, 수정, 삭제가 /topic/:pageId보다 밑에 있게 되면 
// data에서 create, update, delete_process라는 파일이름을 찾게된다.
// 그러므로 순서가 중요하다.
app.get('/topic/:pageId', (req, res, next) => {
	console.log('req.list => ', req.list);
    var filteredId = path.parse(req.params.pageId).base;
    console.log('pageId : ', filteredId);
    fs.readFile(`data/${filteredId}`, 'utf8', (err, description) => {
    	if(err) {
        	next(err);
        } else {
        	var title = req.params.pageId;
            var sanitizedTitle = sanitizeHtml(title);
            var sanitizedDescription = sanitizeHtml(description, {
            	allowedTags:['h1']
            });
            var list = template.list(req.list);
            var html = template.HTML(sanitizedTitle, list,
                `<h2>${sanitizedTitle}</h2>${sanitizedDescription}`,
                ` <a href="/topic/create">create</a>
                <a href="/topic/update/${sanitizedTitle}">update</a>
                <form action="/topic/delete_process" method="post">
                    <input type="hidden" name="id" value="${sanitizedTitle}">
                    <input type="submit" value="delete">
                </form>`
            );
            res.send(html);
        }
    });
});

app.use((req, res, next) => {
	res.status(404).send('Sorry can\'t find that!');
}); 

app.use((err, req, res, next) => {
	console.log(err.stack);
    res.status(500).send('Something broke!');
});

app.listen(3000, () => console.log('Example app listening on port 3000!'));

이 모든 코드가 main에 있으니 매우 복잡하다.

 

라우터 분리하기

topic패스에 대해서 처리하는 라우트와 home 패스 라우트를 분리하여 따로 관리하자.

 

1. topicRouter

const express = require('express');
const router = express.Router();
// express()는 application 객체를 반환하고,
// express.Router()는 router 객체를 반환한다.

... 필요한 모듈들 생략

router.get('/create', (res, res) => {
	... 생략 ...
});

... 생략 ...

module.exports = router;

topic router에서는 패스에 '/topic'을 생략하여 적는다. 또한 router를 사용하므로 app.get이 아닌 router.get으로 적는다. 그리고 모듈을 export하기 위해서는 마지막에 module.exports = 객체명으로 export를 해야한다.

 

2. indexRouter

const express= require('express');
const router = express.Router();

...생략...

module.exports = router;

 

3. main.js

...모듈 생략...
const topicRouter = require('./routes/topic');
const indexRouter = require('./routes/index');

... 생략...

app.use('/', indexRouter);
app.use('/topic', topicRouter);

... 생략...

main.js의 코드도 훨씬 간결해진다. 사용하기 위해서는 require로 해당 모듈을 가져온 이후에 미들웨어 등록한다. 그러면 '/'패스에 대해서 indexRouter 미들웨어가 적용되고, '/topic'으로 시작하는 주소에는 topicRouter 미들웨어가 작동한다. 

반응형