[NestJS] - 7. TypeORM 데이터베이스 연동과 엔티티 매핑
이제 데이터베이스를 사용하기 위해서 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의 행위를 로깅할지의 여부 |
엔터티 클래스 작성
▶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문을 실행시키는 것을 확인할 수 있다.
다음 포스팅에서는 해당 테이블들의 관계를 설정하는 방법을 다루어볼 예정이다.
해당 강의를 들으면서 학습한 내용을 바탕으로 저만의 프로젝트를 만드는 과정을 기록하여 남기는 것을 목표로 하고 있습니다.
주관적인 생각이 들어가 있을 수 있으므로 혹시 틀린 내용이 있다면 피드백 부탁드립니다.
'Backend > Node.js (NestJS)' 카테고리의 다른 글
[NestJS] - 9. Pipe와 Validator, 요청 데이터 사전 검문하기 (0) | 2023.02.23 |
---|---|
[NestJS] - 8. 데이터베이스 관계와 TypeORM 데이터베이스 관계 매핑 (0) | 2023.02.22 |
[NestJS] - 6. 상품 REST API 만들기 (0) | 2023.02.09 |
[NestJS] - 5. 모듈 의존성 주입, 다른 모듈의 서비스를 사용해보자 (0) | 2023.02.09 |
[NestJS] - 4. DI / IoC (의존성 주입/제어의 역전) (0) | 2023.02.09 |