Express의 꽃: 커스텀 미들웨어 만들기
Express는 거대한 미들웨어(Middleware) 체인입니다. 미들웨어는 클라이언트의 요청(req)과 응답(res) 사이에 끼어들어(Middle) 조작을 가하는 함수입니다. 남이 만든 플러그인을 쓸 수도 있지만, 우리만의 로직을 담은 커스텀 미들웨어를 만들 줄 알아야 진정한 백엔드 개발자입니다.
미들웨어가 하는 3가지 핵심 역할
| 역할 |
설명 및 예시 |
| 1. 데이터 조작/주입 |
req 객체에 새로운 속성을 추가하여 다음 라우터로 넘겨줍니다. (예: req.user = 'Minstudio' 로 로그인 정보 주입) |
| 2. 요청 차단 (보안) |
로그인 안 한 유저면 next()를 호출하지 않고 곧바로 res.send('꺼져!') 로 응답을 끝내버립니다. 뒤에 있는 라우터는 실행되지 못합니다. |
| 3. 에러 처리로 넘기기 |
진행 중 DB 접속 실패 등 치명적인 에러가 발생하면 next(error) 형태로 넘깁니다. |
🚨 에러 핸들링 미들웨어 (Error-handling Middleware)
Express에서 매개변수가 정확히 4개 (err, req, res, next) 인 함수는 특별하게 에러 전용 미들웨어로 인식됩니다. 일반 미들웨어에서 next(err)를 호출하면, 중간에 있는 수많은 정상 미들웨어들은 모두 무시(Skip)하고 이 에러 전용 미들웨어로 즉시 순간이동(Jump) 합니다. 주로 app.js의 맨 마지막에 단 하나만 배치하여 모든 에러를 중앙 통제합니다.
커스텀 & 에러 핸들링 미들웨어 동작 원리
미들웨어가 req 객체를 조작하여 뒤에 있는 라우터로 데이터를 넘겨주거나, 에러 발생 시 에러 처리 전용 미들웨어로 즉시 점프(Jump)하는 흐름입니다.
const express = require('express');
const app = express();
// 1. 일반 미들웨어 (데이터 주입)
app.use((req, res, next) => {
req.user = 'Minstudio Admin'; // req 객체에 새로운 데이터 주입
console.log(`[미들웨어 A: Data Injector] req.user 주입 완료 -> next()`);
next(); // 다음 미들웨어나 라우터로 정상 진행
});
// 2. 유효성 검사 라우터 (에러 발생 시나리오)
app.get('/error', (req, res, next) => {
console.log(`[미들웨어 B: Validator] 필수 파라미터 누락 확인! -> next(err) 호출`);
// next() 안에 값이 들어가면 정상 라우터를 모두 건너뛰고 에러 핸들러로 직행합니다!
next(new Error('Missing Param'));
});
// 3. 정상 동작하는 최종 라우터
app.get('/normal', (req, res) => {
console.log(`[최종 라우터: app.get("/normal")] 미들웨어가 넘긴 값: ${req.user}`);
res.send(`정상 응답 완료! (유저: ${req.user})`);
});
// 4. 에러 전용 핸들링 미들웨어 (반드시 매개변수가 4개여야 함)
// 위치: 보통 모든 라우터 선언이 끝난 app.js 맨 마지막에 위치합니다.
app.use((err, req, res, next) => {
console.error(`\n[에러 전용 미들웨어: (err, req, res, next)]`);
console.error(`> 잡힌 에러: ${err.message}`);
console.error(`🚨 클라이언트로 500 오류 반환. 서버 다운 방지 성공!`);
res.status(500).send('서버 내부 오류가 발생했습니다.');
});
app.listen(3000, () => console.log('서버가 3000번 포트에서 대기 중입니다...'));
$ node middleware.js
서버가 3000번 포트에서 대기 중입니다...
--- 1. 정상 요청 테스트 (GET /normal) ---
[미들웨어 A: Data Injector] req.user 주입 완료 -> next()
[최종 라우터: app.get("/normal")] 미들웨어가 넘긴 값: Minstudio Admin
--- 2. 에러 발생 테스트 (GET /error) ---
[미들웨어 A: Data Injector] req.user 주입 완료 -> next()
[미들웨어 B: Validator] 필수 파라미터 누락 확인! -> next(err) 호출
[에러 전용 미들웨어: (err, req, res, next)]
> 잡힌 에러: Missing Param
🚨 클라이언트로 500 오류 반환. 서버 다운 방지 성공!