✅ Express 미들웨어의 기본 구조 패턴
형태매개변수역할호출 상황
| ① 라우트 핸들러 (2개) | (req, res) | 단순 요청 응답 | app.get, app.post 등에서 next 사용 안 할 때 |
| ② 일반 미들웨어 (3개) | (req, res, next) | 요청-응답 중간 처리, 다음으로 넘김 | app.use, app.get 등 대부분의 미들웨어 |
| ③ 에러 처리 미들웨어 (4개) | (err, req, res, next) | 에러 처리 전용 | throw, next(err) 호출 시 자동 실행 |
| ④ 특수 케이스 (1개) | (err) or (req) 등 | 커스텀 함수(Express 내부 규칙 아님) | 직접 호출하거나 외부 라이브러리 내부용 |
① (req, res) — 가장 단순한 라우트 핸들러
이건 “요청 들어오면 바로 응답하는 함수”입니다.
app.get('/', (req, res) => { res.send('Hello World'); });
- next()가 없기 때문에 이 함수에서 요청이 끝남
- 즉, res.send()로 응답하면 Express는 다음 미들웨어를 실행하지 않음
사용 예시: 일반적인 페이지 라우팅, API 응답 등
② (req, res, next) — 일반 미들웨어(가장 자주 씀)
요청이 들어오면 먼저 실행되고,
작업이 끝나면 next()로 다음 단계로 넘기는 구조예요.
app.use((req, res, next) => { console.log(`[${req.method}] ${req.url}`); next(); // 다음 미들웨어로 이동 });
특징:
- app.use()나 app.get() 등 어디서든 사용 가능
- next()를 호출하지 않으면 요청이 멈춤
- 인증, 로깅, 파싱, 공통 처리 등에 주로 사용
③ (err, req, res, next) — 에러 처리 미들웨어
이건 Express가 특별하게 인식합니다.
함수의 첫 번째 인자가 err이면 → 에러 처리 전용이라고 간주합니다.
app.use((err, req, res, next) => { console.error('에러 발생:', err.message); res.status(500).send('서버 오류 발생'); });
이 함수는 아래의 경우에 자동 호출됩니다:
- throw new Error() 한 경우
- next(err) 한 경우
예시:
app.get('/', (req, res, next) => { next(new Error('문제 발생!')); });
→ Express는 err가 전달된 걸 감지하고
→ (err, req, res, next) 구조의 미들웨어로 바로 점프합니다.
④ 기타 변형 케이스
✅ 비동기 함수(async/await)
비동기 코드에서 에러가 발생하면 try/catch로 감싸서 next(err)로 넘겨야 Express가 잡습니다.
app.get('/user', async (req, res, next) => {
try {
const user = await db.getUser();
res.json(user);
} catch (err) {
next(err); // 에러 미들웨어로 전달
}
});
✅ 여러 미들웨어를 연결할 때
하나의 라우트에 여러 개의 (req, res, next)를 순차 등록할 수 있습니다.
app.get(
'/test',
(req, res, next) => {
console.log('1단계');
next();
},
(req, res, next) => {
console.log('2단계');
next();
},
(req, res) => {
console.log('3단계');
res.send('완료');
}
);
실행 순서:
요청 → 1단계 → next() → 2단계 → next() → 3단계 → 응답
🔍 요약 비교표
미들웨어 종류함수 형태next() 필요 여부실행 시점
| 라우트 핸들러 | (req, res) | ❌ | 라우트에 도착했을 때 |
| 일반 미들웨어 | (req, res, next) | ⭕ | 요청–응답 중간 |
| 에러 처리 미들웨어 | (err, req, res, next) | 선택적 | next(err)나 throw 발생 시 |
| 비동기 미들웨어 | async (req, res, next) | ⭕ (try/catch 필요) | 비동기 처리 시 |
| 종료 미들웨어 | (req, res) | ❌ | 마지막 응답 시점 |
✅ 실전 예시로 전체 흐름
const express = require('express');
const app = express();
app.use((req, res, next) => {
console.log('1️⃣ 요청 로깅 미들웨어'); next();
});
app.get('/error', (req, res, next) => {
console.log('2️⃣ 에러 발생 지점');
next(new Error('테스트 에러'));
});
app.get('/', (req, res) => {
console.log('3️⃣ 정상 요청 처리');
res.send('Hello World');
});
app.use((err, req, res, next) => {
console.error('4️⃣ 에러 미들웨어 작동:', err.message);
res.status(500).send('에러 처리 완료');
});
app.listen(3000, () => console.log('서버 대기중...'));
요청 흐름:
/ → 1️⃣ → 3️⃣ → 응답 /error → 1️⃣ → 2️⃣(next(err)) → 4️⃣(에러 처리)
'Backend' 카테고리의 다른 글
| 크리스마스 시즌 웹사이트를 만들었는데 (0) | 2025.11.17 |
|---|---|
| 백엔드 코드 패턴 정리 (1) | 2025.10.07 |
| 자유 게시판 (0) | 2025.09.29 |