Spring/Spring Jpa

@ManyToMany를 사용하면 안 되는 이유

윤밥밥 2024. 10. 15. 20:14

@ManyToMany 를 실무에서 사용하면 안된다는 얘기를 많이 들었고, 그래서 항상 관계를 풀어서 사용했었다.

이번에 다시 관계를 풀어 사용하면서 왜 풀어야하나 생각해보니 답이 떠오르지 않아 이를 정리해본다.


@ManyToMany


@Entity
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToMany
    @JoinTable(
        name = "student_course"  // 중간 테이블의 이름
    )
    private List<Course> courses = new ArrayList<>();

    // 기본 생성자, getter/setter 생략
}

@Entity
public class Course {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @ManyToMany(mappedBy = "courses")  // Student 엔티티에서의 관계를 매핑
    private List<Student> students = new ArrayList<>();

    // 기본 생성자, getter/setter 생략
}

@ManyToMany 를 사용하면, Jpa가 자동으로 중간 테이블을 생성해준다.

따라서 @OneToMany , @ManyToOne 을 통해 중간테이블 클래스를 직접 만들어 사용하는 것과 동일한 결과를 얻을 수도 있다.

그럼 왜 @ManyToMany 를 사용하면 안될까?


@ManyToMany를 사용하면 안되는 이유


1. 중간 테이블에 추가 데이터를 추가할 수 없다.

@ManyToMany 를 사용하면, JPA가 중간 테이블을 자동으로 생성해주고 쿼리문도 알아서 처리해준다.

중간 테이블을 개발자가 설정할 수 없게 되므로, 중간 테이블에 추가 정보(생성일, 상태 등)을 저장할 수 없다.

 

2. 인덱싱을 할 수 없다.

@ManyToMany 의 경우 조회 시 다음과 같이 join이 많아져 성능이 저하될 수 있다.

SELECT s.id, s.name, c.title
FROM student s
JOIN student_course sc ON s.id = sc.student_id
JOIN course c ON sc.course_id = c.id

성능이 좋지 못 한 경우, 중간 테이블에 대해 인덱싱을 통해 어느 정도 성능을 개선할 수 있지만, @ManyToMany 의 경우 중간 테이블에 대해 설정할 수 없으므로 개선이 불가능해진다.

(예를 들어 특정 학생이 수강하는 모든 강의를 조회한다고 하면, 중간 테이블 학생 외래키에 인덱싱을 걸면 더 빠르게 데이터를 찾을 수 있다.)