nest js

NestJs 데이터베이스 연동하기 (mysql, typeorm)

호리둥절 2023. 4. 12. 19:47

🌈 NestJs에서 typeORM을 사용하는 이유는?

  • 통합성: NestJS는 TypeScript 기반의 프레임워크로, TypeORM은 TypeScript 및 JavaScript에서 사용할 수 있는 ORM입니다. 이 두 기술의 통합성이 높아, NestJS에서 TypeORM을 사용하면 일관된 개발 경험을 제공합니다.
  • 객체 지향 프로그래밍: TypeORM은 데이터베이스 테이블을 클래스로 모델링하여 객체 지향 프로그래밍을 가능하게 합니다. 
  • 강력한 쿼리 빌더: TypeORM은 쿼리 빌더를 제공하여 복잡한 쿼리를 직관적인 방식으로 작성할 수 있습니다. 이를 통해 SQL 쿼리를 직접 작성하지 않아도 되며, 코드의 가독성과 유지 관리성이 향상됩니다.
  • 데코레이터 및 메타데이터: TypeORM은 데코레이터를 활용하여 엔티티와 컬럼을 정의합니다. 이를 통해 코드의 간결함과 가독성을 유지하면서도 데이터베이스 스키마를 정의할 수 있습니다.
  • 마이그레이션 지원: TypeORM은 데이터베이스 스키마 변경을 안전하게 관리할 수 있는 마이그레이션 기능을 제공합니다. 이를 통해 팀원들과 협업하거나, 프로덕션 환경에서의 변경 사항을 안전하게 적용할 수 있습니다.
  • 다양한 데이터베이스 지원: TypeORM은 다양한 데이터베이스 시스템을 지원합니다. 이를 통해 여러 데이터베이스 시스템에 쉽게 대응하거나, 기존 데이터베이스와의 통합을 원활하게 진행할 수 있습니다.

NestJS에서 TypeORM을 사용하면 이러한 이점들을 활용하여 데이터베이스와의 상호 작용을 더욱 간편하게 처리할 수 있습니다. 또한, 코드의 일관성을 유지하면서도 유연하게 데이터베이스를 다룰 수 있어, 개발 효율성이 크게 향상됩니다.

 

🔨 mysql 설치하기

mysql이 설치되지 않으신 분은 아래의 글을 참조하여 설치하시기 바랍니다.

https://develop-const.tistory.com/20

 

Docker로 Mysql 쉽게 설치하기

Docker 다운로드하기 https://www.docker.com/ Docker: Accelerated, Containerized Application Development Docker is a platform designed to help developers build, share, and run modern applications. We handle the tedious setup, so you can focus on the co

develop-const.tistory.com

 

프로젝트 생성하기

NestJS CLI를 사용하여 새 프로젝트를 생성합니다.

nest new project-name

필요한 패키지 설치 

TypeORM 및 MySQL을 사용하려면 관련 패키지를 설치해야 합니다.   

npm install --save @nestjs/typeorm typeorm mysql2

typeorm설정하기

env파일로 빼도 되지만 간단한 실습을 위해 appModule에 바로 작성하겠습니다.

[ app.module.ts ]

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { BooksModule } from './books/books.module';
import { BookEntity } from './books/entities/book.entity';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '1234',
      database: 'test', 
      synchronize: true, 
    }), 
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule { }
  • TypeOrmModule.forRoot({ ... }): TypeORM 설정을 초기화합니다. forRoot() 메서드는 TypeORM 모듈을 초기화하는 데 필요한 설정 객체를 반환합니다.
  • type: 사용할 데이터베이스 종류를 지정합니다. 이 경우 mysql을 사용합니다.
  • host, port: 데이터베이스 서버의 호스트 이름과 포트 번호를 지정합니다.
  • username, password: 데이터베이스 서버에 로그인하기 위한 사용자 이름과 비밀번호를 지정합니다.
  • database: 사용할 데이터베이스 이름을 지정합니다.
  • entities: 사용할 엔티티 클래스를 지정합니다. 이 경우 BookEntity를 사용합니다.
  • synchronize: 엔티티와 데이터베이스 테이블을 자동으로 동기화할지 여부를 지정합니다. 이 경우 true로 설정하여 자동 동기화를 활성화합니다. 개발모드에서만 사용해야합니다.

books 파일 생성하기

NestJS CLI를 사용하여 BooksController, BooksService, BookEntity, CreateBookDto, UpdateBookDto와 같은 필수적인 파일들을 생성해줍니다.

nest g resourse books

 

[ app.module.ts ]

entities: [BookEntity]: TypeORM이 사용할 엔티티 클래스를 지정합니다. 이 경우 BookEntity 엔티티를 사용합니다.

BooksModule도 사용하기 위해 import 해줍니다.

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { BooksModule } from './books/books.module';
import { BookEntity } from './books/entities/book.entity';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '1234',
      database: 'test',
      entities: [BookEntity],
      synchronize: true, 
    }),
    BooksModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule { }

 

[ book.entity.ts ]

