본문 바로가기

연재작/WEB - BE

Nest.js과 TypeORM

 

 

TypeORM에서 Entity의 사용은 JPA와 흡사해 보여서 쓰면서 적응하면 될 것 같기는 하다.

 

https://docs.nestjs.com/recipes/sql-typeorm

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Rea

docs.nestjs.com

일단 적용은 위처럼 공식문서에서 다루고 있다.
보면 @Configuration이나 @Bean을 통해서 DataSource를 관리하는 방식과 
비슷하게 다음처럼 적용하면 된다.

import { DataSource } from 'typeorm';

export const databaseProviders = [
  {
    provide: 'DATA_SOURCE',
    useFactory: async () => {
      const dataSource = new DataSource({
        type: 'mysql',
        host: 'localhost',
        port: 33067,
        username: 'root',
        password: 'root',
        database: 'test',
        entities: [
        'dist/**/*.entity{.ts,.js}'
        // 처음 init할 때는 __dirname + '/../**/*.entity{.ts,.js}'를 사용하라는데,
        // npm run start를 할 때 dist에 있는 build 파일 기반으로 실행되기에,
        // __dirname을 설정하거나 나처럼 직접적으로 dist를 지정해주어야 한다.
        ],
        synchronize: true,
        // 참고로 이 속성이 hibernate의 auto-ddl과 같은 속성이다.
      });

      return dataSource.initialize();
    },
  },
];

 

내가 써야할 부분은 BaseEntity를 통한 공통 Entity 설정과 관련된 것이었다.

이에 대한 내용은 아래의 공식 문서에서 사용법을 확인이 가능하다.

https://typeorm.io/entity-inheritance

 

참고로 typeorm에는 이미 BaseEntity라는 class가 있는데, 

https://typeorm.delightful.studio/classes/_repository_baseentity_.baseentity

 

BaseEntity | typeorm

 

typeorm.delightful.studio

이에 대해서 잠깐만 설명하자면 다음과 같다.

 

Active Record vs Data Mapper

  • Active Record : TypeORM에서 기본적으로 제공해주는 메서드들이 내장되어 있고, 이를 사용할 수 있다.
    Spring Data JPA의 기본 쿼리 메서드들이
    BaseEntity에 정의되어 있다고 보면 된다.
    이를 통해서 Repository에서의 관리 없이, EntityManager없이
    해당 메서드들 만으로 기본적인 사용이 가능하다.
    + QueryBuilder를 통해서 동적인 메서드 구현도 가능하니
    다양한 방식으로 사용이 가능하다
  • Data Mapper : Spring Data JPA에서 자주 사용하던 그 패턴이다.

 

내가 BaseEntity에서 원하는 것은 id, createdAt, deletedAt과

같은 기본적인 column의 구성이므로 BaseEntity를 사용하지는 않겠다.

(혹은 BaseEntity를 extends해서 CustomBaseEntity를 만들고 내가 원하는 컬럼을 집어넣는 방식도 좋아보인다.)

 

import {
	CreateDateColumn,
	DeleteDateColumn,
	PrimaryGeneratedColumn,
	UpdateDateColumn,
} from 'typeorm';

export abstract class CustomBaseEntity {
	@PrimaryGeneratedColumn()
	id: number;

	@CreateDateColumn()
	createdAt: Date;

	@UpdateDateColumn()
	updatedAt: Date;

	@DeleteDateColumn()
	deletedAt: Date; // typeORM에서는 이 값이 있는지를 판단해서 soft delete를 결정
}

 

위와 같은 방식으로 CustomBaseEntity를 설정하고

nest g resource

를 통해서 CRUD 관련 세팅을 미리 해준 후, user.entity.ts에 아래처럼 엔티티를 등록해주자.

import { CustomBaseEntity } from '@/common/CustomBaseEntity.entity';
import { Column, Entity } from 'typeorm';

@Entity()
export class User extends CustomBaseEntity {
	@Column()
	username: string;

	@Column()
	password: string;

	@Column()
	nickname: string;
}

 

그러면 다음과 같이 DDL 수행되어 Table 생성이 되는 것을 볼 수 있다!

 

 

그러면 이제 여러 테이블 간의 연관 관계 설정까지 알아보자.

https://typeorm.io/many-to-one-one-to-many-relations

공식 문서는 위를 참조하자.

 

우선 user가 글을 사용할 Post 엔티티이다.

나는 ID 기반으로 엔티티 관리를 하고 싶기 때문에 다음처럼 id와 entity를 같이 넣어 줄 것이다.

 

import { CustomBaseEntity } from '@/common/CustomBaseEntity.entity';
import { User } from '@/user/entities/user.entity';
import { Column, Entity, ManyToOne, RelationId } from 'typeorm';

@Entity()
export class Post extends CustomBaseEntity {
	@ManyToOne(() => User, { nullable: false })
	user: User;

	@RelationId((post: Post) => post.user)
	userId: number;

	@Column()
	postTitle: string;

	@Column('text')
	postContent: string;

	@Column()
	postVoteCount: number;

	@Column()
	postCommentCount: number;

	@Column()
	isDraft: boolean;
}

@ManyToOne 데코레이터는 JPA와 동일하나, 넣는 속성 값이 조금 JS스럽다 (함수형 프로그래밍스럽다+ JSON)

 

이처럼 Table형성이 되고,

참고로 JPA의 경우 ID의 경우는 알아서 long 타입을 넣어줬는데
지금은 int 타입으로 들어가고 있기에 다음과 같이 BaseEntity의 id 속성을 수정해주자.

	@PrimaryGeneratedColumn({ type: 'bigint' })
	id: number;

 

만약 실제 운영환경에서의 DB라면 이런식으로 entity 설정이 alter나 drop이 일어나도록 해두지도 않고,

DB스키마는 직접 DB 접근을 통해 이루겠지만, 지금은 테스트 환경이므로 이렇게 해두고

나중에 운영환경 만들때 설정해주자

 

https://typeorm.io/active-record-data-mapper

https://typeorm.io/

 

TypeORM - Amazing ORM for TypeScript and JavaScript (ES7, ES6, ES5). Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server,

 

typeorm.io

 

'연재작 > WEB - BE' 카테고리의 다른 글

Spring Boot와 비교해보는 Nest.js의 핵심  (0) 2025.02.13
Spring 개발자의 Nest.js 초입  (1) 2025.02.11
Spring과 Spring Boot  (1) 2024.12.03
Spring Bean Deep Dive  (0) 2024.12.02
디렉토리 구조와 Facade 패턴  (1) 2024.11.19