목표
다른 이의 미들웨어를 사용하는 것이 아닌, 미들웨어 생산자가 되어 보자!
미들웨어 작성
var express = require('express');
var app = express();
var myLogger = function (req, res, next) {
console.log('LOGGED');
next();
};
app.use(myLogger);
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000);
app.use(함수)
var 함수 = function (req, res, next) {
- req, res, next 객체
- 함수 내부 구성에 따라 third-party middleware와 같은 기능을 가지게 된다.
미들웨어 사용
현재 우리의 코드에서 글 목록을 표현해주는 기능을 가진 readdir가 공통적으로 사용되고 있다. 이를 middleware로 처리를 해보자.
app.use(function(request, response, next) {
fs.readdir('./data', function(err, filelist){
request.list = filelist;
next();
});
});
- next() : 다음에 호출되어야 할 middleware가 실행됨
이제 request.list에는 filelist가 담겨 있다.
// 2. pageId 링크 클릭 시 페이지
app.get('/page/:pageId', function(request, response){
console.log(request.list);
pageId 클릭 시 request.list를 콘솔해보면 다음과 같이 filelist값이 들어가 있는 것을 확인할 수 있다.
request 객체에 list값을 셋팅하여 나온 결과이다. 이를 통해 이제 모든 라우트 안에서 request 객체의 list property를 통해 글 목록을 접근하게 된다. 따라서 각 경우의 수에서 일일이 파일을 readdir를 할 필요가 없다.
// 1. 홈 페이지
// app.get('/', (req, res) => { res.send('Hello World!')})
app.get('/', function(request, response){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list = template.list(request.list);
var html = template.html(title, list,
`<a href="/create">create</a>`,
`<h2>${title}</h2>${description}`
);
response.send(html);
});
readdir를 제거하고 파일이름을 request.list로 변경한다. 다른 코드들도 동일하게 변경한다.
문제점
하지만 이는 비효율적이다. 글 목록을 읽어올 필요가 없는 경우에도 글 목록을 무조건 읽어오기 때문이다.
해결
app.get('*', function(request, response, next) {
app.use -> app.get 으로 수정한다.
그렇게 되면 get 방식으로 들어오는 요청만 파일 목록을 가져오게 된다. 그러면 기존의 post 방식은 파일 목록을 불러오지 않으므로 비효율적이라는 문제를 해결하게 된다.
check
//6. update>제출 버튼 클릭 시 페이지
app.post('/update', function(request, response){
console.log(request.list);
위와 같이 작성하고 글을 update한 후 제출을 누르게 되면 다음과 같이 undefined라고 뜬다. 글 목록 데이터를 가져오지 않았다는 뜻이다. 따라서 우리가 만든 미들웨어를 이용하여 필요한 경우에만 파일 목록을 읽어온다.
코드 다시 살펴보기
여기서 우리가 작성한 코드를 다시 살펴보자.
// 1. 홈 페이지
// app.get('/', (req, res) => { res.send('Hello World!')})
app.get('/', function(request, response){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list = template.list(request.list);
var html = template.html(title, list,
`<a href="/create">create</a>`,
`<h2>${title}</h2>${description}`
);
response.send(html);
});
지금까지 라우트라고만 생각했던 이 코드에서 callback function은 사실 미들웨어였다. 우리가 이전에 만든 것처럼 말이다.
Express에서는 모든 것이 미들웨어로 이뤄져있다해도 과언이 아니다.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(compression());
app.get('*', function(request, response, next) {
fs.readdir('./data', function(err, filelist){
request.list = filelist;
next();
});
});
app.use를 통해 bodyParser 미들웨어가 실행이 되고, 그 다음 compression 미들웨어가 실행된 다음, 우리가 만든 미들웨어가 실행이 되고, 그 후 순서대로 아래로 쭉 실행되다가 path에 해당하는 미들웨어가 실행된다.
미들은 가운데라는 뜻이다. 애플리케이션이 구동될 때 순서대로 등록된 프로그램들이 실행이 되는데, 각각 프로그램들이 서로가 서로를 연결해주는 작은 소프트웨어라는 점에서 미들웨어라는 표현을 사용한다.
전체 코드
const express = require('express');
const app = express();
const fs = require('fs');
const path = require('path');
const qs = require('querystring');
const sanitizeHtml = require('sanitize-html');
const template = require('./lib/template');
const bodyParser = require('body-parser');
const port = 3000;
const compression = require('compression');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(compression());
//파일목록읽는 미들웨어 만들기
app.get('*', function(request, response, next) {
fs.readdir('./data', function(err, filelist){
request.list = filelist;
next();
});
});
// 1. 홈 페이지
// app.get('/', (req, res) => { res.send('Hello World!')})
app.get('/', function(request, response){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list = template.list(request.list);
var html = template.html(title, list,
`<a href="/create">create</a>`,
`<h2>${title}</h2>${description}`
);
response.send(html);
});
// 2. pageId 링크 클릭 시 페이지
app.get('/page/:pageId', function(request, response){
var filteredId = path.parse(request.params.pageId).base;
fs.readFile(`data/${filteredId}`, 'utf8', function(err, description){
var title = request.params.pageId;
var sanitizedTitle = sanitizeHtml(title);
var sanitizedDescription = sanitizeHtml(description);
var list = template.list(request.list);
var html = template.html(sanitizedTitle, list,
`<a href="/create">create</a>
<a href="/update/${sanitizedTitle}">update</a>
<form action="/delete_process" method="post">
<input type="hidden" name="id" value="${sanitizedTitle}">
<input type="submit" value="delete">
</form>
`,
`<h2>${sanitizedTitle}</h2>${sanitizedDescription}`);
response.send(html);
});
});
//3. Create 버튼 클릭 시 페이지
app.get('/create', function(request, response){
var title = 'WEB - create';
var list = template.list(request.list);
var html = template.html(title, list,
'',
`
<form action="/create" 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>
`);
response.send(html);
});
//4. create>제출 버튼 클릭 시 페이지
app.post('/create', function(request, response){
var post = request.body;
var title = post.title;
var description = post.description;
fs.writeFile(`data/${title}`, description, 'utf8',
function(err) {
response.redirect(`/page/${title}`);
});
});
//5. update 버튼 클릭 시 페이지
app.get('/update/:pageId', function(request, response){
var filteredId = path.parse(request.params.pageId).base;
fs.readFile(`data/${filteredId}`, 'utf8', function(err, description){
var title = request.params.pageId;
var list = template.list(request.list);
var html = template.html(title, list,
//form 부분
`
<form action="/update" 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>
`,
``);
response.send(html);
});
});
//6. update>제출 버튼 클릭 시 페이지
app.post('/update', function(request, response){
var post= request.body;
var id = post.id;
var title = post.title;
var description = post.description;
fs.rename(`data/${id}`, `data/${title}`, function(err){
fs.writeFile(`data/${title}`, description, 'utf8',
function(err) {
response.redirect(`/page/${title}`);
});
});
})
//7. delete 버튼 클릭 시 페이지
app.post('/delete_process', function(request, response){
var post = request.body;
var id = post.id;
var filteredId = path.parse(id).base;
fs.unlink(`data/${filteredId}`, function(error){
response.redirect('/');
});
})
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
'Back-End > Node.js' 카테고리의 다른 글
Express - 12. 정적인 파일의 서비스 (0) | 2020.09.08 |
---|---|
Express - 11. 미들웨어의 실행순서 (0) | 2020.09.08 |
Express - 9.2. 미들웨어의 사용 - compression (0) | 2020.09.06 |
Express - 9.1. 미들웨어의 사용 - body parser (0) | 2020.09.06 |
Express - 8. 페이지 삭제 구현 + redirect (0) | 2020.09.06 |