본문 바로가기
Express, Next.js/Express

[express] 미들웨어 적용하기- (2)

by 방배킹 2024. 3. 18.


미들웨어란?

미들웨어 함수는 요청 오브젝트(req), 응답 오브젝트 (res), 그리고 애플리케이션의 요청-응답 주기 중 그 다음의 미들웨어 함수 대한 액세스 권한을 갖는 함수입니다. 그 다음의 미들웨어 함수는 일반적으로 next라는 이름의 변수로 표시됩니다.

 

 

 

app.get('/', (req, res, next) => {
    // next()에 인수가 없다면, 바로 다음 미들웨어 함수로 넘어가게 된다. 
    next(); 
}, (req, res) => {
    // 코드 작성
});

 

위와 같이 미들웨어를 작성해도 되지만 가독성과 재사용성을 위해 따로 미들웨어 함수를 만들어서 아래와 같이 사용하였다.

app.get('/',validator ,(req, res) => {
    // 코드 작성
});

 

1. 로그를 남기는 미들웨어

// expresswork\middleware\randomIdMaker.js
const randomIdMaker = function (req, res, next) {
    // 1부터 100000000까지의 랜덤한 정수 생성
    const randomId = Math.floor(Math.random() * 100000000) + 1;
    // 요청 객체에 randomId 속성으로 추가
    req.randomId = randomId;
    next();
};

module.exports = randomIdMaker;

 

// expresswork\middleware\myLogger.js
const myLogger = function (req, res, next) {

    const now = new Date();
    const year = now.getFullYear().toString().padStart(4, '0');
    const month = (now.getMonth() + 1).toString().padStart(2, '0');
    const day = now.getDate().toString().padStart(2, '0');
    const hour = now.getHours().toString().padStart(2, '0');
    const minute = now.getMinutes().toString().padStart(2, '0');
    const second = now.getSeconds().toString().padStart(2, '0');
    const currentDateTime = `${year}-${month}-${day} ${hour}:${minute}:${second}`;

    const headers = JSON.stringify(req.headers); // 헤더를 JSON 문자열로 변환
    const body = JSON.stringify(req.body); // 바디를 JSON 문자열로 변환
    const uriParam = JSON.stringify(req.params); // URI 파라미터를 JSON 문자열로 변환
    const query = JSON.stringify(req.query); // 쿼리를 JSON 문자열로 변환

    console.log(`현재시간: ${currentDateTime}, url: ${req.method} ${req.url}, request-id: ${req.randomId}\n header:${headers}\n body:${body}\n uriParam:${uriParam}\n query:${query}`)
    next();
};

module.exports = myLogger;

 

위와 같이 myLogger.js와 randomIdMaker.js를 작성하고 module.exports를 하고 app.js에 적용해주었다.

// app.js
const randomIdMaker = require('./middleware/randomIdMaker');
const myLogger = require('./middleware/myLogger');

app.use(randomIdMaker);
app.use(myLogger);

app.use를 통해 모든 라우터에서 로그를 남길수 있도록 적용하였다.

 

myLogger에서 randomIdMaker를 사용하기 때문에 randomIdMaker를 더 위에 작성해줘야한다. (에러가 게속 발생해서 해결하는데 애를 먹었다.)

 

2. 유효한지 확인하는 미들웨어 (vaildator)

// expresswork\middleware\vaildator.js
const user = require('../data/user');

const userVaildator  = function(req,res,next){
    const {age,name} = req.body;
    if(!name || name.length<1 || name.length>10){
        return res.status(400).json({error:"유저의 이름은 1~10글자여야 합니다."});
    }
    
    if(age<0 || age>100){
        return res.status(400).json({error:"유저의 나이는 1~100 사이여야 합니다."});
    }
    next();
}
const updateUserValidator = function(req, res, next) {
    const { id } = req.params;
    const { name, age } = req.body;

    // id가 숫자가 아니거나 음수인 경우
    if (isNaN(id) || id < 0) {
        return res.status(400).json({ error: "유효하지 않은 ID입니다." });
    }

    // id가 배열의 인덱스 범위를 넘어가는 경우
    if (id >= user.length) {
        return res.status(404).json({ error: "해당 ID의 유저가 존재하지 않습니다." });
    }
    
    // 유저의 이름 유효성 검사
    if (name && (name.length < 1 || name.length > 10)) {
        return res.status(400).json({ error: "유저의 이름은 1~10 글자여야 합니다." });
    }

    // 유저의 나이 유효성 검사
    if (age !== undefined && (age < 0 || age > 100)) {
        return res.status(400).json({ error: "유저의 나이는 0~100 사이여야 합니다." });
    }

    next();
};

module.exports = {userVaildator, updateUserValidator};

 

user를 추가하고 수정하는 값에 대한 유효성을 검증하는 함수를 작성해주었다.

// app.js
const {userVaildator,updateUserValidator} = require('./middleware/vaildator');

// ...

//Create
app.post('/user',userVaildator,(req,res)=>{
    const {name,age} = req.body;
    const data = { name, age }; //const data = {"name":name,"age":age};
    user.push(data);
    console.log("추가된 데이터: ",data);
    // res.send(data); //res.send(data)를 하면 상태 코드 200이 전송된다. (디폴트값) 
    res.status(201).json(data);
});

//Update
app.put('/user/:id',updateUserValidator,(req, res) => {
    const { id } = req.params;
    const { name, age } = req.body;
    
    if (id >= 0 && id < user.length) {
        console.log("수정 전 : ", user[id]);
        if (name !== undefined) user[id].name = name;
        if (age !== undefined) user[id].age = age;
        console.log("수정 후 : ", user[id]);
        res.send("수정 완료");
    } else {
        res.status(404).send("User not found.");
    }
});

 

create와 update하는 라우터에 해당 vaildator를 적용시켜주었다.

 

처음에 user array가 app.js에 있었는데, vaildator.js에서 app.js의 user를 참조 하고 app.js가 vaildator.js를 참조 하였더니

순환 참조 문제가 발생하였다.

 

이를 해결하기 위해 user data를 /data/user.js로 따로 빼서 작성하였고, app.js와 vaildator.js에서 각각 user.js를 참조 하여 사용하였다.

 

결과

 

 

 

 

로그도 잘 남고, vaildator 미들웨어도 잘 작동한다.

댓글