Web

Trello - member 테이블을 통하는 인증, 인가

필립 2024. 7. 16. 05:06

오늘은

이번 프로젝트에서는 Board에 관한 접근 권한을 인증하기 위해 Member라는 테이블을 추가로 구성했고

유저 인증, 인가 외에 Member 인증, 인가를 구현하기로 했습니다.

 

프로젝트 ERD입니다.

기본적으로 보드, 리스트, 카드와 관련된 API 호출 → 해당 유저가 멤버에 등록 되어있는지 조회 → true일 경우 API 호출을 진행합니다.

이를 위한 인증과 인가를 구현하기 위해 몇 가지 방법을 생각했습니다.

  • Guard를 통한 구현
  • Interceptor + Guard를 통한 구현
  • Middleware + Guard를 통한 구현
  • Method를 통한 구현
  • 다른 방법들

1. Guard를 통한 구현

첫 번째로 Guard를 통한 구현을 계획했습니다.

  • URL을 통해 매 호출마다 boardId를 전달받는다.
  • JWT 인증에서 넘어온 req.user를 통해 userId를 전달받는다.
  • 해당 Id값으로 member 테이블을 조회
  • 결과 값으로 member 여부 판단

해당 로직으로 구현을 시작하려고 했으나 문제가 있었습니다.

저를 제외한 팀원들은 대부분의 API 엔드포인트에서 boardId를 사용하지 않았습니다.

# 제가 생각한 엔드포인트 
boards/:boardId/lists/:listId

# 팀원들의 엔드포인트
lists/:listId

RESTful한 API를 작성하기 위해 엔드포인트에 경로가 param이 아니더라도 body나 query를 통해 전부 입력이 되야한다고 생각했습니다. (depth가 전부 표현 되야한다고 생각)

팀원들에게 ‘listId 또한 유니크한 값이고 어느 보드에 속한지 알지 못하더라도 특정할 수 있기 때문에 굳이 boardId를 매번 입력받을 필요가 없다’ 라는 피드백을 받았고 저또한 그게 좀 더 효율적이겠다는 생각이 들었습니다.

Guard를 구현하기 위해서는 boardId를 입력받지 못했을 때 조인을 통해 boardId를 추출하는 로직이 필요해졌고, Guard 하나만으로는 인증을 구현하기 어렵겠다는 판단이 들었습니다.

2. Guard + Interceptor를 통한 구현

추가로 Interceptor를 사용해보기로 했습니다.

boardId를 가져오려면 board에게 종속되어 있는 엔티티에 Id를 전달받아 조인하여 값을 가져와야 합니다.

하지만 종속된 엔티티에 Id 값 또한 query, param 등 호출 마다 다른 방식으로 값을 전달받기 때문에 매번 다른 분기가 필요합니다.

각각 다른 분기를 처리하는 Interceptor를 만들고 값을 추출하여 Guard를 통해 통합적으로 처리하는 로직을 생각했으나, 여기서도 문제가 있었습니다.

NestJS에서 제공하는 Request LifeCycle입니다.

3번과 4번을 보면 Guard가 Interceptor의 실행보다 빠르다는 것을 알 수 있습니다.

Interceptor로 값을 추출하기 전에 Guard의 실행이 끝나기 때문에 또 다른 방법을 생각해야 했습니다.

3. Middleware + Guard를 통한 구현

실행이 더 빠른 Middleware를 통해 구현하고자 하였습니다.

Middleware를 각 분기에 맞게 동작시켜 boardId를 추출하고 Guard를 통해 멤버 검사를 할 수 있습니다.

하지만 추출한 boardId 값을 다시 req에 포함시켜주기 위해 데코레이터를 사용해야하고 그 이후에 Guard가 동작할 수 있습니다.

과정을 통합하여 인증을 진행하겠다는 목적과 멀어진 것 같아 번거롭더라도 메서드를 사용하여 진행하기로 했습니다.

4. Method를 통한 구현

메서드를 사용하여 구현했습니다. 정상 동작하지만, 해당 서비스에서 생기는 모든 경우를 대비해서 만드느라 매 호출마다

많은 실행이 일어나고 있습니다. 실제 서비스라면 좀 더 나은 방법을 찾아보고 선택해야 할 것 입니다.

4. 다른 방법들

그 외 고려해본 방법과 피드백을 받은 방법입니다.

  • AccessToken에 넣기

AccessToken에 유저 Id뿐만 아니라 해당하는 BoardId도 함께 들어가면 Jwt 인증과 동시에 멤버 인증도 함께 할 수 있지 않을까 ?

하는 생각이 들었는데, 만약 Board를 새로 만들었을 때 해당 BoardId가 AccessToken에 추가되려면 새로 AccessToken을 발급받아야 하는 문제가 생겨 보류하게 되었습니다.

  • 프론트엔드에서 받기

가장 쉽고 간단해 보이는 방법입니다. 실제 서비스에서 해당 BoardId를 프론트엔드에서 전달해준다면 처음 생각했던 Guard 하나만으로

구현 할 수 있습니다.