| 구분 | 인증 (Authentication) | 인가 (Authorization) |
|---|---|---|
| 질문 | "당신은 누구입니까?" (Who are you?) | "당신은 무엇을 할 수 있습니까?" (What can you do?) |
| 목적 | 사용자의 신원을 확인하는 과정 (로그인) | 신원이 확인된 사용자가 특정 리소스에 접근할 권한이 있는지 확인하는 과정 |
| 결과 | 인증 성공 또는 실패 | 접근 허용 또는 거부 (e.g., 403 Forbidden) |
| 예시 | 아이디/비밀번호로 로그인 | 관리자(Admin)만 사용자 삭제 가능 |
User 엔티티에 role 필드 추가User 엔티티에 추가합니다. 역할은 문자열로 관리할 수도 있지만, Enum(열거형)을 사용하면 타입의 안정성과 코드의 가독성을 높일 수 있습니다.// user.entity.ts
export enum UserRole {
CLIENT = 'Client',
OWNER = 'Owner',
ADMIN = 'Admin',
}
@Entity()
export class User {
// ...
@Column({ type: 'enum', enum: UserRole, default: UserRole.CLIENT })
@Field(() => UserRole)
role: UserRole;
}
@AuthUser, @Role)@AuthUser 데코레이터:
AuthGuard를 통해 요청 객체에 담긴 현재 로그인된 사용자 정보를 쉽게 가져올 수 있도록 돕는 파라미터 데코레이터입니다.req.user와 같은 코드를 직접 사용하는 대신, @AuthUser() user: User와 같이 깔끔하게 사용할 수 있습니다.@Role 데코레이터:
SetMetadata: NestJS가 제공하는 기능으로, 클래스나 메서드에 키-값 형태의 메타데이터를 첨부할 수 있게 해줍니다. @Role 데코레이터는 이 SetMetadata를 사용하여 "이 메서드는 'Admin' 역할이 필요해"라는 정보를 붙여줍니다.// role.decorator.ts
import { SetMetadata } from '@nestjs/common';
import { UserRole } from 'src/users/entities/user.entity';
export const ROLES_KEY = 'roles';
export const Role = (roles: UserRole[]) => SetMetadata(ROLES_KEY, roles);
// 컨트롤러에 적용
@Get()
@Role([UserRole.ADMIN]) // 이 엔드포인트는 ADMIN 역할만 접근 가능
findAll() { ... }
RolesGuard: 역할 기반의 접근 제어RolesGuard는 @Role 데코레이터로 설정된 메타데이터와, 현재 로그인한 사용자의 실제 역할을 비교하여 접근을 허용하거나 차단하는 커스텀 가드(Guard)입니다.RolesGuard의 동작 흐름AuthGuard('jwt')가 먼저 실행: 먼저 JWT가 유효한지, 사용자가 로그인 상태인지를 확인합니다.RolesGuard 실행: AuthGuard를 통과하면 RolesGuard가 실행됩니다.Reflector): Reflector 서비스를 사용하여, 현재 실행될 컨트롤러 메서드에 @Role 데코레이터로 설정된 필요한 역할(메타데이터)을 가져옵니다.true를 반환합니다.req.user)에서 현재 로그인한 사용자의 실제 역할을 가져옵니다.true를 반환하여 요청을 통과시킵니다.false를 반환하여 403 Forbidden 에러를 발생시킵니다.AuthGuard와 RolesGuard를 app.module.ts에서 전역 가드로 등록하면, 모든 컨트롤러와 모든 메서드에 대해 이 가드들이 기본적으로 적용됩니다.
이를 통해, @Role 데코레이터가 없는 엔드포인트는 로그인만 하면 누구나 접근 가능하고, @Role 데코레이터가 있는 엔드포인트는 해당 역할을 가진 사용자만 접근할 수 있는 일관된 인가 정책을 쉽게 구축할 수 있습니다.
// app.module.ts
@Module({
providers: [
{ provide: APP_GUARD, useClass: AuthGuard('jwt') }, // AuthGuard를 전역으로
{ provide: APP_GUARD, useClass: RolesGuard }, // RolesGuard를 전역으로
],
})
@Role과 같은 커스텀 데코레이터와 SetMetadata를 사용하여, 특정 API에 필요한 역할(권한)을 메타데이터로 선언적으로 명시합니다.RolesGuard라는 커스텀 가드는 이 메타데이터와 실제 사용자의 역할을 비교하여, 접근을 허용하거나 차단하는 실질적인 인가 로직을 수행합니다.