지난 주에 팀원들과 함께 설정한 ERD를 토대로 오늘은 Entity를 설정하였다.
TypeORM을 사용하여 postgresql을 연결하였고, 엔티티 클래스들을 잘 정의하였다.
가장 신경 쓴 건 일대다 관계와 cascade 설정이었다.
데이터베이스에서 관계 설정을 하지 않으면 많은 공간의 낭비가 발생한다. 관계 설정을 하게 된다면 공간의 낭비를 해결할 수 있을 뿐아니라 성능도 증가하게 된다.
위의 관계의 예시로는 블로그 사용자와 그 사용자가 올린 게시물들을 들 수 있다.
한명의 블로그 사용자는 여러개의 게시물을 가질 수 있다. 즉, 일대다 관계에서 '일'은 사용자를, '다'는 게시물에 해당한다.
nestJS에서는 TypeORM으로 관계를 설정할 수 있다. @OneToMany와 @ManyToOne이라는 데코레이터를 사용하여 관계를 가질 칼럼 위에 지정한다. 예를 들어 TypeORM docs에 있는 코드를 살펴보자.
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm"
import { User } from "./User"
@Entity()
export class Photo {
@PrimaryGeneratedColumn()
id: number
@Column()
url: string
@ManyToOne(() => User, (user) => user.photos)
user: User
}
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm"
import { Photo } from "./Photo"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@OneToMany(() => Photo, (photo) => photo.user)
photos: Photo[]
}
이처럼 양쪽에 일대다, 다대일 관계를 설정해줌으로써 엔티티간 관계를 설정할 수 있음을 직관적으로 확인할 수 있다.
이해하는데 어려움을 겪었던 것은 데코레이터 안에 있는 것들이다. 데코레이터는 필수로 2개의 인자를 받아야한다. 첫번째는 타겟 엔티티 클래스를 반환하는 함수를, 두번째는 타겟 엔티티 내에서 연결할 필드를 지정하는 함수를 받아야한다. 두번째에서 지정한 것은 주로 반대쪽 관계(현재 클래스에서 @OneToMany라면 @ManyToOne을 지정한 필드)를 지정해야한다.
@OneToMany에서는 여러개의 값을 가지기 때문에 해당 클래스 타입으로 구성된 리스트를 필드의 타입으로 지정한다.
@JoinColumn()도 지정하면 외래키를 지정할 수 있다. ManyToOne() 쪽에 지정하여 Id를 붙여준다. 예를 들면, 위의 코드에서 @JoinColumn()을 붙이면, userId라는 필드가 엔티티 상에서 생성된다.
cascade는 부모엔티티에서 이루어지는 save, insert, remove 등에 의해 연결된 자식엔티티의 레코드를 자동적으로 관리해주는 옵션이다.
전에 했었던 프로젝트들에서는 이를 설정하지 않았지만 이번에는 비즈니스 서비스이기 때문에 이 옵션을 true로 하였다.
cascade 옵션은 일대다 중 일에 줘야하기 때문에 @OneToMany를 지정한 필드에다가 추가해야한다.