๐ŸŒณ ๊ณ ๊ธ‰ํ”„๋กœ์ ํŠธ: middleWare(1)

yeonjeongยท2025๋…„ 6์›” 20์ผ

์ด๋ฒˆ์— ์ง„ํ–‰ํ•˜๋Š” ๊ณ ๊ธ‰ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋กœ๊ทธ์ธํ•œ ์œ ์ € ๋ฟ ์•„๋‹ˆ๋ผ ๋กœ๊ทธ์ธํ•˜์ง€ ์•Š์€ ์œ ์ €๋„ ์ ‘์†ํ•˜์—ฌ ๋‚ด์šฉ์„ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์ด ๋ช‡ ์žˆ๋‹ค.

  • ๋กœ๊ทธ์ธ ์‹œ์—๋Š” ํ•ด๋‹น ์œ ์ €์— ๋งž์ถคํ˜•์œผ๋กœ ๋ณ€ํ™˜
  • ๋กœ๊ทธ์ธ์„ ์•ˆํ•  ๊ฒฝ์šฐ ์ผ๋ฐ˜ ํŽ˜์ด์ง€ ๋ณด์—ฌ์คŒ

๊ทธ๋Ÿฌ๋ฉด ๋กœ๊ทธ์ธ์„ ํ•  ๋•Œ๋Š” header์— ์žˆ๋Š” ํ† ํฐ์„ ํ™•์ธ -> ๋กœ๊ทธ์ธ id ์ถ”์ถœ -> ์‚ฌ์šฉ์ž ์ •๋ณด ๋ฐ˜์˜๊ณผ ๊ฐ™์€ ๋กœ์ง์œผ๋กœ ๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋กœ๊ทธ์ธ ํ•˜์ง€ ์•Š์€ ์œ ์ €๊ฐ€ ์ ‘์†ํ–ˆ์„ ๋•Œ๋Š” ํ† ํฐ์ด ์—†๊ธฐ์— ํ† ํฐ์„ ํ™•์ธํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด๋ฅผ ํ†ต๊ณผ ํ•  ์ˆ˜ ์—†๋‹ค. UnauthError๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ์— ๋กœ๊ทธ์ธ์„ ์ง„ํ–‰ํ•˜์—ฌ ํ† ํฐ์ด ์žˆ๋‹ค๋ฉด ํ† ํฐ์„ ํ™•์ธํ•˜์—ฌ ์œ ์ € ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก, ํ† ํฐ์ด ์—†๋‹ค๋ฉด ์ผ๋ฐ˜ ํŽ˜์ด์ง€๊ฐ€ ๋ณด์ด๋„๋ก optional์ด ํ•„์š”ํ•˜์˜€๋‹ค.

์›๋ž˜ ๋กœ๊ทธ์ธํ•œ ์œ ์ €๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ํŽ˜์ด์ง€์—์„œ๋Š”

const extractToken = (req: Request): string | null => {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return null;
  }
  return authHeader.split(" ")[1];
};

export const authMiddleware = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  try {
    const token = extractToken(req);
    if (!token) {
      throw new UnauthError();
    }

    const { id } = verifyAccessToken(token);
    const user = await userService.getById(id);
    if (!user) {
      throw new UnauthError();
    }

    req.user = user;
    next();
  } catch {
    next(new UnauthError());
  }
};

์ด์™€ ๊ฐ™์ด ํ† ํฐ ์ •๋ณด๊ฐ€ ์—†๋‹ค๋ฉด "๋‹น์‹ ์€ ์ด ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ ์ƒํƒœ๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”" ์˜ ์˜๋ฏธ์˜ error๋ฅผ ๋ฑ‰์œผ๋ฉฐ status = 401์ด ๋˜์–ด์•ผ ํ•œ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์ด์ œ ์ด๊ฒƒ์„ ๋กœ๊ทธ์ธํ•˜์ง€ ์•Š์€ ์œ ์ € ๋˜ํ•œ๋„ ์ ‘๊ทผํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

export const optionalAuthMiddleware = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  try {
    const token = extractToken(req);
    if (!token) {
      return next();
    }
    const { userId } = verifyAccessToken(token);
    const user = await userService.getById(userId);
    if (user) {
      req.user = user;
    }
  } catch {
  } finally {
    next();
  }
};

์œ„์™€ ๊ฐ™์ด ํ† ํฐ์ด ์—†์„ ๊ฒฝ์šฐ์—๋Š” ์ด ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๊ทธ๋ƒฅ ํ†ต๊ณผํ•˜๋„๋ก next()๋กœ ๋‹ค๋ฅธ ๋กœ์ง์œผ๋กœ ๋„˜๊ฒจ์ฃผ๋ฉด ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ์œ„์˜ ์ฝ”๋“œ๋งŒ ๋ณด์•˜์„ ๋•Œ ๋งฅ๋ฝ์€ ๋งž์ง€๋งŒ ํ‹€๋ฆฐ ๋ถ€๋ถ„์ด ์žˆ์—ˆ๋‹ค.

