Node JS Web Express framwork 4
Node Express 라우터 사용하기
소프트웨어가 거대해지면 서비스마다 분리하여 관리를 하여 유지/보수를 편리하게 구축해야한다. 따라서 서비스별로 router를 이용하여 경로를 잡아주고 소스를 나누어 줄 수 있다.
우선 현재 예시는 목록과 게시판형태의 서비스만 있기 때문에 홈, topic으로 2분류로 구분하였다.
1. topic 라우터
routes 디렉토리에 우선 tp.js 파일을 만들어 준다.
그리고 main.js에 있던 topic과 관련된 소스를 옮겨 준다.
- routes / tp.js
var express = require('express');
var router = express.Router();//라우터를 사용하기위해 선언
var topic = require("../lib/topic.js");//부모 디렉토리에서 lib 폴더를 접근
var bodyParser =require('body-parser'); //미들웨어인 바디파서를 사용
//미들웨어를 표현하는 표현식 (사용자가 전달한 post데이터를 분석해준다)
router.use(bodyParser.urlencoded({extended:false}));
router.get('/create',(req,res)=>topic.create(req, res));
router.post('/create_process',(req,res)=>topic.create_process(req, res));
router.get('/update/:pageId',(req,res)=>topic.update(req, res));
router.post('/update_process',(req,res)=>topic.update_process(req, res));
router.post('/delete_process',(req,res)=>topic.delete_process(req, res));
// /:pageId로 설정하게 되면 request.params.pageId를 통해 값을 얻을 수 있다.
router.get('/:pageId',(req,res) =>topic.page(req, res));
module.exports=router;//router를 모듈로서 설정하기 위해 export해준다.
주의
페이지를 이동하는 코드의 순서가 중요하다. 따라서 /:pageId가 있는 코드 위에 모든 소스를 위치 하였다.
홈 화면은 따로 index파일로 분류한다.
- routes / index.js
var express = require('express');
var router = express.Router();//라우터를 사용하기 위해 선언
var topic = require("../lib/topic.js");//부모 디렉토리에서 lib 폴더를 접근
router.get('/',(req,res)=>topic.home(req, res));
module.exports=router;
현재 tp 와 index에서 topic 을 lib에서 접근을 하고 있으나, 이렇게 라우터로 구분을 하게 되면 각각 서비스에 해당하는 파일에서 직접 소스를 구현하여도 괜찮을 것 같다.
- main.js
const express = require('express')//모듈을 가져온다
const app = express();
var author = require('./lib/author.js');
var topicRouter = require('./routes/tp'); // 라우터를 통해 tp 사용한다는 의미
var indexRouter = require('./routes/index'); //라우터로 index 읽어오게함
app.use('/topic',topicRouter);//topic경로로 가게되는 페이지는 모두 topiRouter에서 설정해준 ./routes/tp의 내용들을 읽어준다.
app.use('/',indexRouter);
// 특정 경로에 내가 만든 미들웨어를 동작하도록 설정
app.use('/',function(request,response,next){
console.log('Time:',Date.now());
//next는 데이터를 request통해 전달 받고 실행한다는 의미
next();
});
//express 정적 서비스를 가져오는 내장함수 (static(접근경로))
app.use(express.static('public'));
//404 에러가 떴을때 응답하도록 설정
app.use(function(req,res,next){
res.status(404).send('sorroy not found')
})
//에러가 났을때(404가 아닌 쿼리문이나 내부 에러가 났을때)
app.use(function(err, req, res, next){
console.error(err.stack)
res.status(500).send('Something broke')
})
//3000 번 포트일때 반응하도록 설정
app.listen(3000)
페이지와 관련된 부분만 남겨두고 나머지는 라우터를 이용하여 따로 구분하였다.
이 외 파일
- db.js
var mysql = require("mysql");
var db = mysql.createConnection({
host: "localhost",
user: "root",
password: "system",
database: "opentutorials",
});
db.connect();
module.exports = db;
- topic.js
var db = require("../lib/db");
var template = require("../lib/template.js");
var sanitizeHtml = require('sanitize-html');
var path = require('path');
const express = require('express')//모듈을 가져온다
const app = express();
var compression = require('compression'); // 전달할 데이터를 압축하는 모듈
app.use(compression());//압축 사용
exports.home = function (request, response) {
db.query(`SELECT *FROM topic`, function (error, topics) {
var title = "Welcome";
var description = "Hello Node.js";
var list = template.list(topics);
var html = template.html(
title,
list,
`<h2>${title}</h2>${description}
<img src="/images/hello.jpg" width="300px" style="display:block; margin-top:10px">`,
`<a href="/topic/create">create</a>`
);
response.send(html);
});
};
exports.page = function (request, response) {
var pi = path.parse(request.params.pageId).base;
db.query(`SELECT *FROM topic`, function (error, topics) {
if (error) {
throw error;
}
db.query(
`SELECT * FROM topic LEFT JOIN author ON topic.author_id = author.id WHERE topic.id =?`,
[pi],
function (error2, topic) {
if (error2) {
next(err);
} else {
var title = topic[0].title;
var description = topic[0].description;
var list = template.list(topics);
var html = template.html(
title,
list,
`<h2>${sanitizeHtml(title)}</h2>${sanitizeHtml(description)}
<p>by ${sanitizeHtml(topic[0].name)}</p>
`,
`<a href="/topic/create">create</a> <a href="/topic/update/${pi}">update</a>
<form action="/topic/delete_process" method="post">
<input type="hidden" name="id" value="${pi}">
<input type="submit" value="delete">
</form>`
);
response.send(html);
}
}
);
});
};
exports.create = function (request, response) {
db.query(`SELECT *FROM topic`, function (error, topics) {
db.query(`SELECT * FROM author`, function (error2, authors) {
var title = "Create";
var list = template.list(topics);
var html = template.html(
sanitizeHtml(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>
${template.authorSelct(authors)}
</p>
<p><input type="submit"></p></from>`,
`<a href="/topic/create">create</a>`
);
response.send(html);
});
});
};
exports.create_process = function (request, response) {
var post = request.body;
db.query(
`INSERT INTO topic (title, description, created, author_id) VALUES(?, ?, NOW(), ?)`,
[post.title, post.description, post.author],
function (error, result) {
if (error) {
throw error;
}
response.redirect(`/`);
}
);
};
exports.update = function (request, response) {
var pi = path.parse(request.params.pageId).base;
db.query(`SELECT * FROM topic`, function (error, topics) {
if (error) {
throw error;
}
db.query(
`SELECT * FROM topic WHERE id =?`,
[pi],
function (error2, topic) {
if (error2) {
throw error2;
}
db.query(`SELECT * FROM author`, function (error2, authors) {
var list = template.list(topics);
var html = template.html(
sanitizeHtml(topic[0].title),
list,
`<form action="/topic/update_process" method="post">
<input type="hidden" name="id" value="${topic[0].id}"
<p><input type="text" name ="title" placeholder="title" value="${
sanitizeHtml(topic[0].title)
}"></p>
<p><textarea name="description" placeholder="description">${
sanitizeHtml(topic[0].description)
}</textarea></p>
<p>
${template.authorSelct(authors, topic[0].author_id)}
</p>
<p><input type="submit"></p>
</form>`,
`<a href="/topic/create">create</a> <a href="/topic/update/${topic[0].id}">update</a>`
);
response.send(html);
});
}
);
});
};
exports.update_process = function (request, response) {
var post = request.body;
db.query(
`UPDATE topic SET title = ?, description = ?, author_id=? WHERE id = ?`,
[post.title, post.description, post.author, post.id],
function (error, result) {
response.redirect(`/topic/${post.id}`);
}
);
};
exports.delete_process = function (request, response) {
var post = request.body;
db.query(
"DELETE FROM topic WHERE id =?",
[post.id],
function (error, result) {
if (error) {
throw error;
}
response.redirect('/');
}
);
};
- template.js
var sanitizeHtml = require('sanitize-html');
module.exports = {
html: function (title, list, body, control) {
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
<a href="/author">author</a>
${list}
${control}
${body}
</body>
</html>
`;
},
list: function (topics) {
var list = "<ul>";
var i = 0;
while (i < topics.length) {
list += `<li><a href="/topic/${topics[i].id}">${sanitizeHtml(topics[i].title)}</a></li>`;
i++;
}
list = list + "</ul>";
return list;
},authorSelct:function(authors, author_id){
var tag = "";
var i = 0;
while(i < authors.length){
var selected = '';
if(authors[i].id === author_id){
selected = ' selected';
}
tag += `<option value="${authors[i].id}"${selected}>${sanitizeHtml(authors[i].name)}</option>`;
i++;
}
return`
<select name="author">
${tag}
</select>
`
},authorTable:function(authors){
var tag = '<table>';
var i = 0;
while(i < authors.length){
tag +=`
<tr>
<td>${sanitizeHtml(authors[i].name)}</td>
<td>${sanitizeHtml(authors[i].profile)}</td>
<td><a href="/author/update?id=${authors[i].id}">update</a></td>
<td><form action="/author/delete_process" method="post">
<input type="hidden" name="id" value="${authors[i].id}">
<input type="submit" value="delete">
</form>
</td>
</tr>
`
i++;
}
tag +='</table>';
return tag;
}
};