<aside> 💡 목차
</aside>
서비스 중 동일한 요청에 로그인 여부에 따른 분기처리를 하고 싶어요.
ex) 모임 리스트 반환 API → 로그인한 사용자에게는 내가 속한 모임을 추가적으로 제공
@UseGuards()를 사용하면 비회원 접근이 불가능하고, 안붙이면 로그인 정보를 가져올 수가 없어요
NestJS의 Reflector
를 활용하여 class의 MetaData에 OptionalGuard
라는 정보를 추가하는 데코레이터를 만듭니다.
// decorator.ts
import { SetMetadata } from '@nestjs/common';
export const OPTIONAL_GUARD = 'OptionalGuard';
export const OptionalGuard = () => {
return SetMetadata(OPTIONAL_GUARD, true);
};
UseGuard의 TokenAuthGuard
의 메소드를 상속 구현(override)을 추가합니다.
이를 사용하기 위해서 생성할 때 Reflector
를 주입받도록 코드를 수정합니다.
// auth.guard.ts
@Injectable()
export class TokenAuthGuard extends AuthGuard('jwt') {
constructor(private reflector: Reflector) {
super();
}
...
}
앞서 주입받은 OptionalGuard
라는 정보를 토대로 아래와 같이 분기하여 에러 처리를 합니다.
// auth.guard.ts
export class TokenAuthGuard extends AuthGuard('jwt') {
...
handleRequest(err: any, user: any, info: any, context: ExecutionContext) {
const optional = this.reflector.getAllAndOverride<boolean>(OPTIONAL_GUARD, [
context.getHandler(),
context.getClass(),
]);
if (optional && !user) {
return null;
}
if (err || !user) {
throw err || new UnauthorizedException();
}
return user;
}
}
최종 코드
// auth.guard.ts
import { ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { OPTIONAL_GUARD } from '@src/decorator';
@Injectable()
export class TokenAuthGuard extends AuthGuard('jwt') {
constructor(private reflector: Reflector) {
super();
}
handleRequest(err: any, user: any, info: any, context: ExecutionContext) {
const optional = this.reflector.getAllAndOverride<boolean>(OPTIONAL_GUARD, [
context.getHandler(),
context.getClass(),
]);
if (optional && !user) {
return null;
}
if (err || !user) {
throw err || new UnauthorizedException();
}
return user;
}
}
UseGuards를 사용할 때 데코레이터를 함께 붙여줘요.(순서무관)
@OptionalGuard()
@UseGuards(TokenAuthGuard)
⇒ 어떻게 순서 무관하게 가능한 지, 컴파일 단계의 지식까지는 추가 학습이 필요합니다..!(아직 잘 몰라요..)
// GET /groups
@OptionalGuard()
@UseGuards(TokenAuthGuard)
@Get()
async getAllGroups(@Req() { user }, @Query() findOptions, paginationOptions) {
console.log('user: ', user);
}