๐ NestJS๋?
NestJS๋ TypeScript๋ก ์์ฑ๋ Node.js ๊ธฐ๋ฐ ๋ฐฑ์๋ ํ๋ ์์ํฌ์
๋๋ค.
Express๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๋ฉฐ, ๋ชจ๋ํ(Modular), ์์กด์ฑ ์ฃผ์
(Dependency Injection), ๋ฐ์ฝ๋ ์ดํฐ ๊ธฐ๋ฐ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํฉ๋๋ค.
๐น NestJS์ ๊ธฐ๋ณธ ๊ฐ๋
๐ 1. ๋ชจ๋(Module) ๊ธฐ๋ฐ ๊ตฌ์กฐ
NestJS๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ชจ๋ ๋จ์๋ก ๊ตฌ์ฑํ์ฌ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๊ณ ์ ์ง๋ณด์๋ฅผ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
import { Module } from '@nestjs/common';
@Module({
imports: [],
controllers: [],
providers: [],
})
export class AppModule {}
๐ 2. ์ปจํธ๋กค๋ฌ(Controller) โ ์์ฒญ ์ฒ๋ฆฌ
์ปจํธ๋กค๋ฌ๋ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ๋ฐ์ ์ฒ๋ฆฌํ๋ ์ญํ ์ ํฉ๋๋ค.
import { Controller, Get } from '@nestjs/common';
@Controller('users') // '/users' ๊ฒฝ๋ก๋ฅผ ์ฒ๋ฆฌ
export class UserController {
@Get()
findAll() {
return "๋ชจ๋ ์ ์ ์กฐํ";
}
}
๐ 3. ์๋น์ค(Service) โ ๋น์ฆ๋์ค ๋ก์ง ๋ด๋น
์๋น์ค๋ ์ปจํธ๋กค๋ฌ์์ ํธ์ถ๋๋ฉฐ, ์ค์ ๋น์ฆ๋์ค ๋ก์ง์ ์ํํฉ๋๋ค.
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserService {
getUsers() {
return ['User1', 'User2', 'User3'];
}
}
๐ 4. ์์กด์ฑ ์ฃผ์ (Dependency Injection, DI)
NestJS๋ ์์กด์ฑ ์ฃผ์ (DI)์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ์ฌ, ๊ฐ์ฒด ๊ฐ์ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ฝ๊ฒ ํฉ๋๋ค.
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get()
findAll() {
return this.userService.getUsers();
}
}
๐๏ธ NestJS์ ์ฑ๊ธํค ํจํด๊ณผ ์ฃผ์ํ ์
๐ฏ ์ฑ๊ธํค(Singleton) ํจํด์ด๋?
์ฑ๊ธํค ํจํด์ ํ๋์ ํด๋์ค์์ ๋จ ํ๋์ ์ธ์คํด์ค๋ง ์์ฑํ๋๋ก ์ ํํ๋ ํจํด์
๋๋ค.
์ฃผ๋ก ์ ์ญ ์ํ๋ฅผ ์ ์งํ๊ฑฐ๋ ๊ณตํต ๋ฆฌ์์ค๋ฅผ ๊ด๋ฆฌํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
โ ์ฑ๊ธํค ํน์ง
- 1ํด๋์ค 1๊ธฐ๋ฅ์ ์ํํ๋ฉฐ, ๊ฐ์ฒด๊ฐ ํ ๋ฒ ์์ฑ๋๋ฉด ํด๋น ์ธ์คํด์ค๋ฅผ ๊ณ์ ์ฌ์ฌ์ฉํฉ๋๋ค.
- ์ธ์คํด์ค๋ฅผ ์ฌ๋ฌ ๊ฐ ๋ง๋ค์ง ์๊ณ ๋จ ํ๋๋ง ์ ์งํ๋ ๊ตฌ์กฐ์ ๋๋ค.
- NestJS์์๋ @Injectable({ providedIn: 'root' }) ๋๋ module ๋จ์๋ก providers์ ๋ฑ๋กํ์ฌ ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค.
โ NestJS์ ์ฑ๊ธํค ์ธ์คํด์ค ๊ด๋ฆฌ
NestJS์์๋ ๊ฐ๋ฐ์๊ฐ ์ง์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ ๋ชจ๋์ ํตํด ์๋์ผ๋ก ์ฑ๊ธํค ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
์ฆ, NestJS์์ provider๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฑ๊ธํค์ผ๋ก ์์ฑ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ ํน์ ์กฐ๊ฑด์์๋ ์ฑ๊ธํค์ด ์๋ ์๋ก์ด ์ธ์คํด์ค๊ฐ ์์ฑ๋ ์ ์์ต๋๋ค!
โ ์ค์ ์ฌ๋ก: WebSocket ์๋ต์ด ๋ ๋ฒ ์ค๋ ๋ฌธ์
๐น ๋ฌธ์ ์ํฉ
NestJS์์ WebSocket์ ์ด์ฉํ ๋ฉ์์ง ์ ์ก ์, ์๋ต์ด ๋ ๋ฒ ์ค๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.
์ฝ๋๋ฅผ ํ์ธํด๋ ๋ก์ง์ ์ด๋ฒคํธ๋ฅผ ์ค๋ณต์ผ๋ก ์ฒ๋ฆฌํ ์ด์ ๊ฐ ์์๋๋ฐ, ์๋ฒ์์ ๋์ผํ ์๋ต์ด ๋ ๋ฒ ์ ๋ฌ๋์์ต๋๋ค.
๐น ์์ธ ๋ถ์
@Module({
imports: [ChatModule],
providers: [ChatGateway],
})
export class AppModule {}
์์ ๊ฐ์ด AppModule์์ ChatModule์ importํ๊ณ , ๋์์ providers์ ChatGateway๋ฅผ ์ถ๊ฐํ๋ฉด ์ธ์คํด์ค๊ฐ ์ค๋ณต ์์ฑ๋ ์ ์์ต๋๋ค.
๐จ ๊ฒฐ๊ณผ์ ์ผ๋ก WebSocket ์๋ต๋ ๋ ๋ฒ ์ ๋ฌ๋จ ๐จ
๋๋ฒ๊น ๊ฒฐ๊ณผ:
constructor() {
console.log('ChatGateway ์ธ์คํด์ค ์์ฑ!');
}
โ console.log๊ฐ ๋ ๋ฒ ์ฐํ์ โ ์ฆ, ์ธ์คํด์ค๊ฐ ๋ ๊ฐ ์์ฑ๋จ!
๐น ํด๊ฒฐ ๋ฐฉ๋ฒ
โ๏ธ ๋์ผํ provider๋ฅผ ์ฌ๋ฌ ๋ชจ๋์์ ์ค๋ณต ์ฃผ์ ํ์ง ์๊ธฐ
@Module({
imports: [],
controllers: [],
providers: [ChatGateway],
exports: [ChatGateway], // ๋ค๋ฅธ ๋ชจ๋์์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ก exports ์ค์
})
export class ChatModule {}
@Module({
imports: [ChatModule], // ChatGateway๋ ChatModule์์ ์ ๊ณต
})
export class AppModule {}
์ด๋ ๊ฒ ํ๋ฉด ChatGateway ์ธ์คํด์ค๊ฐ ๋จ ํ๋๋ง ์์ฑ๋๋ฉฐ, ์ค๋ณต ์๋ต ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
๐ NestJS์ ์ฑ๊ธํค ์ธ์คํด์ค ์์ฑ ์๋ฆฌ
โ๏ธ ๊ธฐ๋ณธ์ ์ผ๋ก provider๋ ์ฑ๊ธํค์ผ๋ก ๋์ โ๏ธ provider๋ฅผ ์ฌ๋ฌ ๊ณณ์์ ์ค๋ณต ์ ์ํ๋ฉด ์๋ก์ด ์ธ์คํด์ค๊ฐ ์์ฑ๋จ โ๏ธ ๋ชจ๋์์ provider๋ฅผ exports ํ๊ณ imports๋ฅผ ํตํด ์ฐธ์กฐํ๋ฉด ์์ โ๏ธ ์ ์ญ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ์ถ์ provider๋ Global ๋ชจ๋๋ก ์ ์ธ ๊ฐ๋ฅ
๐ ๊ณต์ ๋ฌธ์ ์ฐธ๊ณ : NestJS Injection Scopes
๐ฏ ๊ฒฐ๋ก : ์ฌ๋ฐ๋ฅธ ์ฃผ์ ๋ฐฉ๋ฒ
1๏ธโฃ ๊ฐ๋ฅํ๋ฉด ๋ชจ๋ ๋จ์๋ก imports ํ์ฌ provider๋ฅผ ๊ณต์ 2๏ธโฃ ๊ธ๋ก๋ฒํ๊ฒ ์ฌ์ฉํด์ผ ํ ๊ฒฝ์ฐ @Global() ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ํ์ฉ 3๏ธโฃ ๋ฐ๋์ providers์ ์ง์ ์ฃผ์ ํด์ผ ํ๋ ๊ฒฝ์ฐ๋ฅผ ์ ์คํ๊ฒ ํ๋จ
NestJS๋ ๊ฐ๋ ฅํ DI ์์คํ ์ ์ ๊ณตํ์ง๋ง, ๋ฌด์กฐ๊ฑด ๋ชจ๋ provider๊ฐ ์ฑ๊ธํค์ด ๋๋ ๊ฒ์ ์๋๋ค! ๋ผ๋ ์ ์ ๊ธฐ์ตํด์ผ ํฉ๋๋ค.
๐ ์ฌ๋ฐ๋ฅธ provider ์ฃผ์ ๊ตฌ์กฐ๋ฅผ ์ค๊ณํ์ฌ ์๊ธฐ์น ์์ ๋ฒ๊ทธ๋ฅผ ๋ฐฉ์งํ์ธ์! ๐
๐น ์ฑ๊ธํค์ ์ฐ๋ฉด ์ ๋๋ ๊ฒฝ์ฐ
์ฑ๊ธํค์ด ์ ์ ํ์ง ์์ ๊ฒฝ์ฐ๋ ์กด์ฌํฉ๋๋ค.
1๏ธโฃ ํฉํ ๋ฆฌ ํจํด(Factorial Pattern)์ด ํ์ํ ๊ฒฝ์ฐ
- ๋งค๋ฒ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํ๋ ๊ฒฝ์ฐ
- ์: ์ฌ์ฉ์ ์์ฒญ๋ง๋ค ๋ค๋ฅธ ์ค์ ์ ๊ฐ์ง ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ผ ํ ๋
- ์ฑ๊ธํค์ ํ๋์ ์ธ์คํด์ค๋ฅผ ๊ณต์ ํ์ง๋ง, ํฉํ ๋ฆฌ ํจํด์ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
- NestJS์์๋ useFactory๋ฅผ ํ์ฉํ์ฌ ๋์ ์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
- ๊ด๋ จ ๊ณต์ ๋ฌธ์: NestJS Factory Providers
2๏ธโฃ ์์กด์ฑ ์ฃผ์ (DI)์ด ํ์ํ ๊ฒฝ์ฐ
- ์ฑ๊ธํค ๊ฐ์ฒด๋ ์ฃผ์ ๋ฐ์ ์์กด์ฑ์ ๋ณ๊ฒฝํ๊ธฐ ์ด๋ ต์ต๋๋ค.
- ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฐ์ฒด(์: ์์ฒญ๋ง๋ค ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํ๋ ๊ฐ์ฒด)๋ ์ฑ๊ธํค์ผ๋ก ๋ง๋ค๋ฉด ์์กด์ฑ ์ฃผ์ ์ ํตํด ๋์ ์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ ์ด๋ ต์ต๋๋ค.
- ์ฆ, ์์กด์ฑ์ ๋ค๋ฅด๊ฒ ์ค์ ํด์ผ ํ๋ ๊ฒฝ์ฐ ์ฑ๊ธํค์ ์ฌ์ฉํ๋ฉด ๋นํจ์จ์ ์ ๋๋ค.
๐ ํฉํ ๋ฆฌ ํจํด (Factory Pattern)
ํฉํ ๋ฆฌ ํจํด์ ๊ฐ์ฒด์ ์์ฑ์ ๋ด๋นํ๋ ๋ณ๋์ ํด๋์ค๋ ํจ์๋ฅผ ๋์ด ๊ฐ์ฒด๋ฅผ ์ ์ฐํ๊ฒ ์์ฑํ๋ ํจํด์
๋๋ค.
NestJS์์๋ useFactory๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
โ ํฉํ ๋ฆฌ ํจํด์ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ
- ๊ฐ ์์ฒญ๋ง๋ค ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํ๋ ๊ฒฝ์ฐ
- ์: ์ฌ์ฉ์๋ณ ์ปค์คํ ์ค์ ์ด ํ์ํ ์๋น์ค
- ๊ฐ์ฒด ์์ฑ ๊ณผ์ ์ด ๋ณต์กํ ๋
- ์ฌ๋ฌ ๊ฐ์ ์์กด์ฑ์ ์กฐํฉํด์ผ ํ๋ ๊ฒฝ์ฐ
- ๋์ ์ผ๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํด์ผ ํ๋ ๊ฒฝ์ฐ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ์์ฒญ๋ง๋ค ์๋ก ์์ฑํด์ผ ํ๋ ๊ฒฝ์ฐ
๐ซ ํฉํ ๋ฆฌ ํจํด์ ์ฌ์ฉํ๋ฉด ์ ๋๋ ๊ฒฝ์ฐ
- ์ ์ญ์ ์ผ๋ก ํ๋์ ๊ฐ์ฒด๋ง ์ ์งํ๋ฉด ๋๋ ๊ฒฝ์ฐ
- ์: ๋ก๊ทธ ๊ด๋ฆฌ, ์บ์ฑ ์์คํ , ์ค์ ๊ฐ ๊ด๋ฆฌ
- ๊ฐ์ฒด ์์ฑ ๋น์ฉ์ด ํฌ์ง ์๊ณ , ์ฌ์ฌ์ฉ์ด ํ์ํ ๊ฒฝ์ฐ
- ๋น๋ฒํ ์ธ์คํด์ค ์์ฑ์ด ๋ถํ์ํ ๋ฆฌ์์ค ๋ญ๋น๋ก ์ด์ด์ง ์ ์์
๐น NestJS์์ ์ฑ๊ธํค๊ณผ ํฉํ ๋ฆฌ ํจํด ํ์ฉ ์์
โ ์ฑ๊ธํค ์๋น์ค (Repository ํจํด ํ์ฉ)
import { Injectable } from '@nestjs/common';
@Injectable()
export class SingletonService {
private data: string = '์ด๊ธฐ ๋ฐ์ดํฐ';
getData() {
return this.data;
}
setData(newData: string) {
this.data = newData;
}
}
ํด๋น ์๋น์ค๋ @Injectable()๋ก ๋ฑ๋ก๋๋ฉฐ, ์ ํ๋ฆฌ์ผ์ด์ ๋ด์์ ํ๋์ ์ธ์คํด์ค๋ง ์ ์ง๋ฉ๋๋ค.
โ ํฉํ ๋ฆฌ ํจํด ํ์ฉ (๋์ ๊ฐ์ฒด ์์ฑ)
import { Injectable } from '@nestjs/common';
@Injectable()
export class DynamicService {
constructor(private readonly config: any) {}
getConfig() {
return this.config;
}
}
import { Module } from '@nestjs/common';
@Module({
providers: [
{
provide: 'DYNAMIC_SERVICE',
useFactory: () => {
return new DynamicService({ key: 'value' });
},
},
],
exports: ['DYNAMIC_SERVICE'],
})
export class DynamicModule {}
useFactory๋ฅผ ์ด์ฉํ๋ฉด ๋งค๋ฒ ๋ค๋ฅธ ์ค์ ๊ฐ์ ๊ฐ์ง ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
๐น 3๋ ์ด์ด ๊ตฌ์กฐ + DB ๋ ํฌ์งํ ๋ฆฌ ์ ์ฉ
3๋ ์ด์ด ์ํคํ ์ฒ(NestJS ์คํ์ผ)์์ ์ฑ๊ธํค๊ณผ ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ํ์ฉํ๋ ๋ฐฉ์์ ๋๋ค.
๐ ๊ตฌ์กฐ
1๏ธโฃ Controller - ์์ฒญ์ ๋ฐ๊ณ ์๋ต์ ์ฒ๋ฆฌ
2๏ธโฃ Service - ๋น์ฆ๋์ค ๋ก์ง ์ฒ๋ฆฌ
3๏ธโฃ Repository - ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ จ ๋ก์ง ์ฒ๋ฆฌ
โ ๋ ํฌ์งํ ๋ฆฌ (Repository)
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserRepository {
private users = [];
findAll() {
return this.users;
}
save(user) {
this.users.push(user);
}
}
UserRepository๋ ๋ฐ์ดํฐ ์ ์ฅ์ ์ญํ ์ ํ๋ฉฐ, ์ฑ๊ธํค์ผ๋ก ์ ์ง๋ฉ๋๋ค.
โ ์๋น์ค (Service)
import { Injectable } from '@nestjs/common';
import { UserRepository } from './user.repository';
@Injectable()
export class UserService {
constructor(private readonly userRepository: UserRepository) {}
createUser(user) {
this.userRepository.save(user);
}
getAllUsers() {
return this.userRepository.findAll();
}
}
UserService๋ UserRepository๋ฅผ ์ฃผ์ ๋ฐ์ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค.
โ ์ปจํธ๋กค๋ฌ (Controller)
import { Controller, Get, Post, Body } from '@nestjs/common';
import { UserService } from './user.service';
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
@Post()
createUser(@Body() user) {
this.userService.createUser(user);
return { message: 'User created' };
}
@Get()
getAllUsers() {
return this.userService.getAllUsers();
}
}
UserController๋ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ๋ฐ์ UserService๋ฅผ ํธ์ถํ๋ ์ญํ ์ ํฉ๋๋ค.
๐น ์ ๋ฆฌ
โ ์ฑ๊ธํค ํจํด
- ์ ์ญ์ ์ผ๋ก ํ๋์ ์ธ์คํด์ค๋ง ์ ์งํด์ผ ํ๋ ๊ฒฝ์ฐ ์ ํฉ
- ๋ก๊ทธ, ์ค์ ๊ฐ, ๊ณตํต ์บ์ ๊ด๋ฆฌ ๋ฑ์ ์ ๋ฆฌ
โ ํฉํ ๋ฆฌ ํจํด
- ๋งค๋ฒ ์๋ก์ด ๊ฐ์ฒด๊ฐ ํ์ํ ๊ฒฝ์ฐ ์ ํฉ
- ์์กด์ฑ์ ๋ค๋ฅด๊ฒ ์ฃผ์ ํด์ผ ํ๋ ๊ฒฝ์ฐ ์ ์ฉ
โ NestJS์์ ์ฑ๊ธํค๊ณผ ํฉํ ๋ฆฌ ์ ์ฉ
- Repository๋ ์ฑ๊ธํค์ผ๋ก ์ฌ์ฉ
- ์ ๋์ ์ธ ์ค์ ์ด ํ์ํ ๊ฐ์ฒด๋ ํฉํ ๋ฆฌ ํจํด์ ํ์ฉ
๐ NestJS์์ ์๋น์ค(Service)์ ๋ ํฌ์งํ ๋ฆฌ(Repository) ์์
NestJS์์ 3๋ ์ด์ด ๊ตฌ์กฐ(Controller โ Service โ Repository) ๋ฅผ ์ ์ฉํ์ฌ ์๋น์ค๋ฅผ ๊ตฌ์ฑํ๋ ์์ ์
๋๋ค.
์ด ์์ ์์๋ ์ฌ์ฉ์(User) ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํฉ๋๋ค.
โ 1. Repository ํ์ผ (UserRepository)
Repository๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ง์ ์ ์ผ๋ก ์ํธ์์ฉํ๋ ์ญํ ์ ํฉ๋๋ค.
NestJS์์๋ @Injectable()์ ์ฌ์ฉํ์ฌ ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
๐ user.repository.ts
import { Injectable } from '@nestjs/common';
interface User {
id: number;
name: string;
email: string;
}
@Injectable()
export class UserRepository {
private users: User[] = []; // ์์ ๋ฐ์ดํฐ ์ ์ฅ์ (DB ๋์ ์ฌ์ฉ)
// ๋ชจ๋ ์ฌ์ฉ์ ์กฐํ
findAll(): User[] {
return this.users;
}
// ํน์ ์ฌ์ฉ์ ์กฐํ
findById(id: number): User | undefined {
return this.users.find(user => user.id === id);
}
// ์ฌ์ฉ์ ์ถ๊ฐ
save(user: User): User {
this.users.push(user);
return user;
}
// ์ฌ์ฉ์ ์ญ์
delete(id: number): boolean {
const index = this.users.findIndex(user => user.id === id);
if (index !== -1) {
this.users.splice(index, 1);
return true;
}
return false;
}
}
๐ ์ค๋ช :
- findAll(): ๋ชจ๋ ์ฌ์ฉ์ ๋ฆฌ์คํธ ๋ฐํ
- findById(id): ํน์ ID์ ์ฌ์ฉ์ ์ฐพ๊ธฐ
- save(user): ์๋ก์ด ์ฌ์ฉ์ ์ถ๊ฐ
- delete(id): ํน์ ์ฌ์ฉ์๋ฅผ ์ญ์
โ 2. ์๋น์ค ํ์ผ (UserService)
Service๋ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ๋ ๊ณณ์ผ๋ก, Repository๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ํฉ๋๋ค.
๐ user.service.ts
import { Injectable } from '@nestjs/common';
import { UserRepository } from './user.repository';
interface User {
id: number;
name: string;
email: string;
}
@Injectable()
export class UserService {
constructor(private readonly userRepository: UserRepository) {}
// ๋ชจ๋ ์ฌ์ฉ์ ์กฐํ
getAllUsers(): User[] {
return this.userRepository.findAll();
}
// ํน์ ์ฌ์ฉ์ ์กฐํ
getUserById(id: number): User | undefined {
return this.userRepository.findById(id);
}
// ์ฌ์ฉ์ ์์ฑ
createUser(name: string, email: string): User {
const newUser: User = {
id: Date.now(), // ๊ฐ๋จํ ID ์์ฑ
name,
email,
};
return this.userRepository.save(newUser);
}
// ์ฌ์ฉ์ ์ญ์
deleteUser(id: number): boolean {
return this.userRepository.delete(id);
}
}
๐ ์ค๋ช :
- getAllUsers(): ๋ชจ๋ ์ฌ์ฉ์ ์กฐํ
- getUserById(id): ํน์ ์ฌ์ฉ์ ์กฐํ
- createUser(name, email): ์๋ก์ด ์ฌ์ฉ์ ์ถ๊ฐ
- deleteUser(id): ์ฌ์ฉ์ ์ญ์
โ 3. ๋ชจ๋ ํ์ผ (UserModule)
Repository์ Service๋ฅผ UserModule์ ๋ฑ๋กํ์ฌ ์ฌ์ฉํฉ๋๋ค.
๐ user.module.ts
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserRepository } from './user.repository';
@Module({
providers: [UserService, UserRepository],
exports: [UserService], // ๋ค๋ฅธ ๋ชจ๋์์ ์ฌ์ฉํ ์ ์๋๋ก ๋ด๋ณด๋ด๊ธฐ
})
export class UserModule {}
๐ ์ค๋ช :
- providers: UserService์ UserRepository๋ฅผ NestJS์ DI ์ปจํ ์ด๋์ ๋ฑ๋ก
- exports: UserService๋ฅผ ๋ด๋ณด๋ด์ ๋ค๋ฅธ ๋ชจ๋์์ ์ฌ์ฉํ ์ ์๋๋ก ํจ
โ 4. ์ปจํธ๋กค๋ฌ ํ์ผ (UserController)
ํด๋ผ์ด์ธํธ ์์ฒญ์ ๋ฐ์ Service๋ฅผ ํธ์ถํ๋ ์ญํ ์ ํฉ๋๋ค.
๐ user.controller.ts
import { Controller, Get, Post, Delete, Param, Body } from '@nestjs/common';
import { UserService } from './user.service';
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
// ๋ชจ๋ ์ฌ์ฉ์ ์กฐํ
@Get()
getAllUsers() {
return this.userService.getAllUsers();
}
// ํน์ ์ฌ์ฉ์ ์กฐํ
@Get(':id')
getUserById(@Param('id') id: string) {
return this.userService.getUserById(Number(id));
}
// ์ฌ์ฉ์ ์์ฑ
@Post()
createUser(@Body() body: { name: string; email: string }) {
return this.userService.createUser(body.name, body.email);
}
// ์ฌ์ฉ์ ์ญ์
@Delete(':id')
deleteUser(@Param('id') id: string) {
return this.userService.deleteUser(Number(id));
}
}
๐ ์ค๋ช :
- @Get() โ ๋ชจ๋ ์ฌ์ฉ์ ์กฐํ
- @Get(':id') โ ํน์ ์ฌ์ฉ์ ์กฐํ
- @Post() โ ์ฌ์ฉ์ ์ถ๊ฐ
- @Delete(':id') โ ์ฌ์ฉ์ ์ญ์
โ 5. ๋ฉ์ธ ๋ชจ๋ ํ์ผ (app.module.ts)
๋ชจ๋ ๋ชจ๋์ AppModule์์ ๊ฐ์ ธ์์ ์ฌ์ฉํ ์ ์๋๋ก ๋ฑ๋กํฉ๋๋ค.
๐ app.module.ts
import { Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
import { UserController } from './user/user.controller';
@Module({
imports: [UserModule],
controllers: [UserController],
})
export class AppModule {}
UserModule์ AppModule์ ๋ฑ๋กํ์ฌ NestJS๊ฐ ํด๋น ๋ชจ๋์ ์ธ์ํ ์ ์๋๋ก ํฉ๋๋ค.
โ 6. ์คํ ๋ฐฉ๋ฒ
1๏ธโฃ NestJS ํ๋ก์ ํธ์์ ์คํ
npm run start
2๏ธโฃ API ํ ์คํธ (Postman ๋๋ curl ์ฌ์ฉ)
- ๋ชจ๋ ์ฌ์ฉ์ ์กฐํ
curl -X GET http://localhost:3000/users
- ํน์ ์ฌ์ฉ์ ์กฐํ (ID: 1)
curl -X GET http://localhost:3000/users/1
- ์ ์ฌ์ฉ์ ์ถ๊ฐ
curl -X POST http://localhost:3000/users -H "Content-Type: application/json" -d '{"name": "John Doe", "email": "john@example.com"}'
- ์ฌ์ฉ์ ์ญ์ (ID: 1)
curl -X DELETE http://localhost:3000/users/1
โ ์ ๋ฆฌ
- Repository (user.repository.ts) โ DB์ ์ง์ ์ฐ๊ฒฐ (๋ฐ์ดํฐ ์ ์ฅ/์กฐํ/์ญ์ )
- Service (user.service.ts) โ ๋น์ฆ๋์ค ๋ก์ง ๋ด๋น (๋ฐ์ดํฐ ๊ฐ๊ณต ๋ฐ ์ฒ๋ฆฌ)
- Controller (user.controller.ts) โ HTTP ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ Service ํธ์ถ
- Module (user.module.ts) โ ์๋น์ค์ ๋ ํฌ์งํ ๋ฆฌ๋ฅผ NestJS์ ๋ฑ๋ก
NestJS์ ๊ธฐ๋ณธ์ ์ธ 3๋ ์ด์ด ๊ตฌ์กฐ๋ฅผ ์ ์ฉํ ์์ ์
๋๋ค. ๐
์ด์ ์ํ๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ฑฐ๋, DB์ ์ฐ๋ํ๋ ๋ฐฉ์์ผ๋ก ํ์ฅํ ์ ์์ต๋๋ค.
์ฐธ๊ณ
https://jun-choi-4928.medium.com/nest-js-behind-the-curtain-712b39abd49c
https://jay-ji.tistory.com/106
https://velog.io/@kdhn712/NestJs-%EB%B0%9C%ED%91%9C
https://velog.io/@pear/Query-String-%EC%BF%BC%EB%A6%AC%EC%8A%A4%ED%8A%B8%EB%A7%81%EC%9D%B4%EB%9E%80
ํฉํ ๋ฆฌ์ผํจํด
https://docs.nestjs.com/fundamentals/custom-providers#factory-providers-usefactory
'JavaScript > js ๋ฌธ๋ฒ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
NestJs - HTTP ์์ธ ์ฒ๋ฆฌ ํด๋์ค (0) | 2025.02.14 |
---|---|
NestJs ์ปจํธ๋กค๋ฌ - req ๋ฐ์ดํฐ ์ฌ์ฉ (0) | 2025.02.13 |
NestJS์์ TypeORM์ ์ฌ์ฉํ ๋ Repository์์ ์ ๊ณตํ๋ ์ฃผ์ ๋ฉ์๋ (0) | 2025.02.13 |
NestJS - IsDate() vs @IsDateString() (0) | 2025.02.13 |
NestJS ํ์ผ ์์ฑ (0) | 2025.02.13 |