요청과 응답 중간(middle)에 위치하여 미들웨어라고 부른다. 미들웨어는 요청과 응답을 조작하여 기능을 추가하기도 하고, 나쁜 기능을 걸러내기도 한다.
미들웨어는 주로 app.use
와 사용된다.
app.js
를 보면 수많은 app.use
메서드가 사용된다는 것을 알수있다.
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
여기서, app.use
메서드의 인자로 들어있는 함수가 미들웨어이다. 미들웨어는 use 메서드
로 app
에 장착된다.
제일 위에 있는 logger('dev')
부터 시작하여 미들웨어들을 순차적으로 거친 후, 라우터에서 클라이언트로 응답을 보낸다.
이제 직접 미들웨어를 만들어보자! 요청이 들어올경우 콘솔에 메시지를 찍는 단순 미들웨어를 구현할것이다.
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(function(req,res,next) {
console.log(req.url, '저도 미들웨어입니다.');
next();
});
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.set과 app.use 사이에 새로운 미들웨어를 추가해줬다.
app.js를 저장하고 서버를 실행, 그리고 브라우저창에 주소를 입력하여주면
콘솔에 다음과 같이 입력된다.
요청두개, 즉 GET /
와 GET /stylesheets/style.css
가 서버로 전달되었다. 각각의 요청을 통해 커스텀 미들웨어
를 작동시켰다.
이렇게 서버
가 받은 요청은, 미들웨어
를 타고 라우터
까지 전달된다.
다만 주의해야할 점은, 반드시 미들웨어 안에서 next()
를 호출해야만 다음 미들웨어로 넘어간다.
logger, express.json ... 등은 모두 내부적으로 next()
를 호출하기때문에 따로 작성하지 않아도 다음 미들웨어
로 넘어갈 수 있다. next()
는 미들웨어의 흐름을 제어하는 핵심적인 함수이다!
여기서 next 함수
몇가지 기능이 더 있다. 인자의 종류
에 따라 기능이 구분되는데, 구분되는 기능은 다음과 같다.
인자를 아무것도 넣지 않는 경우 : 단순히 다음 미들웨어로 넘김
인자로 route를 넣어줌 : 다음 라우터로 이동
route 외에 다른 값을 넣어줌 : 미들웨어나 라우터를 건너뛰고 바로 에러핸들러로 이동
(넣어준 값은 에러에 대한 내용으로 간주)
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
해당 코드가 에러 핸들링
이 되는 부분이다. 라우터에서 요청이 처리되지 않으면(일치하는 주소가 없다면) 이 미들웨어로 넘어오게 된다.
http-errors(createError) 패키지
가 404 에러
를 만들어내고, 이 에러를 next
에 담아 에러핸들러로 보내준다.
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
이 미들웨어는, 다른 미들웨어와 다르게 4개의 함수 매개변수를 가지게 되는데, err
라는 매개변수가 새로 추가되었다.
next 함수에 넣어준 인자가 err 매개변수
로 연결되는데, 에러 핸들링 미들웨어는 일반적으로 미들웨어 중 가장 아래에 위치하여 위에 있는 미들웨어에서 발생하는 에러를 받아서 처리한다.
콘솔에 나오는 GET / 304 1042.151 ms - -
같은 로그는 모두 morgan 미들웨어
에서 나온다. 해당 미들웨어는 요청에 대한 정보를 콘솔에 기록해준다.
함수의 인자로는 dev가 입력되어있는데, 인자에 따라 콘솔에 나오는 로그가 다르다.
dev인 경우
HTTP 요청(GET) + 주소(/) + HTTP 상태코드 + 응답속도 + 응답바이트
순으로 출력된다.
보통 개발
에서는 short와 dev를, 배포시에는 common
이나 combined
를 많이 사용한다.
세션 관리용 미들웨어로, 로그인 등의 이유로 세션을 구현할때 유용하다.
해당 미들웨어는 express-generator
로 설치되지 않으므로 다음 코드로 설치해야한다.
npm i express-session
설치 후 app.js에 express-generator
를 연결해준다.
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
resave: false,
saveUninitialized: false,
secret: 'secret code',
cookie: {
httpOnly: true,
secure: false,
},
}));
app.use(flash());
app.use('/', indexRouter);
app.use('/users', usersRouter);
이렇게 작성해주면 된다~~~
express-session
은 인자로 세션에 대한 설정을 받는다.
resave : 요청이 왔을때 세션에 수정 사항이 생기지 않더라도 세션을 저장할지?
saveUninitialized : 세션에 저장할 내역이 없어도 저장할지? (방문자 추적시 사용)
secret : 필수항목으로, cookie-parser의 비밀키와 같은 역할
cookie : 세션 쿠키에 대한 설정
express-session
은 세션 관리시 클라이언트에 쿠키를 보내게 되는데, 이를 세션 쿠키
라고 한다. 안전하게 쿠키를 전송하려면 쿠키에 서명을 추가해야 하고, 쿠키를 서명하는데 secret
값이 필요하다.
cookie-parser
의 secret
과 같게 설정해야 한다.