1. ์œ ์ € ์ •๋ณด ์ฐพ์„์‹œ, next() ๋ˆ„๋ฝ

๋งŒ์•ฝ์— ๋กœ๊ทธ์ธ์„ ํ•œ ์œ ์ €์ธ ๊ฒฝ์šฐ,

    const user = await userService.getById(userId);
    if (user) {
      req.user = user;
    }

์œ ์ €์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™”์ง€๋งŒ, ๋ฏธ๋“ค์›จ์–ด์—์„œ ๊ฐ€์ ธ์˜จ ์ •๋ณด์ด๊ธฐ์— ๋‹ค์Œ ๋กœ์ง์œผ๋กœ ๋„˜๊ฒจ์ค˜์•ผ ํ•˜๋Š”๋ฐ next()๊ฐ€ ๋ˆ„๋ฝ๋˜์–ด ๋„˜๊ฒจ์ฃผ์ง€ ๋ชปํ•˜๊ณ  ๋ฏธ๋“ค์›จ์–ด์— ๋‚จ์•„์žˆ๋Š”๋‹ค.

2. error ๋ฏธ์ฒ˜๋ฆฌ

ํ•ด๋‹น ๋ฏธ๋“ค์›จ์–ด์—์„œ๋Š” try-catch๋ฌธ์„ ํ†ตํ•ด์„œ ์—๋Ÿฌ๊ฐ€ ์ƒ๊ธฐ๋ฉด ์žก์•„์„œ ์ „์—ญ error ํ•จ์ˆ˜๋กœ ๋„˜๊ฒจ์ฃผ๋„๋ก ์„ค๊ณ„ํ•˜์˜€๋‹ค.

  } catch {
  } finally {
    next();
  }
};

ํ•˜์ง€๋งŒ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ๋ณด๋‹ˆ ์ •์ž‘ error๋ฅผ ์žก์•„์ค˜์•ผ ํ•˜๋Š” catch์—๋Š” next๊ฐ€ ์—†์–ด์„œ error๋ฅผ ๋„˜๊ฒจ์ฃผ์ง€ ๋ชปํ•˜๊ณ  ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด

1) verifyAccessToken์—์„œ ํ† ํฐ์ด ์žˆ์ง€๋งŒ ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
2) ํ† ํฐ์€ ์œ ํšจํ•˜์ง€๋งŒ userId๋ฅผ ํ†ตํ•ด์„œ ์œ ์ €๋ฅผ ์ฐพ์œผ๋ ค๊ณ  ํ• ๋•Œ ํ•ด๋‹น ์œ ์ €๊ฐ€ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์—†๋Š” ๊ฒฝ์šฐ

์œ„์™€ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ๋Š” ์—์–ด๊ฐ€ ์ž‡์Œ์—๋„ ์ด๋ฅผ ๋ฌด์‹œํ•ด๋ฒ„๋ฆฌ๊ฒŒ ๋œ๋‹ค.
๋‹ค์Œ ์„œ๋น„์Šค์—์„œ๋Š” ์ค‘๋ณต ์—๋Ÿฌ ์ฝ”๋“œ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋งŒ์•ฝ์— ์—๋Ÿฌ๋ฅผ ์žก๋Š” ์กฐ๊ฑด๋ฌธ์„ ๋„ฃ์ง€ ์•Š์•˜๋‹ค๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ์ •ํ™•ํ•œ ์›์ธ ๋ฐ ์œ„์น˜๋ฅผ ํ™•์ธํ•˜๊ธฐ ํž˜๋“ค ๊ฒƒ์ด๋‹ค.

3. finally next() ์ค‘๋ณต ํ˜ธ์ถœ

    if (!token) {
      return next();
    }

ํ† ํฐ์ด ์—†์„ ๋•Œ๋Š” ์›๋ž˜ ํ•ด๋‹น ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ข…๋ฃŒํ•˜๊ณ , ๋‹ค์Œ ์„œ๋น„์Šค ๋กœ์ง์œผ๋กœ ๋„˜์–ด๊ฐ€๋Š” ๊ฒƒ์ด ์ด ๋ฏธ๋“ค์›จ์–ด์˜ ํŠน์ง•์ด๊ธฐ์— ์—ฌ๊ธฐ์„œ์˜ next() ๋ฌด์กฐ๊ฑด ์œ„์น˜๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ,

  } catch {
  } finally {
    next();
  }
};

