서버

[Node] 미들웨어

키또카또 2026. 4. 8. 17:05

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