๐Ÿ€„ MIDDLEWARE

yyยท2023๋…„ 11์›” 8์ผ
0

์žก๋™์‚ฐ์ด

๋ชฉ๋ก ๋ณด๊ธฐ
4/21

๐Ÿ‘ค ์‚ฌ์šฉ์ž ์ธ์ฆ ๋ฏธ๋“ค์›จ์–ด

ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ์ฟ ํ‚ค ๊ฒ€์ฆ. ์ฟ ํ‚ค์•ˆ์— ์„ธ์…˜์ด ๋‹ด๊ฒจ์žˆ๊ฑฐ๋‚˜ jwt๋‹ด๊ฒจ์žˆ์œผ๋ฉด ๊ทธ๊ฑธ ์ด์šฉํ•ด ์‚ฌ์šฉ์ž ์กฐํšŒ๋ฅผ ํ•˜์—ฌ ๊ฒ€์ฆํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด.

// src/middlewares/auth.middleware.js
import jwt from 'jsonwebtoken';
import { prisma } from '../utils/prisma/index.js';

export default async function (req, res, next) {
  try {
    //1. ํด๋ผ์ด์–ธํŠธ -> ์„œ๋ฒ„ : ์ฟ ํ‚ค ์ „๋‹ฌ
    const { authorization } = req.cookies;
    if (!authorization) throw new Error('ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.');

    //2. ์ฟ ํ‚ค : Bearerํ† ํฐ ํ˜•์‹์ธ์ง€ ํ™•์ธ
    const [tokenType, token] = authorization.split(' ');

    if (tokenType !== 'Bearer')
      throw new Error('ํ† ํฐ ํƒ€์ž…์ด ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.');

    //3. ์„œ๋ฒ„์—์„œ ๋ฐœ๊ธ‰ํ•œ JWT ๋งž๋Š”์ง€ ๊ฒ€์ฆ
    const decodedToken = jwt.verify(token, 'secretKey');
    const userId = decodedToken.userId;

    //4. JWT์˜ userId ์ด์šฉ -> ์‚ฌ์šฉ์ž ์กฐํšŒ
    const user = await prisma.users.findFirst({
      where: { userId: Number(userId) },
    });
    if (!user) {
      //๋น„์ •์ƒ์ ์ด๋‹ˆ๊นŒ ์ฟ ํ‚ค ์ธ์ฆ์— ์‹คํŒจํ•˜๋ฉด ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ์˜ ์ฟ ํ‚ค๋ฅผ ์‚ญ์ œํ•ด์ค˜์•ผํ•จ.
      res.clearCookie('authorization');
      throw new Error('ํ† ํฐ ์‚ฌ์šฉ์ž๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.');
    }

    //5. req.user์— ์‚ฌ์šฉ์ž ์ •๋ณด ํ• ๋‹น
    req.user = user;

    //6. ๋ฏธ๋“ค์›จ์–ด ์‹คํ–‰
    next();
  } catch (error) {
    //์ฟ ํ‚ค ์ธ์ฆ์— ์‹คํŒจํ•˜๋ฉด ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ์˜ ์ฟ ํ‚ค๋ฅผ ์‚ญ์ œํ•ด์ค˜์•ผํ•จ.
    res.clearCookie('authorization');

    // ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ๊ฑฐ๋‚˜, ์กฐ์ž‘๋˜์—ˆ์„ ๋•Œ, ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋‹ค๋ฅด๊ฒŒ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
    switch (error.name) {
      case 'TokenExpiredError':
        return res.status(401).json({ message: 'ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.' });
      case 'JsonWebTokenError':
        return res.status(401).json({ message: 'ํ† ํฐ์ด ์กฐ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค.' });
      default:
        return res
          .status(401)
          .json({ message: error.message ?? '๋น„์ •์ƒ์ ์ธ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.' });
    }
  }
}




๐Ÿ“ƒ ๋กœ๊ทธ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด

ํด๋ผ์ด์–ธํŠธ์˜ ๋ชจ๋“  ์š”์ฒญ ์‚ฌํ•ญ์„ ๊ธฐ๋ก -> ์„œ๋ฒ„์˜ ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง ํ•˜๊ธฐ ์œ„ํ•œ ๋ฏธ๋“ค์›จ์–ด.
๋‹ค์–‘ํ•œ ๋กœ๊ทธ๋ ˆ๋ฒจ์„ ์ด์šฉํ•˜์—ฌ ํŠน์ • ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ถœ๋ ฅํ•˜๋Š” ๋ ˆ๋ฒจ์„ ๋‹ค๋ฅด๊ฒŒ ๊ตฌํ˜„ ๊ฐ€๋Šฅ.

