2023. 6. 6. 17:24ㆍ개발 문서 번역/NestJS
이 포스팅은 「NestJS 기초실무 가이드 : 강력하고 쉬운 Node.js 웹 프레임워크로 웹사이트 만들기」
(서명: NestJS 基礎必學實務指南:使用強大且易擴展的 Node.js 框架打造網頁應用程式)
책이 출간되었습니다.
Guard란 무엇인가요?
Guard란 검사 로직인데요. 회사의 보안 시스템과 같습니다. 카드를 통해 출입 통제를 관리한다고 하면
카드를 찍지 않으면 입장을 할 수 없겠지요. 이런 시스템은 주로 신원 확인에 사용됩니다.
승인되지 않은 요청이 있을 시 Guard는 해당 요청을 막아버립니다. Express의 Guard는 Middleware 레이어에 위치하여 처리하는데요. 이 처리방식이 그렇게 안좋은것만은 아닙니다. 단지 next()를통해 실행되는것이 무엇인지만 잘 명시해준다면요.
Nest는 Guard의 실행순서를 확실히 보장하고자 Guard를 따로 설계하였습니다.
아래는 Guard의 실행 순서가 그려져있습니다.
Guard는 Middleware 다음 Interceptor 전에 실행되는것을 확인할 수 있습니다.
Guard 만들기
Guard는 CLI를 통해 생성할 수 있습니다.
$ nest generate guard <GUARD_NAME>
주의: <GUARD_NAME>은 경로를 포함할 수 있습니다. ex: guards/auth
경로를 포함하여 생성시 src 폴더 안에 경로를 포함하여 Guard가 생성됩니다.
AuthGuard를 guards 폴더 아래에 생성하겠습니다.
$ nest generate guard guards/auth
src 폴더 아래에 guards라는 폴더 안에 auth.guard.ts와 auth.guard.spec.ts 파일이 생성된걸 확인할 수 있습니다.
생성된 Guard의 뼈대는 아래와 같은데요.
Guard도 @Injectable 데코레이터가 달려있는걸 확인할 수 있습니다.
그러나 Guard는 CanActivate 인터페이스를 구현해주어야 하며,
canActivate(context: ExecutionContext) 메서드도 작성해주어야 합니다.
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
return true;
}
}
canActivate(context: ExecutionContext) 는 동기와 비동기 모두 지원합니다.
반환값은 boolean, Promise<boolean>이나 Observable<boolean> 중 하나입니다.
인증을 통과하기 위해서는 반드시 최종 결과가 true가 되어야 합니다.
주의: ExecutionContext를 제공해주는 이유는 이를 통해 인증에 필요한 데이터를 가져올 수 있기 때문입니다.
Guard 사용하기
사용하기 전에 먼저 auth.guard.ts를 수정하겠습니다.
먼저 이 예제에서는 고의로 false를 반환하고 비동기식으로 처리해보겠습니다.
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable, of } from 'rxjs';
import { delay } from 'rxjs/operators';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
return of(false).pipe(delay(2000));
}
}
다음으로 TodoModule과 TodoController를 생성해보겠습니다.
$ nest generate module features/todo
$ nest generate controller features/todo
주의: 이미 생성하셨다면 이 단계는 넘어가도 무방합니다.
@UseGuards 데코레이터를 통해 쉽게 적용할 수 있습니다. 사용 방식은 2가지로 나뉩니다.
- 단일 Resource: Controller 메서드 위에 @UseGuards 데코레이터를 적용시킵니다. 해당 Resource에만 적용이 됩니다.
- Controller: Controller 위에 직접 @UseGuards 데코레이터를 적용시킵니다. 해당 Controller의 Resource가 전부 적용됩니다.
아래는 Controller의 예제입니다. todo.controller.ts를 수정해보겠습니다.
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from '../../guards/auth.guard';
@Controller('todos')
@UseGuards(AuthGuard)
export class TodoController {
@Get()
getAll() {
return [];
}
}
서버를 키고 http://127.0.0.1:3000 에 접속해보면 Guard에 의해 막힌것을 확인할 수 있습니다.
{
"statusCode": 403,
"message":"Forbidden resource",
"error":"Forbidden"
}
전역 Guard
해당 App 전체에 Guard를 적용하고자 한다면
main.ts에 useGlobalGuards를 추가해주면 적용할 수 있습니다.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { AuthGuard } from './guards/auth.guard';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalGuards(new AuthGuard());
await app.listen(3000);
}
bootstrap();
의존성 주입을 통해 전역 Guard 적용하기
위의 방법대로 모듈 외부에서 전역 설정으로 구현하여도 되지만
Provider의 token에 APP_GUARD를 설정해줌으로써 구현할 수 있습니다.
이는 useClass를 사용하여 생성해야할 인스턴스의 클래스를 지정해줍니다.
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TodoModule } from './features/todo/todo.module';
import { AuthGuard } from './guards/auth.guard';
@Module({
imports: [TodoModule],
controllers: [AppController],
providers: [
AppService,
{
provide: APP_GUARD,
useClass: AuthGuard
}
]
})
export class AppModule {}
마치며
Guard는 인증을 진행에있어 좋은 도구중 하나이며 자주 쓰이는 기능 중 하나입니다.
뒤에 포스트에서는 Guard와 관련된 것들이 등장할 예정입니다.
아래는 오늘 포스팅의 요약본입니다.
1. Guard는 Middleware의 후, Interceptor 전에 실행됩니다.
2. Guard는 Middleware보다 더 인증에 특화되어 있습니다.
3. ExecutionContext를 사용하여 인증과 관련된 정보를 얻을 수 있도록 합시다.
4. 전역 Guard는 의존성 주입을 통한 방법으로 구현할 수 있습니다.
'개발 문서 번역 > NestJS' 카테고리의 다른 글
NestJS 帶你飛! 시리즈 번역 15# Dynamic Module (0) | 2023.06.09 |
---|---|
NestJS 帶你飛! 시리즈 번역 14# Custom Decorator (0) | 2023.06.07 |
NestJS 帶你飛! 시리즈 번역 12# Interceptor (0) | 2023.06.05 |
NestJS 帶你飛! 시리즈 번역 11# Middleware (0) | 2023.06.04 |
NestJS 帶你飛! 시리즈 번역 10# Pipe (하) (0) | 2023.06.03 |