[Node.js] app.use로 미들웨어 사용하기

nemo·2022년 7월 18일
3

Node.js

목록 보기
3/3

미들웨어(middleware)

미들웨어는 요청과 응답 중간에 위치한다. 미들웨어는 함수이며 Express에서는 사실상 거의 모든 게 미들웨어이다. 요청과 응답을 조작하여 기능을 추가하거나 나쁜 요청을 거르기도 한다.

미들웨어는 순서가 있다. 상단에 있는 미들웨어가 먼저 실행되며 하단으로 갈수록 나중에 실행된다. next를 호출을 하느냐 마느냐에 따라 다음 미들웨어가 실행될 수도 있고 실해되지 않을 수도 있다.

미들웨어 사용 방법

  • app.use(미들웨어)
  • app.use(미들웨어 사용경로, 미들웨어)
  • app.METHOD(미들웨어)
  • app.METHOD(미들웨어 사용경로, 미들웨어)

*METHOD: get, post, put 등의 http 메서드


예제 1

app.use((req, res, next) => {
  console.log('미들웨어입니다.');
  next();
});

위 코드에서 미들웨어 함수 영역은 아래와 같다.

(req, res, next) => {
  console.log('미들웨어입니다.');
  next();
}

예제 2

app.get('/', (req, res, next) => {
  res.sendFile(path.join(__dirname, '/index.html'));
  next();
}, (req, res) => {
  throw new Error('에러 발생');
});

위 코드에서 미들웨어 함수 영역은 아래와 같다.
미들웨어 두 개가 연결되어 있는 형태이다.

(req, res, next) => {
  res.sendFile(path.join(__dirname, '/index.html'));
  next();
}, (req, res) => {
  throw new Error('에러 발생');
}

app.use()는 모든 요청에 미들웨어를 실행하며, app.http메서드()는 각 요청에서 미들웨어가 실행된다.
예를 들어, app.get()은 GET 요청에서 미들웨어가 실행되며, app.post()는 POST 요청에서 미들웨어가 실행되는 것이다.

  • app.use(미들웨어)
    모든 요청에서 미들웨어 실행
  • app.use('/user', 미들웨어)
    user로 시작하는 모든 요청에서 미들웨어 실행
  • app.get('/user', 미들웨어)
    user로 시작하는 GET 요청에서 미들웨어 실행
    ...

🐳 next

next는 미들웨어 함수에 대한 콜백 매개변수로 next()를 작성하게 되면 다음 미들웨어 함수가 호출된다.

미들웨어는 여러 개 선언될 수 있다. 각각의 미들웨어 내부에서는 요청에 대한 응답을 할 수도 있고 상황에 따라 응답하지 않고 응답을 다음 미들웨어에 넘길 수 있다.

위에서 말했듯이 next를 호출을 하느냐 마느냐에 따라 다음 미들웨어가 실행될 수도 있고 실해되지 않을 수도 있다.

  • 모든 미들웨어는 동일한 요청 및 응답 개체를 사용하므로 미들웨어를 통해 응답을 보내면 다음 미들웨어는 모두 건너뛴다.
  • 응답 후에도 next()를 호출하여 추가 작업을 실행할 수 있지만, res.send() 또는 res.json()을 추가로 수행할 수는 없다.
  • 응답 전송을 완료하기 위해 next()를 호출할 필요가 없다. res.send(), res.json()은 모든 응답 스트림을 종료하고 응답을 보내기 때문이다.
  • next()를 호출하지 않으면 finalware가 된다. 다음 미들웨어 실행이 필요 없다면 next()를 호출하지 않는다.
  • 응답이 없는 미들웨어 함수에서는 반드시 next()를 호출하여 다음 미들웨어 함수에 제어를 전달해야 한다. 그렇지 않으면 해당 요청은 정지된 채로 방치된다.

예제 1

app.use(middleware1, middleware2, finalware);

상황1. 미들웨어1에서 응답했다면 다음 미들웨어는 건너뛴다.
상황2. 미들웨어1에서 응답하지 않고 next를 사용하여 미들웨어2로 넘어갈 수 있다.


예제 2

아래와 같이 다음에 위치한 미들웨어 함수로 넘어갈 수도 있다.

const express = require('express');
const app = express();

app.use((req, res, next) => {
  console.log('여기에서는 응답을 하지 않음');
  next();
});

app.get('/', function (req, res) {
  res.send('여기에서 응답함'); 
});

app.listen(3000);

morgan, body-parser, cookie-parser 등의 미들웨어는 내부적으로 next를 호출하고 있으므로 따로 next를 호출하지 않아도 연달아 사용할 수 있다.
next를 호출하지 않는 미들웨어는 res.send나 res.sendFile 등의 메서드로 응답을 보내야 한다.


에러 처리 미들웨어

미들웨어에서 에러가 발생하면 에러 처리 미들웨어에 전달된다. 에러 처리 미들웨어는 매개변수가 네 개이며 사용하지 않아도 모두 작성해야 한다.
특별한 경우가 아니라면 해당 파일 가장 아래에 작성한다.

// 에러 처리 미들웨어
app.get('/', (req, res, next) => {
  res.send('GET / 요청에서만 실행됩니다.');
  // res.sendFile(path.join(__dirname, '/index.html'));
  next();
}, (req, res) => {
  throw new Error('에러는 에러 처리 미들웨어로 갑니다.');
});


app.use((err, req, res, next) => {
  console.error(err);
  // 상태 코드 지정
  res.status(500).send(err.message);
});

Express에서 기본적으로 에러를 처리해주긴 하지만, 실무에서는 이런 식으로 직접 에러 처리 미들웨어를 연결해주는 게 좋다.


참고
https://expressjs.com/ko/guide/writing-middleware.html

https://velog.io/@wiostz98kr/Express-middleware-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-morgan

https://dev-dain.tistory.com/67

0개의 댓글