오늘은 저번시간에 했던 Mini-Node-Server에서
http모듈을 사용하여 만들었던 과제를
express 라는 프레임워크로 리팩토링 하다가 알게된 것을
정리하여 적어보려합니다.
그럼 먼저, express가 무엇일까??
일단 먼저 확실한건 티익스프레스는 아닙니다.
뭐라구요?? 재미없다구요? 저도알아요
Express.js는 Node.js 환경에서 웹 서버, 또는 API서버를
제작하기 위해 사용되는 프레임워크이다.
앞서 작성했었던 http모듈로 작성한 서버와 다른점은
미들웨어 추가가 편리하고, 자체 라우터를 제공한다는 것이다.
미들웨어 추가가 편리..??
미들웨어가 뭔지알아야 추가가 편리한지를 알죠
미들웨어(middleware)는
- 간단하게 말하면, 클라이언트에게 요청이 오고 그 요청을 보내기위해
응답하려는 중간에 목적에 맞게 처리를 하는 함수들이다. - 미들웨어 함수는 req객체, res객체, 그리고 어플리케이션
요청-응답 사이클 도중 그 다음의 미들웨어 함수에 대한
엑세스 권한을 갖는 함수이다. - 다음 미들웨어 함수에 대한 엑서스는 next함수를 통하여
그 다음 미들웨어로 현재 요청을 넘길 수 있다.
예제를 통해 미들웨어와 next함수에 대해 알아보자
const express = require('express');
/* 1. 앱을 만든다. */
const app = express();
/* 2. 앱에 관련 설정 속성들을 만든다. */
app.set('port', 3000);
/* 3. 공통 미들웨어를 만든다. */
app.use((req, res, next) => {
console.log('모든 요청에 다 실행됩니다.');
// next라는 세 번째 매개변수는 다음 미들웨어로 넘어가는 함수이다.
// next를 실행하지 않으면 다음 미들웨어가 실행되지 않는다.
next();
})
/* 4. 라우터들을 만든다. */
// /error 요청 올때 동작
app.get('/error', (req, res, next) => {
next(); // next()에 인수가 없다면, 바로 다음 미들웨어 함수로 넘어가게 된다.
}, (req, res) => { // 미들웨어를 여러개 넣어줘도 된다. 위에서 next()되면 실행 된다.
try {
// .. 에러 발생 코드
} catch (err) {
next(err); // next()에 인수가 있다면, 에러 처리 미들웨어로 점프하게 된다.
}
});
// /about 요청 올때 동작
app.get('/about', (req, res) => {
res.send('Hello, about');
});
// 주소 부분에는 정규표현식, : (콜론)을 사용한 와일드 카드도 적용이 가능하다 :변수명 정도로 생각하면 된다.
// 와일드 카드를 사용할때는 다른 라우터 보다 뒤에 적어주는 것이 좋다
app.get('/category/:name', (req, res) => {
res.send(`Hello, ${req.params.name}`);
});
// 모든 종류의 get요청이 올때 동작
app.get('*', (req, res) => {
res.send('Hello, 승현 !!');
});
// post 요청 올때 동작
app.post('/', (req, res) => {
res.status(200).send('Hello, 승현 ~~');
});
/* 5. 에러 처리 미들웨어를 만든다. */
app.use((err, req, res, next) => { // 에러 미들웨어는 인자는 반드시 4개 선언
console.error(err);
res
.status(500)
.send(err.message);
})
/* 6. 포트를 연결하여 서버를 실행한다. */
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 대기 중.');
});
위의 코드는 직접 미들웨어를 만들어보고,
next()를 주어 다음 미들웨어 함수를 작동시키게 만들었다.
만약에 첫번째 미들웨어함수에서 next()가 없으면
app.use의 실행이 끝나고 다음으로 넘어가지못한다.
따라서 next()를 주어서, 다음 미들웨어로 넘어가게 해주어야한다.
위의 예제를 뜯어서 살펴보자!!
에러 처리 미들웨어
위의 코드를 보면 app.get에서 미들웨어가 두개가 연결되어있다.
미들웨어 두개는 각각 하나는 매개변수(req, res, next)가 있고,
뒤에 붙은 하나는 매개변수(req, res)가 있다.
첫번째 미들웨어에서
next가 호출되면 바로 다음 미들웨어인
뒤에 붙은 미들웨어로 넘어간다.
그리고 두번째 미들웨어에서 catch로 에러가 잡히면,
next() 함수 인자로 err를 주게되면 바로 에러처리 미들웨어로 점프.
즉, app.get과 app.use 사이에 다른 미들웨어가 있다 하더라도
get에서 에러가 잡혀서 next() 함수 인자로 err가 들어가게되면
바로 use의 에러처리 미들웨어로 점프를 한다는 것이다.
에러처리 미들웨어를 보면 매개변수가 err, req, res, next로
총 네개가 있다.
이 매개변수들을 전부다 사용을 하지않더라도 무조건
매개변수 선언은 네개를 반드시 해주어야한다.
미들웨어 next()
위와같이 next()를 하면 다음 미들웨어로 넘어가고,
next(인수)를 하면 에러 핸들러로 넘어가게된다.
또한, next('route')를 하게되면 다음 미들웨어가 아닌
다음 라우터로 넘어가게된다.
그게 무엇...??
예시를 통해 알아봐보도록하자
app.get에서 true일때, next()에 인수로 'route'를 주어
다음 미들웨어를 건너뛰고, 다음 라우터 app.get이 실행됨.
미들웨어 동작 원리
미들웨어 간 데이터를 전달하는 방법을 보면,
현재 요청이 처리되는 동안 req.data를 통해 미들웨어 간 데이터를 공유할 수 있고,
새로운 요청이 올 시 req.data는 초기화 됨.
여기서 속성명 data는 꼭 data일 필요 없다. 다른거로 지어도된다.
하지만 여기서 유의할 점은 다른 미들웨어의 속성과 겹치지않게 해야한다.
위와 같이
app.use의 미들웨어에서 어떤 무언가의 처리가 되어
req.body라는 키와 밸류가 생성이 되고 next()가 되어서
미들웨어에 의해서 생성된 객체를 다른 미들웨어에서 사용할 수 있게 된다.