Express의 미들웨어란 HTTP 요청과 응답 사이에서 단계별 동작을 수행해 주는 함수이다.
미들웨어 = 중간에 있는 소프트웨어
cors > express.json > 인증 / auth > 컨트롤러
- cors : 주소 확인
- express.json : json으로 파싱
- 인증 / auth : 토큰 확인
- 컨트롤러 : db 저장, 응답
모든 미들웨어 함수는 res, req, next를 다룰 수 있다.
next()
작업이 끝난 후 다음 미들웨어로 넘겨주는 작업.
자주 쓰이는 미들웨어
morgan
pnpm i morgan
morgan은 클라이언트 요청, 서버 응답을 콘솔에 기록해 주는 미들웨어이다. (방명록을 적어 준다고 생각하면 됨)
로그를 정리해 주기 때문에 디버깅에 유용하다.
const app = express();
app.use(morgan('dev')); // 로그 포맷 설정
app.get('/test', (req, res) => {
res.send('Hello!');
});
morgan은 기록 스타일을 어떻게 남길지 포맷 설정을 할 수 있다.
- dev: 개발 시 추천
- POST /users/signup 201 4.597 ms - 150
- combined : 실제 배포 / 운영 시 추천 , 상세하게 정보를 남겨 줌. Apache 표준 로그 포맷
- ::1 - - [08/Apr/2026:15:03:32 +0900] "POST /users/signup HTTP/1.1" 201 150 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36"
- tiny/short : dev와 비슷하지만 아주 최소한의 정보만 남겨 준다.
- POST /users/signup 201 150 - 4.597 ms
cookie-parser
pnpm i cookie-parser
브라우저가 서버로 보내는 쿠키를 파싱해주는 미들웨어.
- 쿠키 : 브라우저와 웹 서버 간 정보 교환, 유지를 위해 사용하는 데이터, 쿠키는 클라이언트 측에 저장되고, KEY: VALUE 방식으로 데이터를 저장함. 사용자와 브라우저 간의 이전 상호작용을 기억하거나, 사용자별로 다른 콘텐츠를 표시하고 싶을 때 주로 사용하는 방식이다.
왜 사용해야 할까?
서버는 클라이언트를 기억하지 못한다. 따라서 쿠키로 이름표를 만들어 줘서 구별할 수 있게 하는 것!
그런데. 쿠키는 name=yoonvin; age=20; logged_in=true 처럼 긴 문자열 형태로 날라온다. 쿠키 파서를 사용하지 않는다면 서버쪽에서 이 문자열을 ; 기준으로 자르고, = 기준으로 다시 잘라서 객체로 만드는 코드를 짜야 한다는 것..
쿠키 파서는 이 역할을 대신 한다. 파싱된 객체는 req.cookies에 담긴다.
import cookieParser from "cookie-parser";
app.use(cookieParser());
app.get('/setcookie', (req, res) => { // 쿠키 생성
res.cookie('myCookie', 'hello', { maxAge: 60000 });
});
app.get('/getcookie', (req, res) => { // 쿠키 읽기
const myCookie = req.cookies.myCookie;
if (myCookie) {
console.log(req.cookies);
}
});
cookie-parser 코드는 API 경로를 선언하는 코드보다 위쪽에 위치해야 한다.
왜??
API 라우터가 클라이언트를 맞이하기 전에 이름표를 번역해 둬야 되니까..
express.json() / express.urlencoded()
- express.json() : POST 메소드를 사용하고, json 형식의 paylaod가 있는 request가 전해졌을 때, body를 파싱하는 미들웨어
- express.urlencoded(): 인코딩 된 request의 payload를 파싱해주는 미들웨어
...
프론트는 데이터를 포장해서 서버로 보낸다.
이 포장을 풀어서 개발자가 사용하기 좋은 자바스크립트 객체로 세팅해 주는 것이 두 미들웨어의 역할이다.
두 미들웨어가 index.js에 없다면, 백엔드에서 req.body를 찍어 봤을 때 undefined가 뜨게 된다.
- express.json : JSON 문자열을 자바스크립트 객체로 파싱하여 req.body.name, req.body.age 처럼 바로 꺼내서 사용할 수 있도록 만들어 준다. (HTTP header의 ContentType이 application/json일 때)
- express.urlencoded() : url 주소 뒤에 붙는 쿼리 스트링과 비슷한 형태로 포장된 데이터를 푼다. (HTTP header의 ContentType이 application/x-www-form-urlencoded일 때)
괄호 안에 옵션( extended: false /true)을 적어 주어야 한다.
false - 기본 내장된 가벼운 도구 사용, true - qs라는 외부 라이브러리 사용. 보통은 false를 많이 쓴다.
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
이 두 미들웨어는 과거에는 body-parser라는 패키지였으나, 현재는 Express에 내장되어 있으므로 별도 설치할 필요가 없다.
API 응답 구조 통일
프론트에서 API를 사용할 때 훨씬 쉽게 개발할 수 있기 위해서는 API 응답 구조 통일이 필요하다.
//성공시
{
"resultType": "SUCCESS",
"error":null,
"success":{...}
}
//실패시
{
"resultType": "FAIL",
"error":{
"errorCode":"A100",
"reason": "원인",
"data" : {...}
},
"success":null
}
전역 헬퍼 미들웨어
일관된 응답 구조를 서버 전체에 강제하고, 개발을 편하게 만들어 주는 역할을 한다.
app.use((req, res, next) => {
res.success = (success) => {
return res.json({ resultType: "SUCCESS", error: null, success });
};
res.error = ({ errorCode = "unknown", reason = null, data = null }) => {
return res.json({
resultType: "FAIL",
error: { errorCode, reason, data },
success: null,
});
};
next();
});
res.success()와 res.error()라는 새로운 맞춤형 응답 버튼을 res 객체에 달아주었다.
=> 컨트롤러 코드가 짧아진다
컨트롤러에서는 새롭게 달아 준 함수만 호출하면 된다.
// 성공 시
return res.success(userData);
// 실패 시
return res.error({ errorCode: "INVALID_INPUT", reason: "이메일 누락" });
전역 에러 처리 미들웨어
app.use((err, req, res, next) => {
if (res.headersSent) { // 이미 서버가 프론트로 응답을 보내기 시작했는데 에러가 터졌을 때
return next(err); //Express 내부 기본 에러 처리기에게 넘긴다
}
res.status(err.statusCode || 500).error({ //내가 정해둔 에러 코드를 주거나, 원인을 알 수 없는 500을 주거나
//.error() ---> 헬퍼함수. 터진 에러를 모아 res.error에 담아 프론트에 넘긴다
errorCode: err.errorCode || "unknown",
reason: err.reason || err.message || null,
data: err.data || null,
});
});
에러코드를 커스텀 하는 방법
//errors.js
export class DuplicateUserEmailError extends Error {
errorCode = "U001";
constructor(reason, data) {
super(reason);
this.reason = reason;
this.data = data;
}
}
아래와 같이 사용할 수 있다.
//src/services/user.services.js
if (joinUserId === null) {
throw new DuplicateUserEmailError("이미 존재하는 이메일입니다.", data);
}'서버' 카테고리의 다른 글
| [Node.js] ORM (0) | 2026.04.08 |
|---|---|
| [Node.js] API 만들기 (0) | 2026.04.08 |
| [Node.js] 스터디 4주차. Javascript (0) | 2026.04.01 |
| [DB] 스터디 3주차 데이터베이스 기초 (0) | 2026.03.25 |
| [Node.js] 스터디 2주. Prisma 와 Middleware (0) | 2026.03.19 |