낙서장이자 오답 노트이자 컨닝 페이퍼

패스트캠퍼스 환급챌린지 29일차 : 코드팩토리의 백엔드 아카데미 : 한 번에 끝내는 NestJS 패키지 - 기초부터 MSA까지 강의 후기 본문

NestJS

패스트캠퍼스 환급챌린지 29일차 : 코드팩토리의 백엔드 아카데미 : 한 번에 끝내는 NestJS 패키지 - 기초부터 MSA까지 강의 후기

NangIn 2025. 4. 29. 22:43

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.

 

강의 내용 정리   

 

Jwt Strategy 적용하기

 

관련 패키지 설치

pnpm i @nestjs/jwt @nestjs/passport passport passport-jwt
pnpm i -D @types/passport-jwt
  • @nestjs/jwt: NestJS에서 JWT 사용을 위한 모듈
  • passport-jwt: JWT 기반 Passport 전략
  • @types/passport-jwt: 타입 정의

 

JWT 발급 로직 분리

  • issueToken() 함수 생성
    • 기존 로그인 로직에서 토큰 발급 코드 분리
    • 함수 시그니처:
      • async issueToken(user: User, isRefreshToken: boolean): Promise<string>
        
    • 내부 로직:
      • type: access 또는 refresh
      • secret: .env에서 설정한 값
      • expiresIn: access → 5분(300초), refresh → 24시간

 

로그인 컨트롤러 정리

@Post('login-passport')
@UseGuards(LocalAuthGuard)
async loginPassport(@Request() req) {
  return {
    accessToken: await this.authService.issueToken(req.user, false),
    refreshToken: await this.authService.issueToken(req.user, true),
  };
}
  • LocalAuthGuard로 사용자 검증
  • 검증 성공 시 request.user에서 사용자 정보 추출
  • JWT 2종 발급 후 반환

 

JWT Strategy 생성

  • jwt.strategy.ts
    • @Injectable()
      export class JwtStrategy extends PassportStrategy(Strategy) {
        constructor(private configService: ConfigService) {
          super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            ignoreExpiration: false,
            secretOrKey: configService.get('ACCESS_TOKEN_SECRET'),
          });
        }
      
        async validate(payload: any) {
          return payload; // request.user로 들어감
        }
      }
      ​
       
      • ExtractJwt.fromAuthHeaderAsBearerToken() 사용
      • secretOrKey: access 토큰 시크릿 사용
      • validate()의 반환값이 request.user에 들어감

 

JWT Auth Guard 생성

export class JwtAuthGuard extends AuthGuard('jwt') {}
  • 이름 기반 guard 사용 방지 → 안전한 타입 기반 코드 작성 가능

 

보호된 라우트 생성 및 토큰 검증

@Get('private')
@UseGuards(JwtAuthGuard)
getPrivateData(@Request() req) {
  console.log('run'); // guard 통과 시 실행
  return req.user;
}
  • JWT 토큰 필요
    • Authorization: Bearer <token>
  • 실패 시 → Unauthorized 에러 응답
  • 성공 시 → validate의 반환값이 request.user에 담김

 

학습 후기         

 

NestJS에서 JWT 기반 인증을 구축하면서 가장 인상 깊었던 점은 인증 흐름이 전략 단위로 완전히 분리된다는 점이었습니다. 기존에는 로그인 시 JWT를 직접 발급하고 검증하는 로직을 한곳에 몰아넣기 쉬웠는데, JwtStrategy를 사용하면 토큰 발급과 검증을 명확히 역할별로 나눌 수 있었습니다.

 

특히 Passport의 구조 덕분에 JWT 전략을 별도 파일로 작성하고, validate() 메서드 내부에서 토큰의 payload만 넘겨주면 request.user에 자동으로 주입된다는 점이 매우 편리했습니다. 덕분에 라우트에서는 인증된 사용자 객체를 별도 로직 없이 사용할 수 있었고, 이는 전반적인 코드의 가독성과 유지보수성을 높여주었습니다.

 

또한 access 토큰과 refresh 토큰의 발급 로직을 issueToken() 함수로 분리하여 설계하니, 토큰 발급 정책을 일관되게 관리할 수 있었습니다. 이 방식은 추후 Redis나 블랙리스트 기반의 리프레시 토큰 관리 전략으로 확장할 때도 유리하다는 생각이 들었습니다.

Guard를 통해 인증이 필요한 라우트를 보호하는 구조 역시 직관적이었습니다. @UseGuards(JwtAuthGuard) 한 줄로 해당 라우트를 보호할 수 있고, 토큰이 없거나 잘못된 경우에는 Unauthorized 에러가 자동으로 처리된다는 점에서 불필요한 예외 처리 코드를 줄일 수 있었습니다.

 

하지만 처음에는 PassportStrategy의 추상화 구조가 조금 낯설게 느껴졌습니다. 특히 jwtFromRequest, secretOrKey 등의 설정이 어떻게 작동하는지 이해하는 데 시간이 걸렸습니다. 그럼에도 불구하고 흐름을 파악한 뒤에는 NestJS의 DI 시스템과 함께 잘 어우러져 있다는 점에서 큰 만족감을 느꼈습니다.

 

결국 이번 학습을 통해 느낀 가장 큰 인사이트는, 인증 로직을 전략화함으로써 인증 시스템의 확장성과 유연성을 확보할 수 있다는 점이었습니다. 추후 OAuth2, SNS 로그인, 2차 인증 등의 기능도 각기 다른 Strategy로 관리하면, 시스템 전반의 복잡도를 최소화하면서 기능은 점차 확장해나갈 수 있을 것입니다. NestJS에서 Passport와 JWT를 활용한 인증 설계는, 단순한 구현을 넘어 인증 아키텍처의 핵심적 설계 방식임을 깨닫게 되었습니다.

 

학습 인증샷       

                       

수강 인증 사진
학습 인증샷
공부 시작 시간
공부 종료 시간

https://abit.ly/lisbva