[NestJS] - 7. TypeORM 데이터베이스 연동과 엔티티 매핑

2023. 2. 22. 09:38
반응형

이제 데이터베이스를 사용하기 위해서 NestJS에 데이터베이스를 연동하고, TypeORM을 통해 연동하여 사용하는 방법을 포스팅해보려고 한다.

 


 

TypeORM이란?

 

ORM은 Object-relational-mapping의 약자로 소스코드의 클래스와 데이터베이스를 자동으로 매핑시켜주어 연결해준다.

즉 클래스 <-> 테이블 간의 연결을 자동으로 해준다.

 

Express에서 가장 많이 사용되는 ORM들 중에는 Sequelize와 TypeORM이 있다. Sequelize의 경우에도 타입스크립트를 지원하기는 하지만, 모델의 정의와 관계형성 면에서 TypeORM가 스타일에 잘 맞아서 사용할 ORM으로 선택하려고 한다.

 


데이터베이스 준비

 

TypeORM에서 사용할 데이터베이스를 선택하여야 한다. MySQL, MariaDB, PostgreSQL 등 요구사항에 적합한 데이터베이스 종류를 선택하여 직접 PC에 다운로드, 혹은 도커 컨테이너를 실행시켜서 개발 환경을 만들어주자.

 

필자는 MariaDB를 선택하였으며, 해당 데이터베이스를 기준으로 포스팅을 하려고 한다.

 


만들려고 하는 데이터베이스 구조

중고상품 거래를 할 수 있도록 상품을 게시판에 등록하고, 거래할 수 있는 플랫폼을 만든다고 가정한다.

Product 상품 테이블. 이름, 설명, 가격, 판매여부 등이 있으며, 나머지 네개의 테이블과 관계를 맺고 있음
ProductCategory 상품 카테고리 테이블. 카테고리 하나마다 여러개의 상품과 관계를 가질 수 있는 N:1 관계
ProductSalesLocation 상품 거래 장소. 상품 하나당 상품 거래 장소 하나의 관계를 가지는 1:1 관계
ProductTag 상품 태그. 상품은 여러개의 태그를, 태그는 여러개의 상품과 관계를 맺을 수 잇는 N:M 관계
User 회원. 이메일, 패스워드 등 인증정보 포함. 상품과 1:N 관계

 

 

우선적으로 관계를 제외하고 테이블들을 ORM을 사용하여 생성해보려고 한다.


TypeORM 연결

 

패키지 설치

yarn add @nestjs/typeorm typeorm@0.2 mysql2

 

▶ app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ProductsModule } from './apis/products/products.module';

