μ λ²μκ°μ μ€νλ§ μμΌ°λλ° κ°μκΈ° λ‘κ·ΈμΈ μλΉμ€λ₯Ό λ§λ λ€κ³ νλ©΄ λΉμ½μ΄ λ무 μ¬νλ€κ³ λλ μ μμ κ² κ°λ€. νμ§λ§ κ°λ μ μΌλ‘ μ€λͺ μ νλκ±°λ³΄λ€ λ°λ‘ κΈ°λ₯μ λ§λ€λ©΄μ μ΄μΌκΈ° ν΄λ³΄λ©΄ λ μλΏκ³ μ΄ν΄κ° μ¬μΈ κ² κ°λ€κ³ μκ°νλ€.
λ°λΌμ JWT ν ν°κ³Ό Passport λΌμ΄λΈλ¬λ¦¬λ₯Ό μ΄μ©ν΄μ λ‘κ·ΈμΈ μλΉμ€λ₯Ό ꡬνν΄λ³΄λ©΄μ Nest
μ λν΄μ μ΅μν΄μ§ μ μλ μκ°μ κ°μ Έλ³΄λλ‘ νμ
μ°μ nest
μμ passport
λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νκΈ° μν΄μ λͺ¨λμ λ€μ΄λ‘λ λ°μμΌ λλλ° λ€μκ³Ό κ°μ΄ νλ‘μ νΈ λ£¨νΈ λλ ν 리 μμΉμμ ν°λ―Έλμ μ΄κ³ λͺ
λ Ήμ΄λ₯Ό μ
λ ₯ ν μ μλλ‘ νλ€.
$ npm install --save @nestjs/passport passport passport-local
$ npm install --save-dev @types/passport-local
κ°λ΅νκ² passport
λΌμ΄λΈλ¬λ¦¬μ λν΄μ μ€λͺ
νλ©΄ μΈμ¦ λ―Έλ€μ¨μ΄λ‘ node
νκ²½μμ μ¬μ©ν μ μλ λΌμ΄λΈλ¬λ¦¬μ΄λ€. λ°λΌμ μΈμ¦μ΄λΌλ κ΄μ¬μ¬λ₯Ό λ°λ‘ λΆλ¦¬νκ² λ¨μΌλ‘μ¨ (μΊ‘μνλ passport λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©ν¨μΌλ‘μ¨) μ½λλ₯Ό κ°κ²°νκ³ μ μ§λ³΄μμ±μ΄ μ’μ μ½λλ₯Ό λ§λ€ μ μλλ‘ λμμ€λλ€.
μ°μ passport
λ₯Ό μ€μΉνμΌλ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νκΈ° μν μ½λλ₯Ό μμ±ν΄λ³΄λλ‘ νκ² λ€.
MVC
ν¨ν΄μ μ΄μ©ν΄μ μ½λλ₯Ό μμ±ν΄λ³΄λλ‘ ν μμ μ΄λ€.
κ·Έλ¦¬κ³ μ΄μ 본격μ μΌλ‘ Controller
μ Service
μ½λλ₯Ό μμ±ν΄μΌ λλλ° nest
μμλ cli
λ‘ μ½λλ₯Ό μμ±ν μ μλλ‘ μ§μν΄μ£Όλλ°, cli
λ₯Ό μ΄μ©ν΄μ μμ±ν΄λ³΄λλ‘ ν μμ μ΄κ³ ν°λ―Έλμ μΌκ³ λ£¨νΈ λλ ν 리 μμΉμμ λ€μκ³Ό κ°μ΄ λͺ
λ Ήμ΄λ₯Ό μ μ΄μ€λ€.
$ nest g module login
$ nest g controller login
$ nest g service login
μμ κ°μ΄ λͺ
λ Ήμ΄λ₯Ό μ
λ ₯νλ©΄ login ν΄λκ° λ£¨νΈ λλ ν 리μ μμ±μ΄ λλ©΄μ μμλ Module
, Controller
, Service
μ½λκ° μμ±λκ³ Controller
, Service
μ λν spec
μ΄λ¦μ΄ λΆμ ν
μ€νΈ μ½λκΉμ§ μμ±μ΄ λλ€.
κ·Έλ¦¬κ³ λͺ
λ Ήμ΄λ‘ μ½λλ₯Ό μμ±ν κ²½μ° λͺ¨λ μ½λ λ΄λΆμ μλμΌλ‘ Controller
, Service
μ λν μ€μ λ ν΄μ£Όκ² λλ©΄μ κ°λ°μ νΈμμ±μ΄ λμμ§λ€.
// login.module.ts
import { Module } from '@nestjs/common';
import { LoginController } from './login.controller';
import { LoginService } from './login.service';
@Module({
controllers: [LoginController],
providers: [LoginService],
})
export class LoginModule {}
Module
μ½λμcontroller
,provider
μ μλμΌλ‘ μΆκ°κ° λλ€.
(λ§μ½ μ§μ μ½λλ₯Ό μμ±νλ©΄ μμ κ°μ μμ μ μλμΌλ‘ ν΄μ£Όμ΄μΌ νλ€.)
μ¬κΈ°μ Controller
μ Service
μ½λλ Spring
μ μ ν΄λ³΄μκ±°λ MVC
ν¨ν΄μ λν΄μ 곡λΆν μ¬λλ€μ΄λΌλ©΄ μλ²½νκ²λ λͺ°λΌλ μ΄λ€ λμμ€μΈμ§ νμ
μ λ κ²μ΄λ€.
νμ§λ§ nest
μλ Module
μ½λκ° λ μ‘΄μ¬νλλ°, μ½κ² μκΈ°νλ©΄ @Module
μ λ
Έν
μ΄μ
μ λͺ
μλ₯Ό ν΄μ£Όμ΄μΌλ§ λͺ
μλ μ½λλ€ μ¬μ΄μ μμ λ‘κ² ν΄λμ€λ₯Ό μ¬μ©ν μ μλ€. λ€μ λ§νλ©΄ μμ‘΄μ± μ£Όμ
μ νκΈ° μν΄μλ Module
μ½λμ @Module
μ λ
Έν
μ΄μ
μ μ€μ μ λ§μΆ°μ ν΄λμ€λ₯Ό λ£μ΄μ£Όμ΄μΌ ν©λλ€.
μμ‘΄μ± μ£Όμ
(Dependency Injection) μ Spring
μμλ§ μ¬μ©λλ κ°λ
μ΄ μλ λͺ¨λ νλ‘κ·Έλλ°μμ μ¬μ©λ μ μλ λμμΈ ν¨ν΄μΌλ‘ nest
μμλ ν΄λΉ ν¨ν΄μ μ΄μ©ν΄μ κ°μ²΄λ₯Ό μμ±ν©λλ€.
λ°λΌμ @Module
μ λ
Έν
μ΄μ
μ€μ κ°λ€μ λ€μκ³Ό κ°μ΅λλ€.
imports
: λ€λ₯Έ λͺ¨λμμ export
ν λͺ¨λμ μ¬μ©νκΈ° μν΄μ ν΄λΉ λΆλΆμ μμ±ν©λλ€.controllers
: ν΄λΉ λͺ¨λμμ μ¬μ©ν controller
ν΄λμ€λ₯Ό μμ±ν©λλ€.providers
: ν΄λΉ λͺ¨λμμ μ¬μ©ν service
ν΄λμ€λ₯Ό μμ±ν©λλ€.exports
: λ€λ₯Έ λͺ¨λμμ μ¬μ©νκΈ° μν ν΄λμ€λ₯Ό μμ±ν©λλ€.μ΄ν΄νκΈ° μ½κ² μμ±ν λ΄μ©μΌλ‘ λ³΄λ€ μμΈν λ΄μ©μ ν΄λΉ λ§ν¬λ₯Ό μ°Έκ³ ν΄μ£ΌμΈμ!
μ΄μ ν
μ€νΈλ₯Ό μν΄ Controller
μ λΌμ°ν° νλλ₯Ό μμ±ν΄λ³΄λλ‘ νμ.
import { Controller, Get } from '@nestjs/common';
@Controller('login')
export class LoginController {
@Get()
login() {
return 'login controller test!!';
}
}
@Controller()
: ν΄λΉ ν΄λμ€κ° Controller μμ λͺ μ.
(κ΄νΈμμ μ μΈ ν μ€νΈλ URL κ²½λ‘λ₯Ό μλ―Έ, http://localhost:ν¬νΈ/login μΌλ‘ νΈμΆνλ©΄ ν΄λΉ ν΄λμ€λ‘ μμ²μ΄ μ¨λ€.)
@Get()
:login
μΌλ‘ μμ²μ΄ μμ λGET
λ©μλμΌ κ²½μ° ν΄λΉ λ©μλλ₯Ό μ€νμν¨λ€.
(GET http://localhost:ν¬νΈ/login μμ²μΌ κ²½μ° μ€ν,@Get('test')
λ‘ μμ±ν κ²½μ° GET http://localhost:ν¬νΈ/login/test λ‘ μμ²μ΄ μμΌμ§login()
λ©μλκ° μ€νλλ€.
κ·Έλ¦¬κ³ ν¬μ€νΈλ§¨μ΄ μμΌλ©΄ ν¬μ€νΈλ§¨μΌλ‘ μ€νν΄λ λμ§λ§ GET μμ²μ λΈλΌμ°μ λ₯Ό μ΄μ©ν΄μ ν΄λ μκ΄ μλ€. λ°λΌμ μ½λλ₯Ό npm run start:dev
λͺ
λ Ήμ΄λ₯Ό μ΄μ©ν΄μ μ€νμν€κ³ μκΈ°μ ν¬νΈμ λ§κ² λΈλΌμ°μ μ μ
λ ₯ν΄μ€λ€. (νμλ 8080 ν¬νΈ)
μμ κ°μ΄ login controller test!! ν
μ€νΈκ° μΆλ ₯ λμμΌλ©΄ μ μμ μΌλ‘ μ μ€νμ΄ λ κ²μ΄λ€.
μ¬κΈ°μ νκ°μ§ κ°κ³Όν λΆλΆμ΄ μλλ°, app.module.ts
μ½λλ₯Ό μ΄μ΄λ³΄λ©΄ λ‘κ·ΈμΈκ³Ό κ΄λ ¨λ μ½λλ€μ΄ μμμ μ€μ μ μΆκ°λ λΆλΆμ λ³Ό μ μλ€.
/*
* controller, providerμ Login κ΄λ ¨ ν΄λμ€λ₯Ό μ μ§ μμλ
* LoginModuleμ΄ import λμ΄ μμ΄μ μ€νμ΄ λλ€...
* exportλ₯Ό ν΄μ£Όμ§ μμλ λλ건 μμ§ μ λͺ¨λ₯΄κ² λ€...
*/
@Module({
imports: [ConfigModule.forRoot(), LoginModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
μ¬κΈ°μ Loginκ³Ό κ΄λ ¨λ λͺ¨λ ν΄λμ€λ₯Ό μ κ±°νκ³ λ€μ http://localhost:ν¬νΈ/login μΌλ‘ μ κ·Όνλ©΄ 404 μλ¬κ° λ°μνλ€.
κ·Έ μ΄μ λ κ°λ΅νκ² μ€λͺ
νμλ©΄ main.ts
μ½λκ° μ€νλλ©΄μ NestApplication
μ΄ μμ±μ΄λκ³ μλ²κ° μ€νμ΄ λλλ°, κ·Έ λ AppModule
μ΄ λ±λ‘λλ©΄μ μμνλ€. λ°λΌμ μ°λ¦¬κ° νλ‘μ νΈμμ λͺ¨λμ΄ μΆκ°λ λ λ§λ€ AppModule
μ λ±λ‘μ ν΄μ£Όμ΄μΌμ§λ§ μ μμ μΌλ‘ μ½λλ₯Ό μ¬μ©ν μ μκ² λλ€.
npm run start:dev -> main.ts μ€ν -> AppModule λ±λ‘ (AppModuleμ λ±λ‘λ λͺ¨λ μ½λκ° λ±λ‘λλ€.)
Spring
μμλ@ComponentScan
μ΄λΌλ μ λ Έν μ΄μ μ νλ‘μ νΈ μμμ μ€μΊνκ³ μ νλ ν¨ν€μ§λͺ μ μ μ΄μ£Όλ©΄@Controller
,@Service
,@Repository
,@Component
λ±μ μ λ Έν μ΄μ μ΄ λΆμ ν΄λμ€λ€μ μλμΌλ‘ λΉ κ°μ²΄λ‘ λ±λ‘ν΄μ μ¬μ©ν μ μλλ‘ ν΄μ£Όλλ°, μμ§ λ΄κ° μλ λ°λ‘λnest
μμλ μ΄ λΆλΆμ μλμΌλ‘AppModule
μ λ±λ‘ν΄μ£Όμ΄μΌ νλ κ² κ°λ€.
μ΄λ²μλ μλΉμ€ μ½λλ₯Ό μμ±νκ³ μ»¨νΈλ‘€λ¬ μ½λμμ μ¬μ© ν μ μλ λ°©λ²μ λν΄μ μμ보μ.
컨νΈλ‘€λ¬μμλ λΌμ°ν° λΆκΈ° μ²λ¦¬λ§ μ§ννκ³ λ³Έκ²©μ μΈ λΉμ¦λμ€ λ‘μ§μ μλΉμ€ μ½λμ μμ±νλ κ²μ΄ MVC
ν¨ν΄μ ν λΆλΆμ΄λ€. μ°μ μ ν
μ€νΈλ₯Ό μν΄μ ν
μ€νΈλ₯Ό λ°ννλ μλΉμ€ μ½λλ₯Ό μμ±ν μ μλλ‘ νλ€.
import { Injectable } from '@nestjs/common';
@Injectable()
export class LoginService {
login() {
return 'test';
}
}
@Injectable()
: μμ‘΄μ± μ£Όμ μ ν μ μλ ν΄λμ€λΌκ³ λͺ μνλ μ λ Έν μ΄μ μ΄λ€.
κ·Έλ¦¬κ³ μλΉμ€ μ½λλ₯Ό 컨νΈλ‘€λ¬μμ λ€μκ³Ό κ°μ΄ νΈμΆν΄λ³΄λλ‘ νμ.
import { Controller, Get } from '@nestjs/common';
import { LoginService } from './login.service';
@Controller('login')
export class LoginController {
constructor(private readonly loginService: LoginService) {}
@Get()
login() {
return this.loginService.login();
}
}
μλ° μ½λμμ μμ‘΄μ± μ£Όμ
μ ν λ μμ±μμμ μ£Όμ
ν΄μ£Όλ κ²κ³Ό λ§μ°¬κ°μ§λ‘ nest μμλ μμ±μμμ μμ‘΄μ± μ£Όμ
μ ν΄μ£Όλλ° constructor(private readonly loginService: LoginService) {}
μ²λΌ λͺ
μν΄μ£Όλ©΄ @Injectable()
μ λ
Έν
μ΄μ
μΌλ‘ μΈν΄ μμ‘΄μ± μ£Όμ
μ΄ λμ΄μ μλΉμ€ μ½λλ₯Ό μ¬μ©ν μ μκ² λλ€.
μ½λλ₯Ό μ μ₯νκ³ λ€μ μ€νμν€λ©΄ λ€μκ³Ό κ°μ΄ μ μμ μΌλ‘ μ€νλλ€. (npm start
λ‘ μ€ννμ κ²½μ°μλ μ¬μμ ν΄μ£Όμ
μΌ ν©λλ€.)
μ¬κΈ°μ login.module.ts
μ½λμμ provider
μ λͺ
μλ loginService
λ₯Ό μμ νκ³ μ€ννλ©΄ μ΄λ»κ² λ κΉ?
import { Module } from '@nestjs/common';
import { LoginController } from './login.controller';
@Module({
controllers: [LoginController],
providers: [], // loginService μμ
})
export class LoginModule {}
κ·Έλ¬λ©΄ λ€μκ³Ό κ°μ μλ¬κ° λ°μνλ€.
Error: Nest can't resolve dependencies of the LoginController (?). Please make sure that the argument LoginService at index [0] is available in the LoginModule context.
Potential solutions:
- If LoginService is a provider, is it part of the current LoginModule?
- If LoginService is exported from a separate @Module, is that module imported within LoginModule?
@Module({
ν΄μνμλ©΄ LoginController
μ½λμμ μμ‘΄μ± μ£Όμ
μ ν΄μ£Όκ³ μΆμλ° LoginModule
μ Provider
μ μ μλ μλΉμ€κ° μλ€λ μλ―Έμ΄λ€.
μκΉ μμμλ λ§νλ―μ΄ λͺ¨λμ μ μλ ν΄λμ€λ€λΌλ¦¬ μμ λ‘κ² ν΄λμ€λ₯Ό μμ‘΄μ± μ£Όμ ν΄μ μ¬μ©νλ €λ©΄ λͺ¨λ μ½λμ μ μ μν΄μ£Όμ΄μΌ νλ€.
κ°λ΅νκ² μ€λͺ
μ νμμλ λΆκ΅¬νκ³ λ΄μ©μ΄ κΈΈμ΄μ Έμ μ΄λ² ν¬μ€ν
μ μ¬κΈ°μ λ§λ¬΄λ¦¬ νκ³ , λ€μ ν¬μ€ν
μ μ΄μ΄μ 본격μ μΌλ‘ Passport
, jwt
λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νκ³ λ‘κ·ΈμΈ κΈ°λ₯μ ꡬννλ λ΄μ©μ μμ±ν΄λ³΄λλ‘ νλλ‘ νκ² λ€.
μμ§ κ³΅λΆμ€μ΄λΌ μλ²½νκ² μλ λ΄μ©μ΄ μλκ³ , μλͺ» 곡λΆν΄μ μλͺ» μκ³ μλ λΆλΆλ€λ μμ μ μλλ° μ§μ ν΄μ£Όμλ©΄ μμ ν μ μλλ‘ νκ² μ΅λλ€.
μ΄λ§ μ΄μ΄.. ππ»ββοΈ