@Entity({ name: 'book' })
export class BookEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  author: string;

  @Column()
  name: string;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;

  @DeleteDateColumn()
  deletedAt: Date;

}
  • @Entity({ name: 'book' }): { name: 'book' } 옵션을 사용하여 테이블 이름을 지정할 수 있습니다.
  • @PrimaryGeneratedColumn(): id 필드를 정의하고, 자동으로 증가하는 기본키(primary key)를 설정합니다.
  • @Column(): author, name 필드를 정의합니다. @Column() 데코레이터를 사용하여 열(column)을 정의하고, 해당 필드의 데이터 타입을 지정합니다. 이 경우, author와 name 필드는 각각 string 타입입니다.
  • @CreateDateColumn(): 생성될 때 자동으로 생성일자(createdAt)를 기록합니다.
  • @UpdateDateColumn(): 업데이트될 때 자동으로 업데이트 일자(updatedAt)를 기록합니다.
  • @DeleteDateColumn(): 삭제될 때 자동으로 삭제 일자(deletedAt)를 기록합니다. 이렇게 하면 실제로 데이터를 삭제하지 않고, 삭제된 데이터를 추적할 수 있습니다.

이러한 방식으로 TypeORM을 사용하여 엔티티를 정의하면, 데이터베이스 테이블과 매핑되는 객체를 쉽게 생성하고, 데이터를 조작할 수 있습니다. TypeORM은 엔티티를 생성하고, 데이터를 조작하는 데 필요한 다양한 기능을 제공하기 때문에, 데이터베이스 작업을 보다 쉽게 수행할 수 있습니다. 

 

[ books.service.ts ]

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';

import { BookEntity } from './entities/book.entity';

@Injectable()
export class BooksService {
  constructor(@InjectRepository(BookEntity)
  private booksRepository: Repository<BookEntity>) { }

  async create(book: BookEntity): Promise<BookEntity> {
    const newBook = this.booksRepository.create(book);
    return await this.booksRepository.save(newBook);
  }

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

  async findOne(id: number): Promise<BookEntity> {
    return await this.booksRepository.findOne({
      where: {
        id
      }
    });
  }

  async update(id: number, book: BookEntity): Promise<number> {
    await this.booksRepository.update(id, book);
    return id
  }

  async remove(id: number): Promise<number> {
    await this.booksRepository.delete(id);
    return id
  }
}
  • @InjectRepository(BookEntity): BookEntity 엔티티를 사용하기 위해, booksRepository 멤버 변수에 TypeORM Repository 객체를 주입합니다. 이 객체는 데이터베이스 조작을 수행하기 위해 사용됩니다.
  • async create(book: BookEntity): Promise<BookEntity>:  book 매개변수는 생성할 책의 정보가 들어 있는 BookEntity 객체입니다. 이 메서드에서는 booksRepository.create()를 사용하여 새로운 엔티티 객체를 생성한 후, booksRepository.save()를 사용하여 데이터베이스에 저장합니다.
  • async findAll(): Promise<BookEntity[]>:  booksRepository.find()를 사용하여 데이터베이스에서 모든 책을 조회합니다.
  • async findOne(id: number): Promise<BookEntity>:  booksRepository.findOne()을 사용하여 데이터베이스에서 특정한 책을 조회합니다.
  • async update(id: number, book: BookEntity): Promise<number>:  booksRepository.update()를 사용하여 데이터베이스에서 특정한 책을 업데이트합니다.
  • async remove(id: number): Promise<number>:  booksRepository.delete()를 사용하여 데이터베이스에서 특정한 책을 삭제합니다.

 

[ books.controller.ts ]

books.controller.ts 파일은 HTTP 요청을 수신하고, BooksService를 호출하여 요청을 처리한 후, 클라이언트에게 응답을 반환하는 컨트롤러입니다.

@Controller('books')
export class BooksController {
  constructor(private booksService: BooksService) { }

  @Post()
  async create(@Body() book: BookEntity): Promise<BookEntity> {
    return await this.booksService.create(book);
  }

  @Get()
  async findAll(): Promise<BookEntity[]> {
    return this.booksService.findAll();
  }

  @Get(':id')
  async findOne(@Param('id') id: string): Promise<BookEntity> {
    return this.booksService.findOne(+id);
  }

  @Put(':id')
  async update(@Param('id') id: string, @Body() book: BookEntity): Promise<number> {
    return this.booksService.update(+id, book);
  }

  @Delete(':id')
  async remove(@Param('id') id: string): Promise<number> {
    return this.booksService.remove(+id);
  }
}

데코레이터에 대해 설명이 필요하다면 아래의글을 참고해주세요.

https://develop-const.tistory.com/6

 

NestJs controller에 대해 이해하기

컨트롤러란 HTTP 요청을 처리하고 클라이언트 응답에 반환하는 역할을 한다. 일반적으로 컨트롤러는 특정 URL 엔드포인트에 대한 요청을 처리하며, 이를 위해 데코레이터를 사용하여 연결된 메서

develop-const.tistory.com

 

[ books.module.ts ]

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

import { BooksService } from './books.service';
import { BooksController } from './books.controller';
import { BookEntity } from './entities/book.entity';


@Module({
  imports: [TypeOrmModule.forFeature([BookEntity])],
  controllers: [BooksController],
  providers: [BooksService]
})
export class BooksModule { }

TypeOrmModule.forFeature([BookEntity])TypeOrmModule에서 BookEntity 엔티티를 사용하기 위한 설정입니다.

 

postman을 사용한테스트

postman이 설치되어있지 않다면 아래의 사이트에 접속하셔서 다운받아주세요!

https://www.postman.com/

 

Postman API Platform | Sign Up for Free

Postman is an API platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs—faster.

www.postman.com

[ post ]

[ get ]

[ put ]

[ delete ]

 

다음 시간에는 typeorm을 사용하여 인증관련해서 다뤄보겠습니다.