유저를 검증할 때

당신의 글입니까?

작성된 글을 수정하거나 삭제할 때, 현재 로그인한 유저와 글을 작성한 작성자가 동일함을 확인하고 수행해야 합니다.

2차 프로젝트를 진행하면서 글의 존재 여부와 글의 소유권에 대한 검증 부분을 어디에서 처리할 지 고민하게 되었습니다.

1차 프로젝트

1차 프로젝트의 경우 서비스 계층에서 글에 대한 정보를 불러와 글의 작성자와 로그인한 유저를 비교하는 로직을 작성했습니다.

// services/posts.ts
try {
  const post = await Post.findById(postId);
  if (post.author.toString() !== authorId.toString()) {
    throw new Error("권한이 없습니다.");
  }
} catch (error) {
  throw new Error("존재하지 않는 글입니다.");
}

2차 프로젝트를 진행하면서 1차와 다르게 DB에 접근하는 부분을 서비스 계층에서 처리하지 않고, 모델 계층에서 처리하도록 서비스와 모델을 분리하게 되었습니다.

검증에 대한 부분을 구현하게 되면서,
꼭 모델 계층에 접근해서 유저를 검증해야 할까?
라는 고민을 하게 되었습니다.

가지 않아도 되는 길

지금 가는 길이 끊긴 길이라면 빠르게 되돌아가거나 다른 길로 가야합니다. 막다른 길에 대한 표시는 입구에서 표시하게 됩니다.

글이 존재하지 않거나, 권한이 없는 접근을 한다면 중간에 끊긴 길을 가는 것과 같다고 생각합니다. 가능하면 빨리 다른 길을 안내하는 것이 맞다고 생각했습니다.

미들웨어

빠르게 체크하는 방법에 대해 고민하다가 Express의 미들웨어를 생각했습니다. 해당 라우터에 접근할 때, 글의 존재 여부와 권한 여부를 체크하고 빠르게 리턴하도록 구성했습니다.

미들웨어는?

Express 앱에서 미들웨어는 요청, 응답에 대해 접근할 수 있는 함수입니다. 자세한 내용은 Express 공식 문서에서 미들웨어에 대한 설명을 통해 확인할 수 있습니다.

우리가 사용할 미들웨어

클라이언트의 요청의 URL 경로에 따라 라우터 레벨 미들웨어로 전달됩니다. 그 이전에 미들웨어를 사용해 글의 존재여부와 권한을 체크하기로 했습니다.

import { Request, Response, NextFunction } from "express";
import { Post } from "../../models/Post";

export default async (req: Request, res: Response, next: NextFunction) => {
  // 요청 객체에서 Post ID를 가져옵니다.
  const { postId } = req.params;
  // 로그인한 유저의 정보를 가져옵니다.
  const { user } = req;

  try {
    // PostID를 통해 Post 정보를 호출합니다.
    // Post가 없을 경우 에러 발생
    const post = await Post.findPostById(postId);

    // 유저 정보와 글 작성자 정보 확인
    if (post.author.id !== user.id) {
      return next(new Error("권한이 없어요..."));
    }
  } catch (error) {
    // 앞 서 에러가 발생할 경우 처리
    return next(new Error("존재하지 않는 글입니다."));
  }
  
  // 모든 로직을 통과할 경우
  return next();
};

이와 같은 미들웨어를 설치함으로써 글이 존재하지 않거나, 권한이 없는 유저에 대한 처리를 막다른 길 입구에서 처리하도록 했습니다.

꼭 좋은 방법일까?

최선의 방법인지는 잘 모르겠습니다.

최근 로직을 구현할 때 이전과 다르게 여러 방법에 대해서 구글링을 통해 조사하고 정리하고 가장 좋다고 판단되는 방법을 선택하려고 합니다.

아직은 경험이 부족하지만, 개발노트에 필기가 쌓이면 더 좋은 로직을 선택하고 구현할 수 있다고 생각합니다.

좋은 웹페이지 즐겨찾기