김코딩

JPA - 연관관계 편의 메서드 본문

스프링

JPA - 연관관계 편의 메서드

김코딩딩 2025. 6. 27. 11:52

JPA 공부를 하다보면 자꾸 연관관계 편의 메서드에 대해서 이야기가 나온다...

코드를 보면서 아 그렇구나 하고 넘어가는데, 정확히 이해가 가지 않아서 블로그로 한번 글을 정리해보려고 작성했다.


연관관계 편의 메서드란?

연관관계 편의 메서드
양방향 연관관계에서 두 객체 간의 관계를 한 번에 동기화해주는 메서드입니다.
"둘이 사귀기로 했는데, 한쪽만 사귀는걸 알고 있으면 진짜 사귀는 걸까요..?"

예를 들어, 철수가 영희에게 "우리 사귀자!" 하고 혼자서만 사귀는 줄 알고 있다고 해봅시다.
하지만 영희는 아무 말도 안 들었고, 아무 생각도 없어요.

이 상황, 과연 사귀는 게 맞을까요…?

-> 아니죠. 둘 다 서로 사귀고 있다고 인식해야 관계가 성립하는 겁니다.

 

JPA의 양방향 연관관계도 똑같습니다.

예를 들어, Member와 Team 엔티티가 있고, 둘이 양방향 매핑이 되어있다고 가정해보겠습니다.

  • Member 가 Team을 참조하고 있어도
  • Team이 그 Member를 members 리스트에 넣어주지 않으면 관계가 불완전하게 연결된 것 입니다!

아래에서 예제를 가지고 설명해드리겠습니다.


도메인 설정

@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;
    private String username;
    private int age;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;
}
@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Team {

    @Id
    @GeneratedValue
    @Column(name = "team_id")
    private Long id;
    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();
}

 

  • 현재 Member와 Team은 양방향 매핑이 되어있습니다.
  • 연관관계의 주인은 mappedBy가 가리키는 Member 엔터티의 team 필드가 연관관계의 주인입니다.

왜 연관관계 편의 메서드가 필요할까?

아래와 같이 Member 와 Team 객체를 생성하고, member.setTeam(team) 만 호출하게 된다면 어떤 일이 벌어지는지 확인해보겠습니다. (테스트 환경에서 진행하였습니다.)

 

연관관계 편의 메서드를 사용하지 않을 때

class MemberTest {

    @Test
    void 연관관계_편의_메서드_없이_연관_설정_시_양방향_불일치_발생() {
        // given
        Member member = new Member();
        Team team = new Team();

        // when
        member.setTeam(team); // member의 team에만 설정

        Assertions.assertThat(member.getTeam()).isEqualTo(team);
        Assertions.assertThat(team.getMembers()).doesNotContain(member);
    }
}

 

 

 

 

테스트가 통과하였습니다. 그 말은 즉슨, Member에는 team이 들어있지만 현재 Team에는 Member가 들어있지 않다는 것을 의미합니다.

 

이제 Member 엔티티 즉, 연관관계의 주인이 있는 엔티티에 연관관계 편의 메서드인 chageTeam 메서드를 만들고 다시 테스트를 진행해보겠습니다.

@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;
    private String username;
    private int age;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;
    
    public void changeTeam(Team team) {
    this.team = team;
    team.getMembers().add(this);
    }
}

 

연관관계 편의 메서드를 사용할 때

@Test
void 연관관계_편의_메서드를_사용하면_양방향_정상_연결됨() {
    // given
    Member member = new Member();
    Team team = new Team();

    // when
    member.changeTeam(team);

    Assertions.assertThat(member.getTeam()).isEqualTo(team);
    Assertions.assertThat(team.getMembers()).contains(member);
}

테스트가 통과하는 것을 확인할 수 있습니다. 이제 Member에 Team을 설정하면 자동으로 Team에 Member도 설정해주는 양방향 매핑이 잘 이루어진 것을 알 수 있습니다.


연관관계 편의 메서드가 없다면?

  • 양쪽 상태가 불일치하여 메모리상 관계가 엉켜버립니다.
  • JPA가 flush/commit 시점에 관계 상태를 제대로 파악하지 못해, 예상치 못한 쿼리가 발생하거나 데이터가 누락될 수 있습니다.
  • 화면에 데이터를 조회할 때도 관계가 올바르게 표현되지 않아 사용자에게 잘못된 결과가 보여질 수 있습니다.

마무리

연관관계 편의 메서드는 양방향 연관관계의 불일치를 막고, 객체 상태를 일관되게 유지하기 위한 필수 설계 요소입니다.
JPA를 제대로 활용하려면 꼭 이해하고, 적극적으로 사용해야 하는 부분입니다.