
RBAC(Role-Based Access Control)은 시스템의 권한 관리 방식 중 하나로, 사용자가 어떤 "역할(Role)"을 가지느냐에 따라 접근 권한을 부여하는 방식입니다.
사용자는 여러 역할을 가질 수 있고, 역할은 여러 권한(Permissions)을 포함할 수 있습니다.
이를 통해, 권한 관리를 일괄적으로 처리하고, 권한 설정의 복잡성을 줄일 수 있습니다.
1. 사용자(User): 시스템을 사용하는 주체입니다.
2. 역할(Role): 사용자가 맡은 직무나 위치를 나타냅니다.
예: admin, user, editor.
3. 권한(Permission): 특정 자원에 대해 허용된 작업을 나타냅니다.
예: read, write, delete.
4. 자원(Resource): 사용자가 접근하려는 대상입니다.
예: 파일, 데이터베이스 레코드 등.
Nest.js에서는 RBAC를 사용하여 인증 및 권한을 쉽게 처리할 수 있습니다.
Guards, Decorators와 같은 Nest.js의 다양한 기능을 활용하여
역할 기반 접근 제어를 구현할 수 있습니다.
다음 예제는 admin 역할만 특정 API에 접근할 수 있도록 설정하는 방법을 보여줍니다.
RolesGuard를 만들어 사용자의 역할을 확인합니다.
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ROLES_KEY } from './roles.decorator';
import { Role } from './roles.enum';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
context.getHandler(),
context.getClass(),
]);
if (!requiredRoles) {
return true;
}
const { user } = context.switchToHttp().getRequest();
return requiredRoles.some((role) => user.roles?.includes(role));
}
}
역할을 설정하는 Roles 데코레이터를 정의합니다.
import { SetMetadata } from '@nestjs/common';
import { Role } from './roles.enum';
export const ROLES_KEY = 'roles';
export const Roles = (...roles: Role[]) => SetMetadata(ROLES_KEY, roles);
역할을 정의하는 enum을 생성합니다.
export enum Role {
User = 'user',
Admin = 'admin',
}
Nest.js는 기본적으로 JWT 인증을 사용할 수 있는 AuthGuard를 제공합니다.
JwtAuthGuard를 생성해 RolesGuard와 결합할 수 있습니다.
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
이제 RolesGuard와 Roles 데코레이터를 사용하여 API 엔드포인트에 역할 기반 접근을 설정합니다.
import { Controller, Get, UseGuards } from '@nestjs/common';
import { Roles } from './roles.decorator';
import { Role } from './roles.enum';
import { RolesGuard } from './roles.guard';
import { JwtAuthGuard } from './auth/jwt-auth.guard';
@Controller('admin')
@UseGuards(JwtAuthGuard, RolesGuard)
export class AdminController {
@Get()
@Roles(Role.Admin)
getAdminData() {
return 'This is admin-only data';
}
}
위의 @Roles(Role.Admin) 데코레이터를 사용한 엔드포인트는 admin 역할을 가진 사용자만 접근할 수 있습니다.
RolesGuard는 요청의 user 객체에 저장된 역할을 확인하고, 해당 엔드포인트에 접근 가능한지를 판단합니다.
JWT 토큰을 통해 사용자 정보를 전달할 때, 사용자에게 할당된 역할도 함께 포함되어야 합니다.
사용자 객체는 일반적으로 다음과 같이 생겼습니다.
{
id: 1,
username: 'john',
roles: ['admin', 'user']
}
main.ts에서 글로벌로 JwtAuthGuard나 RolesGuard를 설정할 수도 있지만,
특정 경로에만 제한을 두고 싶다면 개별적으로 적용하는 것이 좋습니다.
권한 관리의 효율성: 역할 기반 접근 제어는 사용자마다 개별 권한을 부여하는 것보다 관리가 용이합니다.
Nest.js Guard와 Decorator 활용: Nest.js의 Guard와 Decorator는 RBAC를 구현하는 데 매우 유용한 도구입니다.
확장성: 여러 역할이 복잡하게 얽힌 경우에도 Guard를 이용해 유연하게 대응할 수 있습니다.
이 코드를 바탕으로 다양한 역할을 추가하고, 더 세밀한 권한 제어를 적용할 수 있습니다.