@Module({
  imports: [
	// ...
    TypeOrmModule.forRoot({
      type: 'mariadb',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '1111',
      database: 'my-database',
      entities: [__dirname + '/apis/**/*.entity.*'],
      synchronize: true,
      logging: true,
    }),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

app.module.ts 안에 TypeORM 사용을 위해서 모듈을 import시킨다.

type 사용할 데이터베이스 종류
host 데이터베이스 호스트
port 데이터베이스 포트
username 데이터베이스 유저 이름
password 데이터베이스 패스워드
database 데이터베이스명
entities 데이터베이스 엔티티 구조로 매핑시킬 모델들을 작성한다. 다음과 같이 사용할 시 apis 내부의 .entity.가 포함된 모든 파일들을 사용하게 된다.
synchronize 엔티티와 모델을 동기화시킬지의 여부. 모델이 변경될 시 데이터베이스 엔티티가 자동으로 변경된다.
logging 콘솔에 TypeORM의 행위를 로깅할지의 여부

엔터티 클래스 작성

 

모듈 구조 안에 entities 폴더 안에 product.entity.ts 생성

 

▶product.entity.ts

import {
  Column,
  DeleteDateColumn,
  Entity,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from 'typeorm';

@Entity()
export class Product {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  name: string;

  @Column()
  description: string;

  @Column()
  price: number;

  @Column({ default: false })
  isSoldOut: boolean;

  @DeleteDateColumn() //TypeORM 제공 삭제여부 타임스탬프
  deletedAt: Date;

  @UpdateDateColumn() //TypeORM 제공 삭제여부 타임스탬프
  updatedAt: Date;
}

Product 테이블을 만들기 위한 TypeORM 모델을 만들어보았다.

- 기본적으로 Class로 생성

- @Entity() 데코레이터를 붙여야 ORM의 매핑 대상이라고 인지한다.

- 클래스 안에는 테이블의 컬럼들을 작성하며 @Column() 데코레이터를 붙여준다.

- @Column()은 디폴트 값으로 사용할 시에는 Typescript 기반으로 ORM이 적절한 자료형으로 데이터베이스와 매핑시켜준다.

- @Column()에 다양한 옵션을 추가할 수도 있다. description의 경우 옵션을 명시하지 않으면 varchar(255)로 ORM이 매핑시켜 테이블을 구성하는데 longtext를 사용하고 싶어서 추가해주었다.

- 마찬가지로 isSoldOut의 경우에도 디폴트값을 사용하고 싶어서 옵션을 작성하였다.

- @PrimaryGeneratedColumn()은 Primary Key라는 것을 명시해주며, 인수로는 포멧을 지정하며 auto_increment(1,2,3...), uuid(고유 문자열) 등을 사용할 수 있다.

- @DeleteDateColumn(), UpdateDateColum(), CreateDateColumn() 데코레이터로 자동 타임스탬프 컬럼을 추가할 수 있다.

 

 

 

▶user.entity.ts

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

@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  email: string;

  @Column()
  password: string;

  @Column()
  name: string;

  @Column()
  age: number;

  @Column({ default: 0 })
  point: number;
}

 

 

▶productSalesLocation.entity.ts

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

@Entity()
export class ProductSalesLocation {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  address: string;

  @Column()
  addressDetail: string;

  @Column({ type: 'decimal' })
  lat: number; //위도

  @Column({ type: 'decimal' })
  lng: number; //경도

  @Column()
  meetingTime: Date;
}

 

 

▶productCategory.entity.ts

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

@Entity()
export class ProductCategory {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  name: string;
}

 

 

▶productTags.entity.ts

import { Product } from 'src/apis/products/entities/product.entity';
import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class ProductTag {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ unique: true })
  name: string;
}

여기까지 마치고 프로젝트를 실행시키면 데이터베이스에 ORM을 통해서 테이블들이 자동 매핑되어 생성되는 것을 확인할 수 있다.

 

실제로 로그를 보면 ORM이 클래스로 작성한 엔터티 모델을 기반으로 SQL문을 실행시키는 것을 확인할 수 있다.

 

생성된 데이터베이스 엔티티

 

다음 포스팅에서는 해당 테이블들의 관계를 설정하는 방법을 다루어볼 예정이다.

 

 

 

 

 


해당 강의를 들으면서 학습한 내용을 바탕으로 저만의 프로젝트를 만드는 과정을 기록하여 남기는 것을 목표로 하고 있습니다.

주관적인 생각이 들어가 있을 수 있으므로 혹시 틀린 내용이 있다면 피드백 부탁드립니다.

https://www.inflearn.com/course/%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%A0%EB%86%8D%EC%B6%95-%EC%BD%94%EC%8A%A4/dashboard

 

[인프런x코드캠프] 부트캠프에서 만든 고농축 백엔드 코스 - 인프런 | 강의

코딩과 사랑에 빠져버린 8년차 풀스택 개발자 Captain의 사심이 가득 담긴 커리큘럼이에요. 백엔드의 모든 것을 다 알려주고 싶은 Captain의 마음이 녹아있죠! 이 강의를 듣다보면 '이렇게까지 알려

www.inflearn.com

 

반응형

BELATED ARTICLES

more