Spring Data JPA에서는 두 엔티티 간의 다대다(Many-to-Many) 관계를 설정할 때 @ManyToMany 어노테이션을 사용한다. 이 관계를 설정할 때는 중간에 연결 테이블을 사용해 두 엔티티를 연결하는데, 이러한 개념은 알아도 실제로 적용하는 법을 모를 때가 종종 있다.
이번 포스트에서는 실제로 @ManyToMany와 @JoinTable 어노테이션을 사용하여 다대다 관계를 설정하는 방법과 작동 방식에 대해 설명해 보도록 하겠다.

☝️ 한 작가가 여러 책을 쓸 수 있고, 하나의 책에도 여러 작가가 존재할 수 있다.
다대다(Many-to-Many) 관계: 하나의 엔티티 인스턴스가 여러 엔티티 인스턴스와 연관되고, 반대로 여러 엔티티 인스턴스가 또 다른 엔티티 인스턴스와 연관되는 관계이다.
연결 테이블: 두 엔티티 간의 다대다 관계를 관리하기 위해 사용하는 중간 테이블이다.
ChatRoom 엔티티ChatRoom 엔티티는 채팅방을 나타내며, 여러 사용자가 참여할 수 있다.
@Entity
public class ChatRoom {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "chat_room_name", nullable = false, unique = true)
private String chatRoomName;
@ManyToMany
@JoinTable(
name = "user_chat_room",
joinColumns = @JoinColumn(name = "chat_room_id"),
inverseJoinColumns = @JoinColumn(name = "user_id")
)
private Set<User> users = new HashSet<>();
}
User 엔티티User 엔티티는 사용자를 나타내며, 여러 채팅방에 참여할 수 있습니다.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
@ManyToMany(mappedBy = "users") // "users"는 ChatRoom 엔티티에서 정의한 필드명
private Set<ChatRoom> chatRooms = new HashSet<>();
}
여기서는 예시를 위해 ChatRoom이라는 채팅방과 User라는 엔티티를 사용할 것이다. 사용자는 여러 채팅방에 참여할 수 있고, 하나의 채팅방에는 여러 유저가 들어올 수 있다.
다음으로는 여기서 사용된 어노테이션과 주요 속성에 대해 알아보자.
@JoinTable 어노테이션@JoinTable은 두 엔티티 간의 다대다 관계를 설정할 때 사용되는 연결 테이블 어노테이션이다. 이 어노테이션은 연결 테이블의 이름과 컬럼을 정의한다.
name: 연결 테이블의 이름을 지정한다.joinColumns: 현재 엔티티의 기본 키가 연결 테이블에서 어떤 컬럼과 매핑될지를 정의한다.inverseJoinColumns: 연관된 엔티티의 기본 키가 연결 테이블에서 어떤 컬럼과 매핑될지를 정의한다.@ManyToMany @JoinTable( name = "user_chat_room", // 연결 테이블의 이름 // ChatRoom 엔티티의 기본 키 joinColumns = @JoinColumn(name = "chat_room_id"), // User 엔티티의 기본 키 inverseJoinColumns = @JoinColumn(name = "user_id") ) private Set<User> users = new HashSet<>();
joinColumns은 ChatRoom 엔티티의 id와 연결 테이블의 chat_room_id를 매핑한다.inverseJoinColumns은 User 엔티티의 id와 연결 테이블의 user_id를 매핑한다.user_chat_room 연결 테이블| 컬럼명 | 데이터 타입 | 설명 |
|---|---|---|
chat_room_id | BIGINT | ChatRoom 테이블의 ID (외래키) |
user_id | BIGINT | User 테이블의 ID (외래키) |
연결 테이블 생성: JPA는 ChatRoom과 User 사이에 user_chat_room이라는 연결 테이블을 생성하여, 두 테이블 간의 관계를 관리한다.
컬럼 매핑: chat_room_id 컬럼은 ChatRoom 엔티티의 기본 키(id)와 연결되며, user_id 컬럼은 User 엔티티의 기본 키(id)와 연결된다.
양방향 연관: ChatRoom 엔티티는 users 필드를 통해 참여하는 사용자들을 참조하고, User 엔티티는 chatRooms 필드를 통해 참여하는 채팅방을 참조한다.
다대다, 일대다, 일대일 관계 등을 제대로 알긴 했지만 실제로 JPA에서 사용하려고 하면 순간 머뭇거릴 때가 있었다. 이 기회에 제대로 DB의 연결 관계에 대해서 공부하고, 더 익숙해지려고 한다. 특히 실전 경험이 중요한 만큼 열심히 이번 프로젝트에서 써봐야겠다!