app.사용할 상황(미들웨어를 사용할 경로, 미들웨어가 할 일)
여기서 헷갈리면 안되는 점은 다음과 같다
(req, res) => {} 이 형태는 express 전용 미들웨어 함수이며, 비동기 처리 콜백 기능과는 아무런 상관이 없다
express 내에서 웹 요청과 응답에 대한 정보를 사용해서 필요한 처리를 진행할 수 있도록 분리된 독립적인 함수이다
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)를 작성한다
위의 코드의 동작 원리를 살펴보면
http://localhost:3000/a 로 요청을 보냈을 때,app.use 를 먼저 거치고(next()) 를 지정하여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에다 저장하고 최종적으로 app에 올리는 방식이다
Router 객체는 그 자체가 미들웨어처럼 움직이므로 app.use()의 argument로 사용될 수 있고 다른 router의 use() 매서드에서 사용될 수 있다
router 인스턴스에 미들웨어가 바인딩 되는 것으로 그 외에는 애플리케이션 레벨 미들웨어와 차이가 없다
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}`) });
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 앱에 기능을 추가해서 사용할 수 있다