안녕하세요. 사용자 정보를 생성(Create), 읽기(Read), 수정(Update), 삭제(Delete)하는 기본적인 CURD(Create, Read, Update, Delete) 기능을 갖춘 REST API를 구현해보겠습니다.
Nest.js 프로젝트 생성
먼저 Nest CLI를 사용하여 새로운 프로젝트를 생성해봅시다.
nest new Nest-project
모듈 생성
API를 구현할 모듈을 생성해봅시다.
nest g module app
nest g module user
컨트롤러 생성
nest g controller app
nest g controller user
서비스 생성
nest g service app
nest g service user
코드 작성
이제 본격적으로 코드를 작성해볼까요?
먼저 src/user 안에 user.module.ts파일을 작성해보도록 하겠습니다.
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';
@Module({
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
그 다음 user 정보를 담을 Model이 들어갈 user.entity.ts 파일을 작성해 보도록 하겠습니다.
typeorm을 사용하여 작성해보죠.
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
username: string;
@Column()
email: string;
}
그 후 user.module.ts에 이 모델을 추가해주어야 합니다.
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { User } from './user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
그 다음에는 해당 클래스에서는 사용자 정보를 다루는 메서드들을 구현하고 있는 UserService클래스를 작성해보도록 하겠습니다.
user.service.ts 부분을 수정해봅시다!
import {Injectable, NotFoundException} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
import {UpdateUserDto} from "../dto/update-user.dto";
import {CreateUserDto} from "../dto/create-user.dto";
import {DeleteDto} from "../dto/delete.dto";
@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private userRepository: Repository<User>,
) {}
async findAll(): Promise<User[]> {
return this.userRepository.find();
}
async findOne(id: number): Promise<User> {
return this.userRepository.findOne({ where: { id } });
}
async create(createUserDto: CreateUserDto): Promise<User> {
const user = new User();
user.username = createUserDto.username;
user.email = createUserDto.email;
return this.userRepository.save(user);
}
async update(id: number, updateUserDto: UpdateUserDto) {
const user = await this.userRepository.findOne({ where: { id } });
if (!user) {
throw new NotFoundException('User not found');
}
await this.userRepository.update(id, updateUserDto);
return { message: 'User updated successfully' };
}
async remove(id: number): Promise<{ message: string }> {
const user = await this.userRepository.findOne({ where: { id } });
if (!user) {
throw new NotFoundException('User not found');
}
await this.userRepository.delete(id);
return { message: 'User deleted successfully' };
}
}
update, remove 부분만 간단하게 예외처리 하였습니다.
create에 따로 예외 처리 하지 않는 이유는 dto에서 빈 값들을 알아서 잡아내주기 때문입니다.
그 다음에는 데이터를 전달하고 검증하기 편하게 하기 위해 DTO를 작성해 줄 겁니다.
user디렉토리 안에 dto 디렉토리를 추가하여 post, update, delete에 대응하는 DTO를 만들어 봅시다.
create-user.dto.ts
export class CreateUserDto {
readonly username: string;
readonly email: string;
}
update-user.dto.ts
export class UpdateUserDto {
readonly username: string;
readonly email: string;
}
delete.dto.ts
export class DeleteDto {
readonly id: string;
}
이제 라우터를 담당하게 되는 컨트롤러 부분인 user.controller.ts에 코드를 추가해보죠.
아까 만들었던 DTO에 대응하도록 만들겁니다.
import { Controller, Get, Post, Put, Delete, Body, Param } from '@nestjs/common';
import { UserService } from './user.service';
import { CreateUserDto } from '../dto/create-user.dto';
import { UpdateUserDto} from "../dto/update-user.dto";
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get()
findAll() {
return this.userService.findAll();
}
@Get(':id')
findOne(@Param('id') id: number) {
return this.userService.findOne(id);
}
@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.userService.create(createUserDto);
}
@Put(':id')
update(@Param('id') id: number, @Body() updateUserDto: UpdateUserDto) {
const user = { id, ...updateUserDto };
return this.userService.update(id, user);
}
@Delete(':id')
remove(@Param('id') id: number) {
return this.userService.remove(id);
}
}
참고로 위와 같이 dto를 따로 따로 만들어서 import 하기 귀찮으시다면 user.dto.ts로 만든 다음에 위 클래스를 한 곳에 넣은 다음 3 클래스를 한 곳에 넣으신 다음에
import { CreateUserDto, UpdateUserDto, DeleteDto } from "../dto/user.dto";
위 형태로 하셔도 무방합니다.
자! 이제 마지막으로 app.module.ts 부분에 UserModule을 추가해봅시다!
여기에 Database를 연결해주고, UserModule도 import 해줘야 합니다.
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import {UserModule} from "./user/user.module";
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: '123456',
database: 'pre-test',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
}),
UserModule
],
})
export class AppModule {}
디렉토리 구조
지금까지 잘 따라오셨다면 디렉토리 구조는 아래와 같습니다.
.spec.ts부분은 제외하고 넣었습니다
Nest-project/
├── src/
│ ├── user/
│ ├── dto/
│ │ ├── create-user.dto.ts
│ │ ├── update-user.dto.ts
│ │ ├── user.controller.ts
│ │ ├── user.model.ts
│ │ ├── user.module.ts
│ │ ├── user.service.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ ├── app.controller.ts
│ ├── main.ts
├── node_modules/
├── package.json
├── tsconfig.json
└── tslint.json
실행
이제 nest명령어를 사용하여 서버를 실행해봅시다.
nest start
그럼 우리가 controller에 추가했던 라우터들이 log에 출력되는 모습을 볼 수 있습니다.
[Nest] 20676 - 2024. 02. 28. 오전 12:42:23 LOG [NestFactory] Starting Nest application...
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [InstanceLoader] AppModule dependencies initialized +66ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [InstanceLoader] TypeOrmModule dependencies initialized +0ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [InstanceLoader] TypeOrmCoreModule dependencies initialized +31ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [InstanceLoader] TypeOrmModule dependencies initialized +0ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [InstanceLoader] UserModule dependencies initialized +1ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [RoutesResolver] UserController {/users}: +13ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [RouterExplorer] Mapped {/users, GET} route +2ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [RouterExplorer] Mapped {/users/:id, GET} route +0ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [RouterExplorer] Mapped {/users, POST} route +1ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [RouterExplorer] Mapped {/users/:id, PUT} route +0ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [RouterExplorer] Mapped {/users/:id, DELETE} route +0ms
[Nest] 20676 - 2024. 02. 28. 오전 12:42:24 LOG [NestApplication] Nest application successfully started +1ms
이제 Postman을 실행하여 Test를 해보죠.
GET
아직 아무런 데이터를 추가하지 않은 상태이기 때문에 빈 값이 출력되는 모습을 볼 수 있습니다.
POST
POST는 @Body로 넣어주기 때문에 위와 같이 넣어주면 됩니다.
제대로 들어갔는 지 확인해볼까요?
정상적으로 수정된 것을 확인할 수 있습니다.
PUT
정상적으로 수정됐네요.
DELETE
지금까지 간단하게 Nest에서 REST API를 구현해보았습니다.
도움이 되셨다면 공감 버튼 부탁드립니다!
'프로그래밍(Basic) > NestJS' 카테고리의 다른 글
[바미] NestJS - 인터셉터(Interceptors) (0) | 2024.03.05 |
---|---|
[바미] NestJS - 데코레이터(Custom decorators) (0) | 2024.03.02 |
[바미] Nest 모듈(Module) 이해하기 (0) | 2024.02.27 |
[바미] Nest 소개 (0) | 2024.02.26 |
Nest - EntityMetadataNotFoundError (0) | 2024.01.12 |