[NodeJS] Middleware

이애진·2022년 7월 14일

Node

목록 보기
2/12
post-thumbnail

대표적인 미들웨어 형태

app.사용할 상황(미들웨어를 사용할 경로, 미들웨어가 할 일)

여기서 헷갈리면 안되는 점은 다음과 같다
(req, res) => {} 이 형태는 express 전용 미들웨어 함수이며, 비동기 처리 콜백 기능과는 아무런 상관이 없다
express 내에서 웹 요청과 응답에 대한 정보를 사용해서 필요한 처리를 진행할 수 있도록 분리된 독립적인 함수이다


Application Level

next 함수를 이용해서 다음 미들웨어로 현재 요청을 넘길 수 있다

app.use((req: Request, res: Response, next: NextFunction) => {
    console.log("All Request");
    next();
});

app.get("/a", (req: Request, res: Response, next: NextFunction) => {
    res.send("a");
    console.log("a");
});

app.use(((err, req, res, next) => { // error 미들웨어는 보안상 반드시 4개를 다 써야한다
    res.status(500).send(err.message);
}) as ErrorRequestHandler);

app.use 안에 있는 모든 함수들은 모두 미들웨어이며, 요청이 들어올 때마다 이 미들웨어를 거치며 클라이언트에 응답하게 된다.

사용 예시)
사용자 인증을 먼저 거친 후에 페이지를 렌더링 하고 싶을 때 사용자 인증 미들웨어(app.use)를 작성한다

위의 코드의 동작 원리를 살펴보면

  1. 클라이언트가 http://localhost:3000/a 로 요청을 보냈을 때,
  2. app.use 를 먼저 거치고
  3. 다음 미들웨어 호출(next()) 를 지정하여
  4. res.send("a") 코드가 담긴 미들웨어로 넘어가게 된다

만약 미들웨어에서 req 객체 프로퍼티를 추가해서 넘겨주고 싶다면 아래와 같이 한다

app.use("/a", (req: Request, res: Response, next: NextFunction) => {
    req.requestTime = new Date().toString();
    next();
});

app.get("/a", (req: Request, res: Response, next: NextFunction) => {
    res.send(req.requestTime);
});

클라이언트가 a 경로에만 들어왔을 때 설정하고 싶으면 위와 같이 하면 된다
하지만 여기서 문제는 a 경로에 맵핑된 모든 상황에 맵핑이 된다
만약 GET a 상황에서만 사용하고 싶다면 아래와 같이 사용한다

app.get("/a", (req: Request, res: Response, next: NextFunction) => {
    req.requestTime = new Date().toString();
    next();
});

app.get("/a", (req: Request, res: Response, next: NextFunction) => {
    res.send(req.requestTime);
});

이럴 때는 코드를 아래와 같이 합칠 수 있다

app.get("/a", (req: Request, res: Response, next: NextFunction) => {
    req.requestTime = new Date().toString();
    next();
}, (req: Request, res: Response, next: NextFunction) => {
    res.send(req.requestTime);
});

Router Level

라우터 레벨 미들웨어의 특징은 여러가지 기능들을 router에다 저장하고 최종적으로 app에 올리는 방식이다
Router 객체는 그 자체가 미들웨어처럼 움직이므로 app.use()의 argument로 사용될 수 있고 다른 router의 use() 매서드에서 사용될 수 있다
router 인스턴스에 미들웨어가 바인딩 되는 것으로 그 외에는 애플리케이션 레벨 미들웨어와 차이가 없다

RouterLevel.ts

import express from "express";
import dotenv from "dotenv";

import pageRouter from "./routers/pages";

dotenv.config({path: __dirname + "/.env"});

const PORT: string | number = process.env.PORT || 3000;

const app = express();

app.use("/pages", pageRouter);

app.listen(PORT, () => console.log("Running on TS-Express Server\n"))
    .on("error", (err) => { throw new Error(`${err.name}: ${err.message}`) });

routers/pages.ts

import express, { Request, Response, NextFunction, ErrorRequestHandler } from "express";
import { RequestParams } from "../interfaces/request";

const router = express.Router();

router.get("/:id", (req: Request<RequestParams>, res: Response, next: NextFunction) => {
    if (req.params.id === "0") {
        next("route");
    } else {
        next();
    }
}, (req: Request<RequestParams>, res: Response, next: NextFunction) => {
    res.send("id is not 0");
});

router.get("/:id", (req: Request<RequestParams>, res: Response, next: NextFunction) => {
    let id: string = req.params.id;

    res.send(`id is ${id}`);
});

router.use(((err, req, res, next) => {
    res.status(500).send("에러 처리 미들웨어");
}) as ErrorRequestHandler);
  
export default router;

그 외

오류 처리 미들웨어

app.use(((err, req, res, next) => {
    res.status(500).send("에러 처리 미들웨어");
}) as ErrorRequestHandler);

오류 처리 함수는 4개의 인수(err, req, res, next)를 전부 써주어야한다 → 시그니처

기본 제공 미들웨어

app.use(express.static("public"));

위의 코드 예시와 같은 기본으로 제공하는 미들웨어가 있고, 추가적인 미들웨어는
GitHub - senchalabs/connect: Connect is a middleware layer for Node.js
여기에서 확인할 수 있다

써드파티 미들웨어

그냥 평소에 npm install [module name] 으로 설치하는 것들이 써드파티 미들웨어로 experess 앱에 기능을 추가해서 사용할 수 있다

profile
Frontend Developer

0개의 댓글