next(err)는 non-blocking?

신연우·2021년 3월 8일
0

JobITs 회고

목록 보기
4/7

문제 발생!

맡았던 개발을 모두 끝내고 테스트를 돌리던 중, next 함수가 원하는대로 동작을 하지 않는 현상이 발생했다.

import { verify } from "jsonwebtoken";
import { Request, Response, NextFunction } from "express";
import config from "../config";
import { TokenRequired } from "../exception";
import logger from "../loaders/logger";

export const authMiddleware = (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  const token: string = req.headers.authorization || "";
  if (!token) {
    next(TokenRequired); // 바로 여기!
  }

  const bearer: string = token.split("Bearer ")[1];
  verify(bearer, config.secertKey, (err, decoded) => {
    if (err) {
      logger.error(`403: ${err.message}`);
      res.status(403).json({ message: "Forbidden Token" });
    }

    req["decoded"] = decoded;
    next();
  });
};

저 부분에서 next(TokenRequired)가 호출되면, 에러 핸들러 미들웨어로 넘어감과 동시에 밑에 있는 const bearer: strng ... 쪽 코드도 같이 실행이 된다.

그래서 만약 403 에러가 발생되는 현상이 일어난다면 TokenRequired 에러로 반환되기 전에 403 에러로 반환되는 현상이 일어난다.

이러면 프론트엔드에서 처리하는데 문제가 생길 수 있기 때문에 빠르게 수정을 했어야 했다.

일단 수정!

return next(TokenRequired);

다음과 같이 return 문을 추가하는 것으로 함수 제어권을 바로 반환하여 밑에 코드가 실행되지 않도록 했지만, 왜 그런지를 생각해보기로 했다.

참고로, throw를 사용해도 현상을 해결할 수 있다.

찾아보기!

나와 비슷한 현상에 대한 질문을 찾았다. 이 글을 읽어보면서 내가 해결한 방법을 제안해주는 것도 확인했다.

그런데, 가장 처음으로 나온 답변을 보면 프로퍼티를 검사할 거라면 한 프로퍼티당 하나의 미들웨어가 필요하다는 말이었다.

나는, req.headers.authorization 프로퍼티를 검사함과 동시에 토큰 인증까지 하나의 미들웨어에서 하기 때문에 해당 현상이 발생하는 것이라는 뜻이었다.

확실히, 이 말을 듣고 보니 항상 미들웨어의 next는 코드의 끝에 등장한다. if 문의 끝이나 else 문의 끝에 등장하기 때문에 해당 코드가 실행되어도 뒤에 더 실행될 코드가 없기 때문에 해당 현상이 발생할 이유가 없었다.

이 글을 읽어보니 throw는 동기적으로 동작한다는 말을 보았다. 그래서 throw로도 해당 현상을 해결할 수 있었던 것 같다.

즉, 이런 현상이 일어나지 않도록 애초에 미들웨어를 잘게 쪼개는 것이 가장 좋은 코드인 것 같다.

profile
남들과 함께하기 위해서는 혼자 나아갈 수 있는 힘이 있어야 한다.

0개의 댓글