제로초 Nest.js 강의를 듣고 있다.
슬랙 클론인데 TypeORM 관계 설정 부분에서 약간 헷갈리는 것들을 정리해볼까 한다.
일대다, 다대일은 흔히 관계형 데이터베이스에서 알고 있는 내용이다.
다만 ORM 이 기존 MySQL 에 비해 설정하는 것이 약간 헷갈려서 정리해본다.
하나의 워크스페이스에는 여러 채널(슬랙을 써봤다면 하나의 워크스페이스 안에 슬랙 채널들을 생각해보자)을 가질 수 있다. One to Many
// Workspaces.ts
export class Workspaces {
@OneToMany(() => Channels, (channels) => channels.Workspace)
Channels: Channels[];
}
워크스페이스 기준으로
첫번째 파라미터에 Many 인 채널 클래스를 리턴해 내보내주는 화살표 함수,
두번째 파라미터에 가져온 채널 모델에서 관계 설정에 사용 중인 Row Name 인 channels.Workspace 를 리턴
------------------------------
// Channels.ts
export class Channels {
@ManyToOne(() => Workspaces, (workspaces) => workspaces.Channels, {
onDelete: 'SET NULL',
onUpdate: 'CASCADE',
})
@JoinColumn([{ name: 'WorkspaceId', referencedColumnName: 'id' }])
Workspace: Workspaces;
}
채널 기준으로
첫번째 파라미터에 One 인 워크스페이스 클래스를 리턴,
두번째 파라미터에 가져온 워크스페이스 클래스에서 관계 설정에 사용 중인 workspaces.Channels 를 리턴
세번째 파라미터에 삭제나 업데이트시 옵션을 추가
조인 칼럼에서 Channels 에 있는 컬럼인 WorkspaceId 와
Workspace 테이블의 id 를 referencedColumnName 으로 정하게 됩니다.
Workspace: Workspaces;
당연히 조인 칼럼 설정이 foreign key 가 있는 Channels 테이블 쪽에 있어야 합니다.

이부분이 조금 헷갈릴 수 있는 부분이라고 생각했습니다.
정리하면, 두개의 테이블이 서로 MTM 관계라면 중간 테이블이 생길 수 밖에 없습니다. 이 중간 테이블을 One To Many 로 각각 연결 시켜주면 해결됩니다.
TypeORM 에서는 기본적으로 Many To Many 를 지원해 중간 테이블을 생성할 필요가 없다고 하지만 과정 중에 생기는 에러를 잡기 힘들기 때문에 ManyToMany decorator 를 걸어주고 동시에 중간 테이블을 직접 만들어 관계를 설정해줍니다.
아래 코드 Channels 클래스의 @ManyToMany 를 보면 Users 와 관계를 설정해주고 있습니다.
Channels 테이블에서는 Members 컬럼을 사용하여 Users 테이블의 Channels 컬럼으로 해당 관계를 이어주고 있습니다.

아래 코드 Users 클래스에서는 Channels 컬럼 이름을 사용하고 @JoinTable 데코레이터 을 통해
channelmembers 테이블을 사용해 조인 컬럼과 인버스 조인 컬럼을 설정해주고 있습니다.
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToMany,
JoinTable,
} from "typeorm"
import { Category } from "./Category"
@Entity()
export class Question {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column()
text: string
@ManyToMany(() => Category)
// JoinTable() 메서드 파라미터에 아무것도 없으면 중간 테이블을 직접 만든게 아니다.
@JoinTable()
categories: Category[]
}

ChannelMembers 클래스에서는 Channel, User 컬럼을 이용한다.
Channels 클래스에서 ChannelMembers 컬럼
Users 클래스에서 ChannelMembers 컬럼
channels.ChannelMembers, users.ChannelMembers
