안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.
사용자 인증 정보 확인 후 다음 미들웨어에게 해당 정보 넘겨주기
API에서 사용자 정보를 확인하고 정보가 없다면 오류를 던져주는 식으로 구현을 했었지만 코드가 중복되어 이를 미들웨어로 분리시켰습니다.
해당 미들웨어에서는 사용자 정보 확인 → 정보가 없다면 상황에 따라 null | Error / 정보가 있다면 userId를 넘겨줍니다.
Auth.ts - getUserFromToken
/**
* jwt 토큰 검증
*/
const getUserFromToken = async (req: Request) => {
const token = req.headers.authorization;
if (!token) {
return null;
}
return jwt.verify(token.replace(/^Bearer\s/i, ""), process.env.JWT_SECRET_KEY!, {
ignoreExpiration: true,
}) as JwtPayload;
};
AuthCheck.ts
import { NextFunction, Request, Response } from "express";
import User from "../models/User";
import { getUserFromToken } from "../utils/Auth";
/**
* 로그인이 반드시 필요한 기능을 사용할 때
* loginUser가 존재하는지 확인하는 미들웨어
*/
const loginUserChecker = async (req: Request, _: Response, next: NextFunction) => {
const user = await getUserFromToken(req);
if (!user || !user.id) {
throw new Error("Not Found LoginUser");
}
req.userId = user.id;
next();
};
/**
* 로그인이 필요하지 않은 기능을 사용할 때
* loginUser 혹은 anonymousUser가 존재하는지 확인하는 미들웨어
*/
const anonOrLoginUserChecker = async (req: Request, _: Response, next: NextFunction) => {
const user = await getUserFromToken(req);
if (user) {
req.userId = user.id;
return next();
}
// 비로그인 사용자일 때 QueryString | body에서 넘어오는 user_id 체크 -> 둘 다 없다면 undefined
let requestedUserId = req.query.user_id ?? req.body.user_id;
if (requestedUserId) {
const anonymousUser = await User.findOne({ where: { email: requestedUserId } });
if (anonymousUser) {
req.userId = anonymousUser?.dataValues.id;
return next();
}
}
req.userId = req.userId ?? null;
next();
};
export { loginUserChecker, anonOrLoginUserChecker };
로그인이 반드시 필요한 기능은 token이 존재하지 않다면, Error
로그인이 반드시 필요하진 않은 기능은 token이 존재하지 않는다면, Querystring에서 넘어오는 user_id를 체크해주고 이를 넘겨주거나 null를 넘겨줍니다.
(비로그인 사용자는 GUID 형태로 query에 붙여 보내줌)
이 때, 해당 userId를 API에서도 사용할 수 있어야 하기 때문에 Request 객체에 담아준 후 다음 미들웨어를 호출해주었습니다.
여기서 Request 객체에 userId 이라는 속성은 존재하지 않으니 오류가 발생하게 됩니다.
(Property 'userId' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'.)
따라서 해당 객체에 userId라는 속성을 부여해주어야 합니다.
src/@types/express.d.ts
declare namespace Express {
export interface Request {
userId?: number | null;
}
}
여기까지만 하면 컴파일 시 동일한 오류가 또 발생하게 됩니다.
여기서 굉장히 헤맸는데..^^ 아래 게시글들을 보고 해결!
https://velog.io/@sinf/error-TS2339-Property-user-does-not-exist-on-type-Reqeust
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/46861
간력하게 요약해보자면,
현재 프로젝트에서는 ts-node-dev 라이브러리(ts-node와 node-dev를 합친 라이브러리)를 사용하고 있는데,
ts-node는 기본적으로 includes, excludes, files를 로드하지 않아 실행 시 --files 옵션을 통해서 포함시켜줘야 한다고 합니다.
따라서 아래와 같이 해결!
tsconfig.json
{
"compilerOptions": {
...
"typeRoots": ["src/@types/*", "node_modules/@types"]
}
}
typeRoots가 없어도 잘 실행되긴 하지만, 혹시 몰라서 정의해놨습니다.
package.json
"scripts": {
"dev": "ts-node-dev --respawn --files ./src/app.ts",
},
'JavaScript > Node.js' 카테고리의 다른 글
Node) 노드버드 SNS 만들기 - 게시글, 이미지 업로드 하기 (0) | 2023.07.31 |
---|---|
Node) Sequelize Migration (0) | 2023.07.28 |
Node) 부모 라우터의 req.params를 자식 라우터에게 넘기기 - 중첩라우터 (0) | 2023.02.02 |
Node) React + Node로 infinity scroll 페이징 처리 (observer) (0) | 2023.01.25 |
Node) express-validator로 유효성 검사하기 (0) | 2023.01.17 |