일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
31 |
- 오라클 캐릭터셋 변경
- ora-01722
- Oracle Express Edition
- Oracle 사용자명 입력
- oracle
- Oracle 18c 설치
- 무료 오라클 데이터베이스
- 오라클 캐릭터셋 조회
- Oracle 윈도우 설치
- Oracle 18c HR schema
- 무료 오라클 설치
- Oracle 사용자명
- 비전공자를 위한 데이터베이스 입문
- Oracle 테이블 띄어쓰기
- Oracle 초기 사용자
- 서평단
- Oracle 18c HR
- 윈도우 Oracle
- Oracle 테이블 대소문자
- ORA-00922
- Orace 18c
- ORA-12899
- 오라클 캐릭터셋 확인
- oracle 18c
- Today
- Total
The Nirsa Way
[Spring Data JPA] 연관 관계 매핑 (2) : 양방향 매핑 (단방향 vs 양방향, 객체 그래프 탐색) 본문
[Spring Data JPA] 연관 관계 매핑 (2) : 양방향 매핑 (단방향 vs 양방향, 객체 그래프 탐색)
KoreaNirsa 2025. 7. 17. 11:11
양방향 매핑이란?
양쪽의 엔티티가 서로를 참조하도록 설계하는 방식으로써 단방향 매핑과는 객체 그래프 탐색 및 DB 외래키 소유와의 매핑 표현 방식 차이가 있습니다. 무한 루프 주의의 경우 JSON 직렬화 시 발생하는 경우가 대부분인데, 일반적으로 MVC 패턴에서 요청/응답 DTO를 따로 사용하므로 해당 내용은 생략합니다.
아래의 코드를 보면 "연관 관계의 주인" 이라는 주석이 있는데 이는 외래키를 관리하는 주체입니다. 즉 insert/update 등이 발생하는 위치를 뜻합니다. member가 ManyToOne으로 team에 매핑하였으므로 당연히 team에서는 반대로 OneToMany가 됩니다.
연관 관계의 주인이 되는쪽은 JoinColumn으로 FK를 지정하고 주인이 아닌쪽은 mappedBy를 통해 "주인이 아님" 즉, 외래키는 상대방이 관리함을 정의합니다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "team_id") // 연관관계의 주인
private Team team;
}
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy = "team") // 주인이 아님 (읽기 전용)
private List<Member> members = new ArrayList<>();
}
주인 관계를 DDL로 나타내면 아래와 같이 됩니다. 즉, FK를 관리중인 자식 테이블이 "연관 관계의 주인"이 되는 겁니다.
CREATE TABLE team (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255)
);
CREATE TABLE member (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255),
team_id BIGINT,
CONSTRAINT fk_member_team FOREIGN KEY (team_id) REFERENCES team(id)
);
객체 그래프 탐색(Object Graph Navigation)
연관 관계로 연결된 엔티티 객체들을 자바 코드로 탐색하는 것을 말하며 A → B와 같이 연결된 엔티티의 참조 필드들을 통해 다른 객체를 찾아가는 행위를 JPA에서 객체 그래프 탐색이라고 합니다.
우선 단방향 매핑의 탐색을 보면 Member의 경우 Team을 매핑하는 필드가 있기 때문에 Mebmer → Team으로는 탐색이 가능하나, Team → Member로의 탐색은 불가능 합니다. Team에는 Member를 가르키는 필드가 없기 때문입니다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
}
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
private String name;
}
양방향 매핑의 탐색의 경우 Member → Team, Team → Member로의 탐색이 자유롭습니다. 서로 관계를 맺은 상태이기 때문에 어느 방향으로든 탐색을 할 때 전혀 무리가 되지 않습니다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
}
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}
요약하자면 단방향은 한쪽으로만 탐색이 가능하며, 양방향은 양쪽으로 탐색이 가능한 형태를 가지게 됩니다.
단방향과 양방향, 언제 어떻게 써야하나
이번 포스팅의 내용만 보면 "무조건 양방향이 더 좋은게 아니야?"라고 할 수 있지만 상황에 따라 바뀌어야 하며, 일반적으로 단방향으로 개발 후 필요에 따라 양방향 설계를 고려하는 것이 좋습니다.
단방향과 양방향은 상황에 따라 변경되는데, 아래의 예시를 확인 해보세요.
- Order → Customer : 주문(Order)에서 고객(Customer) 정보를 알면 됨
단, 고객(Customer)이 주문(Order)한 모든 정보를 조회해야 한다면 양방향 - Post → Writer : 게시글(Post)은 작성자(Writer)의 정보만 알면 됨
단, 작성자(Post)가 작성한 게시글(Post)을 모두 조회해야 한다면 양방향 - Log → User : 로그(Log)는 사용자(User)의 정보만 알면 됨
단, 사용자(User)에 관련된 로그(log)를 모두 조회해야 한다면 양방향
이와 같이 단방향이 좋다, 양방향이 좋다가 아니라 상황에 따라 어느 관계를 맺어 사용해야 할지 판단을 해야 합니다.