티스토리 뷰

1. 미들웨어

  모듈 형태로 만들어진 라우터를 app.use에 등록하여 사용했다. 이번 시간에는 app.use 부분에 대해 알아보자. 해당 부분은 Express에서 미들웨어를 등록하는 부분이다. 사전에 정의된 미들웨어를 사용할 수도 있고, 사용자가 직접 미들웨어를 설계하여 등록할 수 도 있다. 


  미들웨어는 다음과 같은 일을 수행한다.


  • 모든 코드를 실행
  • 요청 및 응답 오브젝트에 대한 변경을 실행
  • 요청-응답 주기를 종료
  • 스택 내의 그 다음 미들웨어 함수를 호출


  미들웨어는 요청 객체, 응답 객체, next 객체 3가지를 인수로 가지게 된다. 만약 미들웨어가 요청과 응답이 끝나지 않는다면 다음 미들웨어 함수인 next 객체에 인자를 전달하게 된다. 만약 next 객체가 없다면 미들웨어는 정지한채로 동작을 멈추게 된다.


미들웨어의 작동 방식 (출처 : https://expressjs.com/ko/guide/writing-middleware.html)



  아래는 기본적인 형태의 미들웨어이다.  


  

1
2
3
4
5
6
7
8
9
var express = require('express');
var app = express();
 
app.use((req, res, next) => {
  console.log('Hello World!')
  next()
});
 
app.listen(3000);
cs


  app.use로 미들웨어를 등록했으므로 모든 요청에 대해 해당 요청이 실행된다. 


  이와 다르게 특정 요청에서 미들웨어를 실행하기 위해서는 app.get에서 미들웨어를 등록해주면 된다.


1
2
3
app.get('/'function (req, res) {
  res.send('Hello World!');
});
cs



  이처럼 위와 같이 app 메소드를 통해 선언되는 미들웨어를 '애플리케이션 레벨 미들웨어'라고 한다.


2. 미들웨어의 구분


2-1) 애플리케이션 레벨 미들웨어


  앞서 살펴본 app의 메소드를 통해 등록한 미들웨어를 애플리케이션 레벨 미들웨어라고 한다. 


  • app.use : 모든 요청 객체에서 공통으로 사용할 수 있는 미들웨어
  • app.METHOD (get, post 등) : 특정 객체에서만 사용할 수 있는 미들웨어


  애플리케이션 레벨 미들웨어는 특정 라우팅에 맞는 미들웨어를 만들 수도 있다. 


1
2
3
4
5
6
7
8
app.get('/page/:pageId'function(request, response) { 
  fs.readdir('./data'function(error, filelist){
    var filteredId = path.parse(request.params.pageId).base;
    fs.readFile(`data/${filteredId}`, 'utf8'function(err, description){      
      response.send(html);
    });
  });
});
cs


  위와 같이 get Method의 첫번쨰 라우팅 인자를 사용하여 특정 라우팅에서만 작동하는 미들웨어를 개발할 수 있다.


2-2) 라우터 레벨 미들웨어


  라우터에서도 미들웨어를 등록할 수 있다. 애플리케이션 레벨 미들웨어와 기능적으로 동일하지만 app이 아닌 router에서 작동한다는 점만 기억하면 된다. 그렇기 때문에 우선 express 라우터를 선언을 해야한다.


var router = Express.router();

  

  라우터에서 동일하게 미들웨어를 로드한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var app = express();
var router = express.Router();
 
// a middleware function with no mount path. This code is executed for every request to the router
router.use(function (req, res, next) {
  console.log('Time:'Date.now());
  next();
});
 
// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use('/user/:id'function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});
 
// a middleware sub-stack that handles GET requests to the /user/:id path
router.get('/user/:id'function (req, res, next) {
  // if the user ID is 0, skip to the next router
  if (req.params.id == 0) next('route');
  // otherwise pass control to the next middleware function in this stack
  else next(); //
}, function (req, res, next) {
  // render a regular page
  res.render('regular');
});
 
// handler for the /user/:id path, which renders a special page
router.get('/user/:id'function (req, res, next) {
  console.log(req.params.id);
  res.render('special');
});
 
// mount the router on the app
app.use('/', router);
cs

