낙서장이자 오답 노트이자 컨닝 페이퍼

패스트캠퍼스 환급챌린지 33일차 : 코드팩토리의 백엔드 아카데미 : 한 번에 끝내는 NestJS 패키지 - 기초부터 MSA까지 강의 후기 본문

NestJS

패스트캠퍼스 환급챌린지 33일차 : 코드팩토리의 백엔드 아카데미 : 한 번에 끝내는 NestJS 패키지 - 기초부터 MSA까지 강의 후기

NangIn 2025. 5. 3. 11:30

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.

 

강의 내용 정리   

 

Role Based Access Control 이론

 

RBAC이란?

  • RBAC = Role-Based Access Control
  • 번역: 역할 기반 인가 시스템
  • 역할(Role)에 따라 리소스에 대한 **권한(Permission)**을 부여
  • 특정 리소스의 CRUD(Create, Read, Update, Delete) 권한을 역할에 따라 제어

 

왜 필요한가?

  • 사용자의 등급/역할에 따라 접근 가능한 기능을 나눌 수 있음
  • 예:
    • 어드민(Admin): 모든 기능 접근
    • 유저(User): 본인 리소스만 접근 가능
    • 게스트(Guest): 열람만 가능

 

구현 난이도

  • RBAC는 매우 복잡하게 설계할 수 있지만, 단순하게 시작하는 것이 좋음
  • 복잡하게 설계할수록:
    • 기능 설계 난이도 급증
    • 기획자/개발자 간 커뮤니케이션 비용 증가
  • 권한 설계는 유지보수가 매우 어려워지므로 작게 시작하고 점진적으로 확장할 것

 

기본 구현 아이디어

  • 역할 분류 예시
    • enum Role {
        ADMIN = 'ADMIN',
        USER = 'USER',
        GUEST = 'GUEST',
      }
      
  • 커스텀 데코레이터로 역할 지정
    • @Roles(Role.ADMIN)
      @Roles(Role.USER)
      
  • 가드 내부에서 처리 로직
    • @Roles() 데코레이터에서 역할 정보 추출
    • 요청의 req.user.role 과 비교
    • 권한 없으면 ForbiddenException 던짐
  • 역할 지정이 없을 경우 처리
    • if (!roles) {
        return true; // 권한 검사하지 않음
      }
      
    • 프로젝트마다 디폴트 정책은 다르게 설정 가능

 

RBAC 구현하기

 

커스텀 데코레이터 생성

  • 파일: auth/decorators/rbac.decorator.ts
    • export const Rbac = createParamDecorator<Role>((role) => role);
      
  • @Rbac(Role.ADMIN) 과 같이 사용될 예정
  • 역할(Roles)을 데코레이터로 엔드포인트에 명시함

 

RbacGuard 생성

  • 파일: auth/guards/rbac.guard.ts
  • CanActivate 가드 인터페이스 구현
  • 핵심 로직
    • // 1. Reflector를 통해 @Rbac 데코레이터 메타데이터 추출
      const requiredRole = this.reflector.get<Role>(RBAC_KEY, context.getHandler());
      
      if (!requiredRole) return true; // 데코레이터 없으면 제한 없음
      
      // 2. Request 객체에서 유저의 role 추출
      const req = context.switchToHttp().getRequest();
      const user = req.user;
      
      if (!user) return false; // 로그인 안 되어 있으면 차단
      
      // 3. 권한 체크 (숫자가 작을수록 높은 권한)
      return user.role <= requiredRole;
      

 

역할 Enum 정의

  • 예시:
export enum Role {
  ADMIN = 0,
  PAID_USER = 1,
  USER = 2,
}
  • 숫자가 작을수록 높은 권한
    • 0 = 최고 권한
    • 2 = 일반 유저
  • app.module.ts에 가드 전역 등록
    • providers: [
        {
          provide: APP_GUARD,
          useClass: AuthGuard, // 인증 먼저
        },
        {
          provide: APP_GUARD,
          useClass: RbacGuard, // 인가(RBAC)는 두 번째
        },
      ];
      
    • 가드 순서 중요: 인증(토큰 확인) → 인가(권한 확인)

 

엔드포인트에 권한 적용

  • 예: 일반 유저는 영화 조회 가능, 관리자만 생성/수정/삭제 가능
@Get()
@Public()
getMovies() {}

@Post()
@Rbac(Role.ADMIN)
createMovie() {}

@Patch(':id')
@Rbac(Role.ADMIN)
updateMovie() {}

@Delete(':id')
@Rbac(Role.ADMIN)
deleteMovie() {}

학습 후기         

 

이번 RBAC 강의를 통해 NestJS에서 역할 기반 인가를 실제로 어떻게 구현할 수 있는지 깊이 있게 이해할 수 있었습니다. 인증만으로는 보안이 완성되지 않으며, 인가가 더해져야 비로소 시스템 전반의 접근 제어가 가능해진다는 점을 실습을 통해 체감했습니다. 특히 JWT에 role 값을 포함하고, 이 값을 기준으로 엔드포인트별 접근 권한을 제한하는 방식은 NestJS의 데코레이터 및 가드 시스템과 매우 잘 어울리는 설계라고 느꼈습니다.

 

RBAC 구현 시 가장 인상 깊었던 부분은 @Rbac()이라는 커스텀 데코레이터를 만들어 각 라우트 핸들러에 요구되는 역할을 명시하고, 이를 Reflector로 추출하여 가드 내부에서 req.user.role과 비교하는 구조였습니다. NestJS의 메타프로그래밍 개념이 실무와 직결되는 순간이었고, 역할이 없을 경우 인가를 건너뛰는 예외 처리 로직까지 반영하면서 유연하고 확장 가능한 인가 시스템을 직접 설계할 수 있다는 자신감을 얻었습니다.

 

또한 권한을 숫자 기반으로 정의한 점도 현실적이고 실용적인 선택이라고 느꼈습니다. 단순한 조건문 비교로 충분한 유연성을 확보할 수 있었고, 나중에 기획 변경이나 새로운 역할 추가 시에도 비교적 손쉽게 대응할 수 있을 것이라 판단됩니다.

 

전역 가드 등록 순서 또한 중요한 학습 포인트였습니다. 인증이 먼저 실행되고, 그 다음에 인가가 실행되는 순서로 구성하여 인증이 먼저 통과된 사용자만이 인가 로직을 거칠 수 있게 함으로써, 책임과 관심사의 분리가 잘 이루어진 구조였습니다. 이로 인해 가드 코드가 더 명확해지고, 유지보수 또한 쉬워진다는 장점이 있었습니다.

 

마지막으로, 퍼블릭 라우트에 잘못된 토큰이 전달될 경우 에러가 발생하지 않도록 Bearer Token 미들웨어를 개선한 방식 역시 실무적인 고민이 반영된 내용이었습니다. 토큰이 없거나 잘못되어도 미들웨어는 조용히 넘어가고, 인가 여부는 가드에서 판단하는 구조는 시스템의 견고함을 높이는 설계라고 생각합니다.

 

이 강의를 통해 RBAC의 필요성과 구조, 그리고 NestJS에서의 구현 방법을 확실히 체득할 수 있었으며, 실제 프로젝트에 도입할 수 있을 만큼 구체적인 실습 경험을 얻을 수 있었습니다. 앞으로 역할 기반의 더 복잡한 권한 시스템(RBAC + ABAC 등)으로도 확장할 수 있다는 점에서 큰 가능성을 느꼈습니다.

 

학습 인증샷       

                       

수강 인증 사진
학습 인증샷
공부 시작 시간
공부 종료 시간

https://abit.ly/lisbva