회원가입 기능을 구현했으니, JWT를 사용한 사용자의 로그인 서비스를 구현해봅시다.
우리가 구현할 LogIn Process는 위 그림과 같습니다.
JWT에 대한 세부적인 내용은 기술블로그에 작성해두었습니다.
사용자의 인증이 필요한 경우 Client는 발급받은 JWT를 Requet Header에 실어 같이 보내줍니다. Backend는 JWT를 받고 Guard를 통해 JWT Strategy를 실행하고, Secret Key를 통해 JWT를 Decoding합니다. JWT를 복호화한 후에 request.user
를 통해 User의 정보를 저장하고, User의 정보를 이용해 원하는 API의 Business Logic이 수행된 후 Response 됩니다.
npm install --save @nestjs/jwt passport-jwt
npm install --save-dev @types/passport-jwt
Passport는 인기있는 node.js 인증 라이브러리로서 자격증명(JWT, 사용자 이름/암호)을 확인하여 사용자를 인증하고, 인증 상태를 관리하고, 인증된 사용자에 대한 정보를 Route Handler에서 사용할 수 있도록 Request 객체에 첨부해줍니다.
기본적인 로그인과 인증절차에 대해 살펴봤으니 User Login 기능을 구현해봅시다.
먼저 사용자에 대한 인증을 처리해줄 AuthModule을 생성해줍니다.
nest g mo auth
nest g service auth
만들어진 Auth 폴더 안에 Jwt 폴더를 생성하고 jwt.guard.ts
와 jwt.strategy.ts
파일을 생성해줍니다.
AuthGuard
를 상속받았는데, AuthGuard
는 Jwt Strategy를 자동으로 실행해주는 기능이 있습니다. 따라서 jwt.strategy.ts
를 다음과 같이 작성해줍니다.
jwtFromRequest
를 통해 Header의 Token으로부터 JWT를 추출하고, SecretKey와 만료기간 설정을 해줍니다. 만료기간을 무시하지 않기 위해 false
로 설정합니다. validate
는 인증부분인데 로그인을 완료한 후 다시 살펴보겠습니다.
Jwt 폴더를 작성한 후 Auth Module에 필요한 Module들을 Import합니다.
Passport Module에서는 나중에 만들 Strategy의 기본 설정을 하고, JwtModule은 로그인에 대한 설정을 해줍니다. 이제 AuthService에서 Login 기능을 만들어봅시다.
회원가입 시 유효성 검사를 위한 UserCreateDto
를 생성한 것 처럼, 로그인 시 필요한 아이디와 비밀번호에 대한 유효성 조건 확인을 위해 LoginRequestDto
를 작성합니다.
로그인을 위해 필요한 작업을 완료했으니 이제
AuthService
에서 Logic을 구현해봅시다.
loginRequestDto
로 로그인에 필요한 아이디와 비밀번호를 받습니다.payload
에 User id와 account를 넣고 JWT를 생성하여 반환합니다.AuthService
를 작성하고 난 후 Controller에서 Route Handler를 통해 Login 요청을 받아 JWT를 발급할 수 있도록 합니다.
이 때, User Controller에서 Auth Service를 사용하려면 User Module에서 Auth Module을 import 해주어야 합니다. 또한 AuthService에서도 UserReposotiry를 사용하기 위해 UserModule을 import 해주었습니다.
이렇게 서로가 서로를 참조하는 경우를 순환참조라고 하며, Call Back과 같은 문제가 발생할 수 있습니다. 이런 경우 forwardRef()
를 사용해서 서로를 import 해줍니다.
Auth Module
User Module
단순히 서로를 import 한다고 사용 가능한 것이 아니라, 다른 Module이 DI가 가능하게 하기 위해서는 export 해줘야 합니다. User Module에서는 TypeOrmModule
, Auth Module에서는 AuthService
를 각각 export 해주었습니다.
PostMan을 활용해서 Login 기능이 구현되고, JWT를 반환해주는지 확인해봅시다!
제대로 accesstoken
을 발급해주는 것을 확인할 수 있었습니다!