(출처 : https://expressjs.com/ko/guide/writing-middleware.html)


2-3) 오류 처리 미들웨어


  에러 처리를 위해 미들웨어를 사용할 수 있다. 에러 처리를 받는 미들웨어는 앞에서 살펴본 미들웨어와 인자가 다르다. 기본 미들웨어와 동일하지만 앞에 에러 인자를 받게 된다.


1
2
3
app.use(function(err, req, res, next) {
  console.error(err.stack);
});
cs


  해당 미들웨어에서 오류 처리 방법을 정의해주면 오류 처리를 위한 미들웨어를 만들 수 있다. 다음은 오류 처리를 위한 기본적은 미들웨어 예제이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const express = require('express');
let app = express();
 
const http = require('http')
 
// MiddleWare
app.get('/:id', (req, res, next) => {
    let id = req.params.id
    if(id == 1){
        next('error 발생')
    }else{
        res.send('hello world')
    }
})
 
app.use((req, res, next) => {
    console.log('404')
    res.status(404).send('<h1>Not Found Page</h1>')
})
 
app.use((err, req, res, next) => {
    console.log(err)
    res.status(500).send(err)
})
 
http.createServer(app).listen(3000, () => {
    console.log('server on: 3000 Port')
})
cs


  id에 1번이 들어오게 되면 next('error 발생')에 의해 다음 미들웨어를 실행하게 된다. 만약 id가 1이 아닌 경우 next 함수로 이동하지 않기 떄문에 아래의 에러 처리 미들웨어 역시 실행되지 않는다.


  이때 404 에러인 경우 첫번째 에러 처리 미들웨어가 실행되고. 500 에러의 경우 두번째 에러 미들웨어가 실행된다. 미들웨어의 경우 next가 실행된다면 정의된 순서대로 실행되기 떄문에 우리가 원하는 방식의 미들웨어에 맞게 개발 순서를 정해주면된다.



3. Express 제공 미들웨어

  사용자가 위와 같이 자유자재로 미들웨어를 개발하여 사용할 수 있다. 하지만 우리가 자주 사용하게 되는 미들웨어가 있는 경우까지 매번 개발하는 것은 소요 시간이 무척이나 많이 든다. 그렇기 때문에 우린 express가 제공하는 중요 미들웨어를 활용한다면 아주 간편하게 미늗ㄹ웨어 구현이 가능하다.


- Body-parser


  이미 한번 살펴본 적이 있는 데이터 파싱 미들웨어이다. Post 요청의 경우 body 또한 별도의 데이터로 전달을 할 수 있어야 한다. 그 경우 body 데이터를 우리가 활용할 수 있도록 parsing 하는 작업이 필요하다. 이 작업은 매우 많이 사용하게 된다. POST 요청을 하는 대부분의 경우 사용하게 된다. 하지만 이를 위한 미들웨어 개발을 일일이 하는 것은 상당한 작업이다. 따라서 우린 Express에서 제공하는 Body parsing 미들웨어를 사용하면 된다.


1
2
3
4
5
6
7
8
9
10
const express = require('express');
let app = express();
 
const http = require('http')
 
// POST
app.post('/', (req, res, next) => {
    console.log(req.body)
    res.json(req.body)
})
cs


  위와 같은 기본적은 Post 요청이 있다. 해당 요청을 클라이언트가 body 데이터를 사용하기 위해 parsing을 한다고 가정해보자. 우선 body-parser 객체를 선언하자.


const bodyParser = require('body-parser');


  그 다음 우리가 사용하는 npm에서는 body-parser를 사용하기 위한 기본 옵션을 지정해준다. x-www-for-urlencoded 형태의 body를 받게 되는데 해당 옵션을 다음과 같이 설정한다.


app.use(bodyParser.urlencoded({ extended: false }))


  bodyParser 사용을 위해서 JSON 형태로 데이터를 호출한다. 


app.use(bodyParser.json());


  

1
2
3
4
const bodyParser = require('body-parser');
 
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
cs



- compression


  서버에서 전달하게 되는 파일에 대한 압축을 제공해주는 미들웨어이다.


1
2
3
4
var express = require('express')
var compression = require('compression')
 
app.use(compression());
cs


- cookie-parser


  헤더에 포한된 쿠키를 json 형태로 parsing 하는 미들웨어이다.


1
2
3
4
var express = require('express')
var compression = require('cookie-parser')
 
app.use(cookieParser());
cs



댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함