NestJS와 TypeORM으로 간단하게 CRUD API 만들기

작성일 :

NestJS와 TypeORM으로 간단하게 CRUD API 만들기

소개

NestJS는 Node.js를 위한 프로그레시브 웹 프레임워크로, 최신의 자바스크립트 기능을 활용하여 강력한 서버사이드 애플리케이션을 구축할 수 있게 도와줍니다. TypeORM은 TypeScript와 함께 사용하기 좋은 ORM(Object Relational Mapper)으로, 쉽게 데이터베이스와 상호작용할 수 있게 해줍니다. 이 글에서는 NestJS와 TypeORM을 사용해서 간단한 CRUD(Create, Read, Update, Delete) API를 만드는 방법을 알아보겠습니다.

준비물

  • Node.js와 npm이 설치되어 있어야 합니다.
  • NestJS CLI가 설치되어 있어야 합니다. npm install -g @nestjs/cli

프로젝트 설정

NestJS 프로젝트를 생성하고 TypeORM을 설정하는 단계부터 시작하겠습니다.

프로젝트 생성

먼저, NestJS 프로젝트를 생성합니다.

sh
nest new crud-api
cd crud-api

생성된 프로젝트로 이동한 후, 필요한 패키지들을 설치합니다.

sh
npm install --save @nestjs/typeorm typeorm mysql2

여기서는 MySQL을 사용합니다. 다른 데이터베이스를 사용하려면 패키지를 변경하면 됩니다.

환경 설정

루트 디렉토리에 .env 파일을 생성하고 데이터베이스 연결 정보를 설정합니다.

DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=password
DB_DATABASE=testdb

src/app.module.ts 파일을 수정하여 TypeORM을 설정합니다.

typescript
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: process.env.DB_HOST,
      port: parseInt(process.env.DB_PORT, 10),
      username: process.env.DB_USERNAME,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_DATABASE,
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
    // 다른 모듈들을 여기에 추가할 수 있습니다.
  ],
})
export class AppModule {}

엔티티 생성

간단한 Item 엔티티를 만듭니다. 이 엔티티는 데이터베이스 테이블과 매핑되며, CRUD 연산을 수행할 대상이 됩니다.

typescript
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Item {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column('text')
  description: string;
}

서비스와 컨트롤러 작성

서비스와 컨트롤러를 작성하여 CRUD API를 구현합니다.

서비스

서비스 클래스는 비즈니스 로직을 담당합니다. src/item/item.service.ts 파일을 생성하여 다음과 같이 작성합니다.

typescript
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Item } from './item.entity';

@Injectable()
export class ItemService {
  constructor(
    @InjectRepository(Item)
    private readonly itemRepository: Repository<Item>,
  ) {}

  async findAll(): Promise<Item[]> {
    return this.itemRepository.find();
  }

  async findOne(id: number): Promise<Item> {
    return this.itemRepository.findOne(id);
  }

  async create(item: Item): Promise<Item> {
    return this.itemRepository.save(item);
  }

  async update(id: number, item: Item): Promise<void> {
    await this.itemRepository.update(id, item);
  }

  async remove(id: number): Promise<void> {
    await this.itemRepository.delete(id);
  }
}

컨트롤러

컨트롤러 클래스는 HTTP 요청을 처리하고 서비스 클래스를 호출하여 응답을 반환합니다. src/item/item.controller.ts 파일을 생성하여 다음과 같이 작성합니다.

typescript
import { Controller, Get, Post, Body, Param, Delete, Put } from '@nestjs/common';
import { ItemService } from './item.service';
import { Item } from './item.entity';

@Controller('items')
export class ItemController {
  constructor(private readonly itemService: ItemService) {}

  @Get()
  findAll(): Promise<Item[]> {
    return this.itemService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: number): Promise<Item> {
    return this.itemService.findOne(id);
  }

  @Post()
  create(@Body() item: Item): Promise<Item> {
    return this.itemService.create(item);
  }

  @Put(':id')
  update(@Param('id') id: number, @Body() item: Item): Promise<void> {
    return this.itemService.update(id, item);
  }

  @Delete(':id')
  remove(@Param('id') id: number): Promise<void> {
    return this.itemService.remove(id);
  }
}

모듈 등록

Item 모듈을 등록하여 완성합니다. src/item/item.module.ts 파일을 생성하여 다음과 같이 작성합니다.

typescript
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Item } from './item.entity';
import { ItemService } from './item.service';
import { ItemController } from './item.controller';

@Module({
  imports: [TypeOrmModule.forFeature([Item])],
  providers: [ItemService],
  controllers: [ItemController],
})
export class ItemModule {}

이제 AppModuleItemModule을 등록합니다. src/app.module.ts 파일을 다음과 같이 수정합니다.

typescript
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from '@nestjs/config';
import { ItemModule } from './item/item.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: process.env.DB_HOST,
      port: parseInt(process.env.DB_PORT, 10),
      username: process.env.DB_USERNAME,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_DATABASE,
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
    ItemModule,
  ],
})
export class AppModule {}

결론

이제 NestJS와 TypeORM을 사용하여 간단한 CRUD API를 구현하는 방법을 배웠습니다. 이 애플리케이션은 기본적인 CRUD 연산을 수행할 수 있으며, 이를 바탕으로 더 복잡한 비즈니스 로직과 다양한 기능을 추가해 나갈 수 있습니다. 다음 단계로는 인증, 권한 부여, 테스트 등 더 고급 주제들을 배우고 프로젝트에 적용해 보세요.