5๋‹จ๊ณ„ : silly
4๋‹จ๊ณ„ : debug
3๋‹จ๊ณ„ : verbose
2๋‹จ๊ณ„ : info
1๋‹จ๊ณ„ : warn
0๋‹จ๊ณ„ : error

๋‹จ๊ณ„๋ณ„๋กœ ์ž์‹ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ทธ ์•„๋ž˜์˜ ๋กœ๊ทธ๊นŒ์ง€ ํ‘œํ˜„ํ•œ๋‹ค. (์˜ˆ์‹œ: info๋‹จ๊ณ„๋ฅผ ์„ค์ •ํ•œ๋‹ค๊ณ  info๋งŒ ๋‚˜์˜ค๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ info, warn, error๊นŒ์ง€ ๋กœ๊ทธ ํ‘œํ˜„์ด ๊ฐ€๋Šฅํ•จ)

winston ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด์šฉ.

โ—โ—app.use ์ค‘ ๊ฐ€์žฅ ์ฒ˜์Œ์— ๋กœ๊ทธ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๋„ฃ์–ด์ค˜์•ผํ•œ๋‹ค.โ—โ—

# yarn์„ ์ด์šฉํ•ด winston์„ ์„ค์น˜
yarn add winston
// ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ํ„ฐ๋ฏธ๋„์— ๊ธฐ๋กํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๋กœ๊ทธ ๋ฏธ๋“ค์›จ์–ด
// src/middlewares/log.middleware.js

import winston from 'winston';

const logger = winston.createLogger({
  level: 'info', // ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ 'info'๋กœ ์„ค์ •
  format: winston.format.json(), // ๋กœ๊ทธ ํฌ๋งท์„ JSON ํ˜•์‹์œผ๋กœ ์„ค์ •
  transports: [
    new winston.transports.Console(), // ๋กœ๊ทธ๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅ
  ],
});

export default function (req, res, next) {
  // ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์ด ์‹œ์ž‘๋œ ์‹œ๊ฐ„์„ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.
  const start = new Date().getTime();

  // ์‘๋‹ต์ด ์™„๋ฃŒ๋˜๋ฉด ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.
  res.on('finish', () => {
    const duration = new Date().getTime() - start;
    logger.info(
      `Method: ${req.method}, URL: ${req.url}, Status: ${res.statusCode}, Duration: ${duration}ms`,
    );
  });

  next();
}
// src/app.js

import LogMiddleware from './middlewares/log.middleware.js';

app.use(LogMiddleware); //๋กœ๊ทธ๋ฏธ๋“ค์›จ์–ด๋Š” ๋‹ค๋ฅธ ๋ฏธ๋“ค์›จ์–ด๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋˜์–ด์•ผํ•จ.

[์ฐธ๊ณ ์ž๋ฃŒ] https://coding8.tistory.com/39 https://ivvve.github.io/2020/05/31/js/js/winston-02-logging-level/


๐Ÿฆน ์—๋Ÿฌ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด

express.js์—์„œ ๋ฐœ์ƒํ•œ ์—์–ด๋ฅผ ํ†ตํ•ฉ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋ฏธ๋“ค์›จ์–ด

โ—โ—app.use ์ค‘ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ์—๋Ÿฌ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๋„ฃ์–ด์ค˜์•ผํ•œ๋‹ค. ์•ˆ๊ทธ๋Ÿผ ์—๋Ÿฌ๊ฐ€ ์ค‘๊ฐ„์— ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œโ—โ—

// src/middlewares/error-handling.middleware.js

export default function (err, req, res, next) {
  // ์—๋Ÿฌ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
  console.error(err);

  // ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  res.status(500).json({ errorMessage: '์„œ๋ฒ„ ๋‚ด๋ถ€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.' });
}
//API ํŒŒ์ผ ๋‚ด try catch๋ฌธ ์ค‘ err๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด next(err)๋กœ ๋„˜๊ฒจ์ค€๋‹ค.
} catch (err) {
    next(err);
  }
});
// src/app.js

import ErrorHandlingMiddleware from './middlewares/error-handling.middleware.js';

app.use(LogMiddleware);
app.use(express.json());
app.use(cookieParser());
app.use('/api', [UsersRouter]);
app.use(ErrorHandlingMiddleware); //์—๋Ÿฌ๋ฏธ๋“ค์›จ์–ด๋Š” ๋งจ ๋งˆ์ง€๋ง‰์— ์œ„์น˜ํ•ด์•ผํ•จ!
profile
์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ๋ฟ ๋‚ด๊ฐ€ ๋ชปํ•  ๊ฑด ์—†๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€