본문 바로가기
DB/typeORM

TypeORM 다대다 연결 시 관계테이블 이름 커스텀하기

by 싯벨트 2025. 1. 18.
728x90

TypeORM 다대다 연결

TypeORM을 통한 다대다 연결을 구성하는 방법을 정리해보겠습니다. 공식문서(many-to-many relations)에 있는 예시를 통해 개략적인 기능을 설명하고, 옵션을 통해 저장되는 테이블명과 컬럼명을 커스텀하는 것도 설명해보겠습니다.

기본 설정

// category.ts
@Entity()
export class Category {
    @PrimaryGeneratedColumn()
    id: number

    @Column()
    name: string
}

// questioin.ts
@Entity()
export class Question {
    @PrimaryGeneratedColumn()
    id: number

    @Column()
    title: string

    @Column()
    text: string

    @ManyToMany(() => Category)
    @JoinTable()
    categories: Category[]
}

Category, Question 두 엔티티로 구성된 케이스를 살펴보겠습니다. 먼저, @ManyToMany() 데코레이터와 @JoinTable() 을 어느곳이든 무조건 적어줘야 합니다. 그러면 두 엔티티의 아이디를 연결하는 관계 테이블이 생성됩니다. 관계 테이블의 이름은 @JoinTable() 데코가 있는 테이블명 + 컬럼명 + 데코가 없는 테이블명 으로 구성됩니다. 그리고 각 테이블의 primaryColumn이 테이블명과 합쳐져서 카멜케이스로 컬럼명이 형성됩니다. 예시처럼 구성된 코드에서는 다음과 같은 테이블이 형성됩니다.

+-------------+--------------+----------------------------+
|              question_categories_category               |
+-------------+--------------+----------------------------+
| questionId  | int(11)      | PRIMARY KEY FOREIGN KEY    |
| categoryId  | int(11)      | PRIMARY KEY FOREIGN KEY    |
+-------------+--------------+----------------------------+

cascade 설정을 해주면 연결된 엔티티의 저장과 삭제도 가능합니다. 이때는 디렉션 설정을 해줘야 합니다. 양방향을 원하면 양쪽에도 할 수 있습니다. 연결된 엔티티의 삭제를 원할 경우, find 메서드를 실행했을 때 relation으로 다대다 관계를 형성한 엔티티의 데이터도 가지고 온 다음 삭제를 해야 합니다. 아래처럼 설정을 하면 Question을 저장, 삭제할 때 연결된 Category도 삭제됩니다.

@Entity()
export class Question {
    @PrimaryGeneratedColumn()
    id: number

    @ManyToMany(() => Category, (category) => category.questions, {
        cascade: true,
    })
    @JoinTable()
    categories: Category[]
}

관계테이블명, 컬럼명 커스텀

커스텀 하는 방법을 살펴보겠습니다. @JoinTable() 옵션을 활용해서 테이블명과 컬럼명을 설정할 수 있습니다. 디비에 저장을 카멜케이스가 아니라 스네이크케이스로 저장을 하고 있다면, 테이블 명을 다음처럼 설정할 수 있습니다.

@Entity()
export class Question {
    @PrimaryGeneratedColumn()
    id: number

    @ManyToMany(() => Category, (category) => category.questions, {
        cascade: true,
    })
    @JoinTable({
        name: "table_question_categry",
        joinColumn: { name: "question_id" },
        inverseJoinColumn: { name: "categry_id" },
    })
    categories: Category[]
}