try ๋ธ”๋ก ๋‚ด๋ถ€๊ฐ€ ์•„๋‹Œ ๋์ธ finally์—์„œ next๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?
try ๋‚ด๋ถ€์— next๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ณ  ๋งŒ์•ฝ ์—๋Ÿฌ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•ด๋„ catch ๋ฌธ ์•ˆ์—์„œ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†์–ด์„œ ์—๋Ÿฌ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๊ธฐ์— finally์—์„œ์˜ next()๋Š” ๋ฌด์กฐ๊ฑด ํ˜ธ์ถœ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

[์˜ˆ์ƒ ์‚ฌ๊ณ  ์ƒํ™ฉ]
1. ํ† ํฐ์ด ์กด์žฌํ•˜์—ฌ if(!token)์„ ํ†ต๊ณผ
2. verfyAccessToken(token)์—์„œ ์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์œผ๋กœ ์ธํ•œ ์—๋Ÿฌ ๋ฐœ์ƒ
3. catch์—์„œ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์žก์„ ์ˆ˜ ์—†์Œ
4. finally ๋ธ”๋ก์œผ๋กœ ์™€์„œ next() ํ˜ธ์ถœ
5. optionalAuthMiddleware ํ•จ์ˆ˜ ์ข…๋ฃŒ -> next() ํ˜ธ์ถœ

๋งŒ์•ฝ์— ์ด ๋ฏธ๋“ค์›จ์–ด ๋‹ค์Œ์— ๋˜ ๋‹ค๋ฅธ ๋ฏธ๋“ค์›จ์–ด๋‚˜ ๋ผ์šฐํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ next()๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋กœ์ง์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด,
next()๊ฐ€ ํ•œ ์š”์ฒญ์— ๋Œ€ํ•ด ๋‘ ๋ฒˆ ์ด์ƒ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ๋‹ค. ํ˜น์€ ๋ผ์šฐํŠธ์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์ •๋ณด๋ฅผ ๋ณด๋‚ธ๋‹ค๋ฉด res.status.send ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ error ๋ฉ”์‹œ์ง€๋ฅผ ๋งˆ์ฃผํ•  ์ˆ˜ ์žˆ๋‹ค.

Cannot set headers after they are sent to the client ์˜ค๋ฅ˜
-> ์ด๋ฏธ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ๋Š” ์‘๋‹ต์ด ์ „์†ก๋˜์—ˆ์ง€๋งŒ ๋‹ค์‹œ ์‘๋‹ต์„ ๋ณด๋‚ด๋ ค๊ณ  ์‹œ๋„ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ

์ด์™ธ์—๋„ ์š”์ฒญ ์ฒ˜๋ฆฌ ํ๋ฆ„์ด ๊ผฌ์—ฌ์„œ ์˜๋„์น˜ ์•Š์€ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์‹คํ–‰๋˜๊ฑฐ๋‚˜, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์ด ์ค‘๋ณต์œผ๋กœ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜ ์„œ๋ฒ„๊ฐ€ ๋ถˆ์•ˆ์ •ํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

finally์€ try์•ˆ์—์„œ ์‹คํ–‰์ด ๋˜๋“  catch๋กœ ์—๋Ÿฌ๋ฅผ ๋„˜๊ธฐ๋“  ์‹คํ–‰๋˜๋Š” ๋ธ”๋ก์ด๊ธฐ์— try ์•ˆ์—์„œ ํ•ด๊ฒฐ๋˜์–ด ํด๋ผ์ด์–ธํŠธ๋กœ ์‘๋‹ต์„ ๋ณด๋‚ด๊ฒŒ ๋˜๊ณ  -> next()๊ฐ€ ํ•œ ๋ฒˆ ๋” ์‹คํ–‰์ด ๋œ๋‹ค. ์ด๋Ÿด ๊ฒฝ์šฐ ์ค‘๋ณต ํ˜ธ์ถœ๋กœ ์ด๋ฏธ ์‘๋‹ต์ด ์™„๋ฃŒ๋œ ๋‹ค์Œ ๋˜ ๋‹ค์‹œ ํ—ค๋”๋ฅผ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ์‘๋‹ต์„ ๋ณด๋‚ด๋ ค๊ณ  ์‹œ๋„ํ•˜๊ฒŒ ๋œ๋‹ค.

๊ผญ ๋ฏธ๋“ค์›จ์–ด์—์„œ ์‚ฌ์šฉํ•  ์‹œ์—๋Š”,,, catch๊นŒ์ง€๋งŒ ์ž‘์„ฑ + try ์•ˆ์—์„œ return next()๋ฅผ ํ†ตํ•ด์„œ ์ดํ›„ ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ ์‹คํ–‰์„ ๋ง‰์•„์ฃผ์ž!

profile
Backend ๊ฐœ๋ฐœ์ž๋กœ ๊ฑฐ๋“ญ๋‚˜๋Š” ๊ทธ ๋‚ ๊นŒ์ง€ !

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