TypeORM 에 대해.. ( feat.Nest.js)

Knoa·2023년 12월 23일

제로초 Nest.js 강의를 듣고 있다.
슬랙 클론인데 TypeORM 관계 설정 부분에서 약간 헷갈리는 것들을 정리해볼까 한다.

OneToMany, ManyToOne

일대다, 다대일은 흔히 관계형 데이터베이스에서 알고 있는 내용이다.
다만 ORM 이 기존 MySQL 에 비해 설정하는 것이 약간 헷갈려서 정리해본다.

Workspaces 와 Channels 의 관계

하나의 워크스페이스에는 여러 채널(슬랙을 써봤다면 하나의 워크스페이스 안에 슬랙 채널들을 생각해보자)을 가질 수 있다. 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 테이블 쪽에 있어야 합니다.

Many To Many

이부분이 조금 헷갈릴 수 있는 부분이라고 생각했습니다.

정리하면, 두개의 테이블이 서로 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

profile
SW 개발자

0개의 댓글