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

가드는 단 하나의 책임을 가진다.
권한이 없는 경우 어떻게 처리할 것인가?
이 책임은 특정 요청 경로와 밀접하게 연관되어있지않아 미들웨어와 가드 둘 다 할 수 있다.
미들웨어에서 해당 내용을 구현해도 상관은 없지만 Nest에서 만들어놓은 Guard를 두고 굳이?
특히 미들웨어는 next()로 무엇을 호출하는지 모른다. 스택이 있긴 하지만 실제로 어떤 미들웨어를 호출할지는 모른다. 이 불확실성 때문에 인증/인가 되기 전 게시글을 보여줄 수 있다는 내용.
하지만 가드는 ExecutionContext 인스턴스에 무엇이 실행될지 정확히 할 수 있다. 따라서 정확한 지점에 처리 로직을 삽입할 수 있다.
처리 로직은 아래와 같다.

Guard는 미들웨어와 Interceptor/Pipe 사이에서 동작한다.
즉 모든 미들웨어가 동작을 하고 난 후 Guard가 동작한다.
이를 인증/인가로 하면
1. 미들웨어에서 토큰이 있는지 확인
2. 토큰이 있으면 Guard로 넘어와서 인증/인가 처리
사용자가 충분한 권한이 있는 경우에 특정 경로를 사용할 수 있게 해야한다(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는 반환값을 통해 제어한다.
Router/Controller - @UseGuards() 데코레이터 사용
이때 new를 써서 인스턴스를 직접 생성하든, 클래스 이름을 넘겨 Nest에 만들어줘 테엥 하든 상관 없다.
글로벌 - app.useGlobalGuards(new RolesGuard());
여기서도 역시 종속성 문제가 있다. 아래로 종속성을 주입할 수 있다.
@Module({
providers: [
{
provide: APP_GUARD,
useClass: RolesGuard,
},
],
})
export class AppModule {}