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

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

NestJS

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

NangIn 2025. 5. 1. 22:41

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

 

강의 내용 정리   

 

Middleware 이론

 

NestJS 요청 처리 순서

  • 미들웨어 → 가드 → 인터셉터 → 파이프 → 컨트롤러(핸들러) → 응답 → 인터셉터 → 예외 필터

 

미들웨어란?

  • 라우트 핸들러 실행 전에 동작
  • Request, Response, Next 객체에 접근 및 조작 가능
  • NestJS 공식 문서에도 다음과 같은 역할로 정의됨:
  • 미들웨어의 주요 역할기능 설명
    자유로운 로직 실행 로그 출력, 요청 전처리 등
    req/res 객체 변경 예: req.user 값 추가
    요청-응답 사이클 중단 인증 실패 시 직접 응답 종료
    다음 단계로 전달 next() 호출 시 다음 미들웨어 혹은 컨트롤러로 진행

 

미들웨어 만들기

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`${req.method} ${req.url}`);
    next();
  }
}
  • NestMiddleware를 구현하고 use() 메서드 필수 정의
  • next() 호출 전까지 원하는 로직 실행 가능

 

미들웨어 적용 방법

  • 모듈 단위 적용
    • AppModule 또는 특정 모듈에서 적용
      • export class AppModule implements NestModule {
          configure(consumer: MiddlewareConsumer) {
            consumer
              .apply(LoggerMiddleware)
              .forRoutes('*'); // 전체 라우트 적용
          }
        }
        
    • apply() 안에 여러 미들웨어 넣을 수도 있음
    • forRoutes()에는 다음과 같은 방식 사용 가능:
      • .forRoutes('cats')                      // 특정 경로 전체
        .forRoutes({ path: 'cats', method: RequestMethod.GET })  // 특정 메서드만
        .forRoutes('*')                         // 전체 라우트
        
        
  • 제외 라우트 설정
    • consumer
        .apply(LoggerMiddleware)
        .exclude({ path: 'cats', method: RequestMethod.POST }) // 제외 조건
        .forRoutes('*');
      
      • exclude()를 먼저 선언하고 forRoutes()로 나머지 적용
      • 너무 복잡하게 exclude 로직을 설계하지 않도록 주의
  • 글로벌 미들웨어로 등록
    • main.ts에서 전체 앱에 전역 적용
    app.use(LoggerMiddleware);
    

 

미들웨어 다중 적용

consumer
  .apply(LoggerMiddleware, AuthMiddleware, CacheMiddleware)
  .forRoutes('*');
  • 미들웨어는 등록 순서대로 실행
  • 순서 중요할 경우 주의 필요

 

Bearer Token Middleware 구현하기

 

목표

  • 매번 컨트롤러/가드에서 Bearer 토큰을 파싱하지 않고, 전역 미들웨어로 처리하여 중복 제거 및 편의성 향상
  • Request 객체에 payload를 삽입해 이후 로직에서 req.user로 간편하게 접근

 

문제 인식

  • parseBearerToken()을 매번 불러서 토큰을 파싱하는 게 번거로움
  • 해결 방안: 미들웨어를 통해 자동으로 처리되도록 만들자

 

미들웨어 구조 설계 및 생성

  • middleware/bearer-token.middleware.ts 생성
  • NestMiddleware 인터페이스 구현 및 use() 함수 정의
export class BearerTokenMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    // ...
  }
}

 

토큰 파싱 및 예외 처리 로직

  • 토큰 유무 확인
    • Authorization 헤더가 없으면 → 인증 의도 없음 → next()로 패스
  • Bearer 토큰 형식 확인 및 파싱
    • 형식이 "Bearer "인지 확인
    • 아니면 BadRequestException 던짐
    • 올바르면 토큰 문자열만 추출
  • 디코드 후 타입 확인 (access / refresh)
    • jwtService.decode()로 타입 확인
    • 타입이 access나 refresh가 아니면 → UnauthorizedException
  • Secret 결정
    • 토큰 타입에 따라 accessTokenSecret 또는 refreshTokenSecret을 선택

 

검증 및 payload 삽입

  • jwtService.verify()로 실제 검증 수행
  • 검증된 payload를 req.user에 삽입

 

의존성 주입

  • JwtService, ConfigService를 생성자에서 주입
  • ConfigModule은 글로벌 등록되어 따로 exports 불필요

 

AppModule에 미들웨어 등록

  • configure()에서 consumer.apply().forRoutes()를 통해 전역 등록
  • 단, 로그인/회원가입은 Basic Auth 사용 → exclude()로 예외 처리
consumer
  .apply(BearerTokenMiddleware)
  .exclude(
    { path: 'auth/login', method: RequestMethod.POST },
    { path: 'auth/register', method: RequestMethod.POST }
  )
  .forRoutes('*');

 

미들웨어 적용 후 검증

  • 컨트롤러에서 @Req() req: Request를 통해 req.user에 접근
  • 토큰이 포함되지 않으면 undefined
  • Bearer 토큰 포함 → payload 정보가 정상 출력됨

 

학습 후기         

 

이번 강의를 통해 NestJS의 미들웨어 구조와 실질적인 활용 방식에 대해 명확하게 이해할 수 있었습니다. 이전까지는 미들웨어를 단순히 로깅이나 요청 전처리 용도로만 생각했으나, 이번에 Bearer Token을 파싱하고 검증하는 과정을 미들웨어로 추출함으로써 인증 흐름 전반을 효율화할 수 있다는 사실을 직접 체감할 수 있었습니다.

 

가장 인상 깊었던 부분은 req.user에 payload를 삽입하는 방식이었습니다. 일반적으로는 가드나 컨트롤러 내부에서 JWT 검증 로직을 넣고 결과를 기반으로 인증 여부를 판단했지만, 이번 방식은 인증과 관련된 공통 로직을 미들웨어로 분리하여 코드 중복을 제거하고 유지보수성을 높이는 데 효과적이었습니다. 특히 parseBearerToken 같은 유틸성 함수가 여기저기서 반복적으로 호출되는 상황에서, 해당 로직을 미들웨어로 대체한 구조는 실무적인 관점에서 매우 유용한 패턴이라고 느꼈습니다.

 

또한 NestJS의 요청 처리 순서를 다시 확인하고, 미들웨어가 가드보다 앞서 실행된다는 점을 이해함으로써 인증 흐름 전체를 설계하는 데에 훨씬 더 명확한 기준을 갖게 되었습니다. 예외 처리와 next() 호출 타이밍, 그리고 Authorization 헤더가 없는 경우에도 유연하게 넘어가는 구조는 사용자 경험 측면에서도 중요하다고 생각합니다.

 

특정 라우트를 exclude() 처리하여 미들웨어 적용 대상에서 제외하는 방법 역시 유연한 라우팅 구성을 가능하게 해주었고, 미들웨어의 실행 순서가 등록 순서에 따라 결정된다는 점은 로그, 캐시, 인증 등을 조합할 때 고려해야 할 중요한 포인트임을 실감했습니다.

 

결론적으로, 이번 강의를 통해 NestJS에서 미들웨어가 단순한 기능적 보조 수단을 넘어서 인증, 보안, 요청 흐름 제어 등 핵심 기능까지도 담당할 수 있는 유연한 구조임을 체감했습니다. 앞으로 프로젝트를 설계할 때는 이러한 구조적 이점을 적극 활용해, 깔끔하고 유지보수 가능한 인증 흐름을 설계하고자 합니다.

 

학습 인증샷       

                       

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

https://abit.ly/lisbva