-
[생활코딩] Node.js 강의 12일차 (Web3-Express)Node.js 2021. 7. 2. 18:26
Express 미들웨어의 사용 - body parser
Express의 중요한 기능은 1. 라우트 2.미들웨어 , 이 두가지가 있다.
미들웨어란? 서비스를 운영체계 상관없이 애플리케이션에 제공하는 소프트웨어이다.
Middleware is a type of computer software that provides services to software applications beyond those available from the operating system (Wikipedia)
쉽게 이야기해보자. 소프트웨어를 만들때 처음부터 끝까지 다 만드는 경우는 거의 없다. 미들웨어는 다른 사람이 만든 소프트웨어를 부품으로 쓸 수 있게 해준다. 정확한 정의는 아니지만, 다른 사람이 만든 소프트웨어를 미들웨어라고 치자. Third-party middleware는 express가 공식적으로 만들지 않고 다른 사람이 만든 미들웨어라는 뜻이다.
수업에서는 body-parser라는 미들웨어를 사용해봤다. (http://expressjs.com/en/resources/middleware/body-parser.html)
body : 웹 브라우저에서 요청한 정보의 본체. ( header: 그 본체를 설명하는 데이터)
body-parser : 그 본체인 데이터를 분석해서 필요한 형태로 가공해주는 프로그램
일단 body-parser가 설치가 됐는지 확인해주고 시작하겠다.
npm show body-parser version
설치가 안됐다면
npm install body-parser --save
body-parser main.js에 적용
app.use() 이 괄호 안은 body-parser가 만들어낸 미들웨어를 표현한다. main.js가 실행될때마다 괄호안의 미들웨어가 실행된다. body-parser는 사용자가 전송한 post 데이터를 내부적으로 분석해서 모든 데이터를 가지고 온 다음에 create_process, update_process, delete_process 각 라우터에 해당되는 callback 함수를 호출한다. 그렇게 약속됐다. 호출하면서 callback 함수의 첫번째 인자인 request 에 body property를 만들어준다. (원래 request에는 body property는 없었다.)
var express = require('express') var app = express() var bodyParser = require('body-parser'); /*생략*/ app.post('/create_process',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(`/?id=${title}`); }) /* 이전 코드 var body = ''; request.on('data',function(data){ body = body + data; }); request.on('end',function(){ var post = qs.parse(body); var title = post.title; var description = post.description; fs.writeFile(`data/${title}`,description,'utf8', function(err){ response.redirect(`/?id=${title}`); }) }); */ }); /*생략*/
Express 미들웨어의 사용 - compression
compression 설치가 됐는지 확인해주고 시작하겠다. (http://expressjs.com/en/resources/middleware/compression.html)
npm show compression version
설치가 안됐다면
npm install compression --save
compression main.js 적용
compression을 호출하면 미들웨어를 리턴하도록 약속되었고, 이 미들웨어가 app.use로 장착된다. 그러면 우리 애플리케이션은 요청이 들어올때마다 body parser 미들웨어가 호출되고 compression 미들웨어가 실행되길 약속되었다.
var express = require('express') var app = express() var fs = require('fs'); var path = require('path'); var sanitizeHtml =require('sanitize-html'); var bodyParser = require('body-parser'); var compression = require('compression'); var template = require('./lib/template.js'); var qs = require('querystring'); app.use(bodyParser.urlencoded({extended:false})); app.use(compression()); /*생략*/
(강제로 리로드 - 윈도우: ctrl +shift +R / 맥 : cmd+shift+R)
compression이 적용되고 원래 33.3 kB가 4.9kB 로 압축돼 네트워크에 전송되는것을 확인할 수 있다.
compression 적용 결과
Express 미들웨어 만들기
폴더에서 파일을 읽어오는 아래 코드가 곳곳에서 사용돼 미들웨어로 만들어주는 작업을 했다.
fs.readdir('./data',function(error,filelist){/*생략*/});
먼저 app.use로 요청이 들어올때마다 수행하는 코드를 작성해봤다.
app.use(function(request,response,next){ fs.readdir('./data',function(error,filelist){ request.list =filelist; next(); }); });
하지만 post 방식인, create_process, update_process, delete_process에는 위 코드가 필요가 없다. 그럼 안읽어주는게 효율적이기에 get방식인 라우터만 적용되게 코드를 바꿔줬다.
app.get('*',function(request,response,next){ fs.readdir('./data',function(error,filelist){ request.list =filelist; next(); }); });
위 코드와 아래코드를 비교해보면, app.get의 두번째 인자는 미들웨어라는 것을 알 수 있다. Express에서는 모든게 middleware라고 할 수 있다.
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,`<h2>${title}</h2>${description}`, `<a href ="/create">create</a>`); response.send(html); });
애플리케이션이 구동될때, 순서대로 등록된 작은 프로그램들이 실행되고 각각의 프로그램들이 서로서로 연결해주는 작은 소프트웨어라는 점에서 'middleware'라는 표현을 쓰는 듯하다.
Express 미들웨어의 실행순서
우리가 만든 미들웨어는 Application-level middleware 강의에서는 이것만 다룸, 더 자세한 내용은 여기서 확인하자.
app.use(함수)를 작성하면 미들웨어가 등록된다. 미들웨어의 핵심은 request와 response 객체를 받아서 변형할 수 있다. next라는 함수를 호출해서 다음에 실행되어야할 미들웨어를 실행할지 실행하지 않을지 , 그 미들웨어의 이전 미들웨어가 결정하도록 한다는 것이 핵심이다.
var app = express() app.use(function(req,res,next){ console.log('Time:'.Date.now()) next() })
미들웨어가 여러개 등록될수있다. 1번함수가 실행되고 next를 호출하면, 2번함수를 호출하는 것과 다름 없음. 순서대로 실행됨.
app.use('/user/:id', /*1번함수*/ function(req, res, next) { console.log('Request URL:', req.originalUrl); next(); },/*2번함수*/ function (req, res, next) { console.log('Request Type:', req.method); next(); });
조건문을 통해 처리할 수도 있다. user ID가 0이면 다음 라우트 3번이 실행되고, 아니라면 같은 라우트 안의 2번이 실행된다.
app.get('/user/:id', /*1번*/function (req, res, next) { // if the user ID is 0, skip to the next route if (req.params.id == 0) next('route'); // otherwise pass the control to the next middleware function in this stack else next(); // }, /*2번*/function (req, res, next) { // render a regular page res.render('regular'); }); // handler for the /user/:id path, which renders a special page app.get('/user/:id',/*3번*/ function (req, res, next) { res.render('special'); });
강의 코드
var express = require('express') var app = express() var fs = require('fs'); var path = require('path'); var sanitizeHtml =require('sanitize-html'); var bodyParser = require('body-parser'); var compression = require('compression'); var template = require('./lib/template.js'); var qs = require('querystring'); app.use(bodyParser.urlencoded({extended:false})); app.use(compression()); app.get('*',function(request,response,next){ fs.readdir('./data',function(error,filelist){ request.list =filelist; next(); }); }); 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,`<h2>${title}</h2>${description}`, `<a href ="/create">create</a>`); response.send(html); }); 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,{ allowedTags:['h1'] }); var list = template.list(request.list); var html= template.html(title,list,`<h2>${sanitizedTitle}</h2>${sanitizedDescription}`, `<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>`); response.send(html); }); }); 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_process" method="post"> <p><input type="text" name="title" placeholder="text"></p> <p> <textarea name="description" placeholder="description"></textarea> </p> <p> <input type="submit"> </p> </form> `,''); response.send(html); }); app.post('/create_process',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(`/?id=${title}`); }) }); 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 action="/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="/create">create</a> <a href="/update/${title}">update</a>` ); response.send(html); }); }); app.post('/update_process', 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(error){ fs.writeFile(`data/${title}`, description, 'utf8', function(err){ response.writeHead(302, {Location: `/page/${title}`}); response.end(); }); }); }); 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(3000, function(){ console.log('Example app listening on port 3000!') });
'Node.js' 카테고리의 다른 글
[생활코딩] Node.js 강의 14일차 (Web3-Express) (0) 2021.07.19 [생활코딩] Node.js 강의 13일차 (Web3-Express) (0) 2021.07.14 [생활코딩] Node.js 강의 11일차 (Web3-Express) (0) 2021.07.02 [생활코딩] Node.js 강의 10일차 (Web3-Express) (0) 2021.07.02 [생활코딩] Node.js 강의 9일차 (0) 2021.07.01