맡았던 개발을 모두 끝내고 테스트를 돌리던 중, 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
로도 해당 현상을 해결할 수 있었던 것 같다.
즉, 이런 현상이 일어나지 않도록 애초에 미들웨어를 잘게 쪼개는 것이 가장 좋은 코드인 것 같다.