Guards는 또 뭔데?

HanSH·2024년 1월 19일

NestJS

목록 보기
9/29

guard는 @Injectable() 데코레이터를 사용하고 CanActivate 인터페이스를 구현한다.

가드는 단 하나의 책임을 가진다.
권한이 없는 경우 어떻게 처리할 것인가?
이 책임은 특정 요청 경로와 밀접하게 연관되어있지않아 미들웨어와 가드 둘 다 할 수 있다.

미들웨어에서 해당 내용을 구현해도 상관은 없지만 Nest에서 만들어놓은 Guard를 두고 굳이?
특히 미들웨어는 next()로 무엇을 호출하는지 모른다. 스택이 있긴 하지만 실제로 어떤 미들웨어를 호출할지는 모른다. 이 불확실성 때문에 인증/인가 되기 전 게시글을 보여줄 수 있다는 내용.
하지만 가드는 ExecutionContext 인스턴스에 무엇이 실행될지 정확히 할 수 있다. 따라서 정확한 지점에 처리 로직을 삽입할 수 있다.

처리 로직은 아래와 같다.

Guard는 미들웨어와 Interceptor/Pipe 사이에서 동작한다.
즉 모든 미들웨어가 동작을 하고 난 후 Guard가 동작한다.
이를 인증/인가로 하면
1. 미들웨어에서 토큰이 있는지 확인
2. 토큰이 있으면 Guard로 넘어와서 인증/인가 처리

Auhtorization - 권한 부여

사용자가 충분한 권한이 있는 경우에 특정 경로를 사용할 수 있게 해야한다(e.g. 마이페이지).
이를 구현한 AuthGuard를 간단히 살펴보도록 하자. 여기서는 헤더의 토큰을 추출하고 토큰 유효성 검사, 인가를 결정한다.

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
      ...
    return validateRequest(request); // true/false 
  }
}

모든 가드는 canActivate() 함수를 구현해야하고, Nest는 반환값을 통해 제어한다.

  • true 반환: request 실행
  • false 반환: request 거부

Guard 사용법

  1. Router/Controller - @UseGuards() 데코레이터 사용
    이때 new를 써서 인스턴스를 직접 생성하든, 클래스 이름을 넘겨 Nest에 만들어줘 테엥 하든 상관 없다.

  2. 글로벌 - app.useGlobalGuards(new RolesGuard());
    여기서도 역시 종속성 문제가 있다. 아래로 종속성을 주입할 수 있다.

@Module({
  providers: [
    {
      provide: APP_GUARD,
      useClass: RolesGuard,
    },
  ],
})
export class AppModule {}
profile
저는 말하는 싹 난 감자입니다

0개의 댓글