[JPA] 양방향 매핑

ttaho·2023년 12월 14일
0

JPA

목록 보기
4/7

이번엔 JPA의 양방향 매핑에 대해 알아보자

양방향 매핑의 필요성

저번 글에서 Member에서 Team을 조회하는 경우 N:1로 단방향으로 매핑 시켰다고 했다.
만약, Team 객체 에서 해당하는 Team에 소속된 Member들을 모두 조회해야하는 경우에 Team 객체 에서도 연관관계를 걸어줘야 한다. 이때의 연관관계를 양방향 연관관계라고 한다.

객체 및 테이블 모델링

N:1 양방향 관계를 이해하기 위해 Member와 Team의 관계를 살펴보자.

  • 회원은 하나의 팀에만 소속된다.
  • 다수의 회원은 하나의 팀에 소속된다.
  • 회원과 팀은 N:1의 관계이다.

해당 관계를 보면 기존의 N:1 단방향 관계와 다를 것이 없다.
왜냐하면 데이터베이스는 방향 이라는 것이 없기 때문이다
그저 외래키를 사용하여 두 테이블을 Join 시켜 내가 원하는 테이블의 데이터를 조회할 수 있다.

해당 사실을 바탕으로 다시 우리가 원하는 것을 생각해보면 총 두 가지이다.
1. 회원(Member) 객체에서 팀(Team)객체를 조회할 수 있어야 한다.
2. 팀(Team) 객체에서 회원(Member)객체 목록을 조회할 수 있어야 한다.

이것을 모델링한 객체 와 테이블 결과는 아래와 같다.

이에 맞게 Member 객체와 Team 객체를 만들어보자.

양방향 객체 연관관계 매핑

회원(Member)

위의 회원(Member) 클래스의 코드는 단방향 매핑때와 일치하다.

팀(Team)

위의 코드는 Team 엔티티에 members라는 필드가 추가되었다.
단뱡향 매핑과는 다르게 @OneToMany 어노테이션을 추가하여 연관관계를 걸어주었다.

@OneToMany 어노테이션의 mappedBy 속성은 양방향 매핑일 때 사용하며, 반대쪽 매핑의 필드 이름값으로 설정한다. 이것은 연관관계의 주인을 설정하기 위한 것이다.

여기서 의문점이 하나 생긴다.

어떤건 @JoinColumn 쓰고, 어떤건 안쓰고 뭐지?
또, Member에서는 @JoinColumn을 걸어줬는데 Team에서는 안쓰네?

이것을 이해하기 위해 먼저, 객체와 테이블이 관계를 맺는 차이를 살펴보자.

객체와 테이블이 관계를 맺는 차이

양방향 연관관계 시 객체와 테이블은 다르다!

  • 객체 연관관계 = 2개
    • 회원 -> 팀 연관관계 1개(단방향)
    • 팀 -> 회원 연관관계 1개(단방향)
  • 테이블 연관관계 = 1개
    • 회원 <--> 팀의 연관관계 1개(양방향)

테이블은 외래키(FK)로 다른 테이블과 Join 시키면 다른 테이블의 정보도 알 수 있다. 그러므로 연관관계를 1개만 걸어주면 된다.
하지만 객체의 연관관계에서는 각각의 객체마다 참조를 걸어줘야 하므로 총 2개의 연관관계를 걸어줘야 한다. 이것을 우리는 양방향 연관관계라고 부른다.

여기서 나는 두 객체에서 어떤 것으로 매핑을 해야하지?라는 의문이 생긴다.

아래의 객체 연관관계를 보자.

상황을 가정해보자.

한 회원(Member)의 팀을 바꿔야 한다.
팀을 바꾸면 그림의 아래에 있는 Member 테이블의 외래키인 TEAM_ID를 업데이트 해야한다.
이 업데이트 작업을 Member 객체의 team으로 해야되는가?
아니면 TEAM 객체의 members 로 해야되는가?

단뱡향 이었을때는 당연히 회원(Member)객체에서 팀(Team)을 참조하므로 이 팀(Team)만 연관관계 매핑을 하면 되지만,
양방향인 경우에는 팀(Team) 객체의 members도 신경을 써야 하므로 어떻게 해야할지 난감하다.

결론은 둘 중 하나로 주인을 정해서 외래 키를 관리해야 한다는 것이다. 이것이 연관관계의 주인이다.

연관관계 주인

양방향 매핑 규칙

  • 객체의 두 관계중 하나를 연관관계의 주인으로 지정
  • 연관관계의 주인만이 외래 키를 관리(등록, 수정)
  • 주인이 아닌쪽은 읽기만 가능
  • 주인은 mappedBy 속성 사용X
  • 주인이 아니면 mappedBy 속성으로 주인 지정

우리의 예시인 회원(Member)와 팀(Team)의 경우에는 외래키가 있는 곳인 회원이 주인이다.

팀(Team) 객체에서 @OneToMany 어노테이션의 mappedBy 속성으로 회원(Member) 객체의 team 필드와 연관관계를 정의해 주었다.

양방향 연관관계 주의점

  • 순수 객체 상태를 고려해서 항상 양쪽에 값을 설정하자
  • 연관관계 편의 메소드를 생성하자
  • 양방향 매핑시에 무한 루프를 조심하자
    • 예 : toString(), lombok, JSON 생성 라이브러리

양방향 매핑 정리

  • 단방향 매핑만으로도 이미 연관관계 매핑은 완료
  • 양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 추가된 것 뿐이다.
  • JPQL에서 역방향으로 탐색할 일이 많다.
  • 단방향 매핑을 잘 하고 양방향은 필요할 때만 추가해도 됨(테이블에 영향을 주지 않음)
  • 비즈니스 로직을 기준으로 연관관계의 주인을 선택하면 안됨
  • 연관관계의 주인은 외래 키의 위치를 기준으로 정해야함
profile
백엔드 꿈나무

0개의 댓글