| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
Tags
- 스프링 배치
- java
- 김영한
- 이펙티브 자바
- Effective Java
- 스케줄러
- 프록시 패턴
- 계산기
- redis
- 추상클래스
- 스프링
- 토스
- DB
- 빌더 패턴
- GoF 23
- 프로그래머스
- 백엔드
- 배치
- Spring
- spring boot
- 성능 개선
- 자바
- 코드카타
- 디자인 패턴
- lv1
- 템플릿 메서드 패턴
- 로드밸런서
- 트러블슈팅
- Spring Batch
- Til
Archives
- Today
- Total
김코딩
JPA - 연관관계 편의 메서드 본문
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를 제대로 활용하려면 꼭 이해하고, 적극적으로 사용해야 하는 부분입니다.
'스프링' 카테고리의 다른 글
| QueryDSL 기본 가이드 (1) | 2025.06.30 |
|---|---|
| 스프링 MVC - 타입 변환은 어떻게 이루어질까? (Converter & Formatter) (0) | 2025.06.05 |
| 반복되는 로그인 체크, 필터 하나로 끝내기(Filter 사용법) (0) | 2025.05.22 |
| 여긴 못지나간다.(@Valid) (0) | 2025.05.19 |
| Spring Container와 Bean이 헷갈리는 이들에게 (0) | 2025.05.15 |