노드

노드 미들웨어 특성 이해하기

포칼이 2023. 4. 17. 17:19
//app.js
const express = require('express');
const path = require('path');

const app = express();
app.set('port', process.env.PORT || 3000);

app.use((req, res, next) => {
  console.log('모든 요청에 실행');
  next();
})

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, '/index.html'));
});

app.post('/', (req, res) => {
  res.send('hello express!');
});
 
app.get('/about', (req, res) => {
  res.send('hello express');
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '번 포트에서 대기 중');
});

위의 코드에서 미들웨어 부분이 정확히 어디일까?

app.use((req, res, next) => {
  console.log('모든 요청에 실행');
  next();
}

색칠한 부분을 미들웨어라고 한다. 그리고 그것을 단순히 app.use에 장착한 것이다. 

 

그렇다면 라우터에서도 보면

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, '/index.html'));
});

보면 라우터에서도 미들웨어를 장착할 수 있는 공간이 있다. 

 

*함수가 미들웨어인 것이고 app.use도

app.use('/about', (req, res, next) => {
  console.log('모든 요청에 실행');
  next();
})

이런 식으로 코드를 작성한다면 app.use가 /about 요청에 대하서만 작동하게 된다. 

 

*또한 미들웨어를 꼭 하나만 사용해야 되는 것은 아니다.

app.use((req, res, next) => {
  console.log('1 모든 요청에 실행');
  next();
}, app.use((req, res, next) => {
  console.log('2 모든 요청에 실행');
  next();
}, app.use((req, res, next) => {
  console.log('3모든 요청에 실행');
  next();
})

next() 때문에 1, 2, 3 순차적으로 실행되는 것을 알 수 있다. 

 

익스프레스 에러 처리

익스프레스는 기본적으로 에러가 발생했을때 에러를 처리해준다. 

하지만 익스프레스가 제공하는 에러 페이지는 너무 보안의 위협이 높다. (구조가 다 드러난다)

따라서 에러 처리를 따로 해주는데 그것 또한 미들웨어이다. 

 

//app.js
const express = require('express');
const path = require('path');

const app = express();
app.set('port', process.env.PORT || 3000);

app.use((req, res, next) => {
  console.log('모든 요청에 실행');
  next();
}, (req, res, next) => {
  throw new Error('에러 발생');
})

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, '/index.html'));
});

app.post('/', (req, res) => {
  res.send('hello express!');
});
 
app.get('/about', (req, res) => {
  res.send('hello express');
});

app.use((err, req, res, next) => {
  console.error(err);
  res.send('에러 발생');
})

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '번 포트에서 대기 중');
});

app.js에 에러 처리를 하는 미들웨어를 추가했다.

 

에러 처리 미들웨어는 총 4가지 인자를 받는다. err, req, res, 그리고 next이다. 단, 반드시 4개의 인자를 받아야 하며 하나라도 생략이 되면 안된다. 

 

*라우터나 미들웨어는 next가 생략이 가능하다

 

실행 해보면 다음과 같다

*500 에러가 발생했다.

 

*app.use 또는 app.get, app.post 문에 보면 마지막에 res.send부분이 있는데 모두 기본적으로 200을 돌려주기 때문에

status(200)이 생략되어 있다.

즉, 원래는 res.status(200).send();다. 

 

*한 라우터에서 send, sendFile 또는 json을 한번 이상 하면 에러가 발생한다.

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, '/index.html'));
  res.send(안녕하세요);
  res.json({ hello: 'me'});
});

다 비슷한 send이고 한 번 이상하면 에러가 발생한다. 

노드를 처음 시작했으면 한 번은 반드시 보는 에러 코드이다.

에러가 발생하는 이유는 원래는 send 했으면 거기서 끝나야 한다. 요청 한 번에 하나의 응답을 해야하기 때문이다. 근데 여러번 해 버리면 위와 같은 에러가 발생한다.