[JPA] 4.다양한 연관관계 매핑
Updated:
다양한 연관관계 매핑
이 게시글을 통해 객체와 테이블간의 연관관계 차이를 이해하고 객체의 참조와 테이블의 외래키를 매핑하는 것을 목표로 한다
배경지식
앞선 JPA 3번 게시글에서 배운 내용을 간략하게 리마인드해보자
다중성
@ManyToOne: 다대일@OneToMany: 일대다@OneToOne: 일대일@ManyToMany: 다대다
실무에서 다대다 관계는 사용하지 않는 것이 좋다. 그 이유와 대체방안에 대해 아래에서 알아보자
단방향과 양방향
- 단방향은 한쪽의 객체에만 반대쪽 객체로의 참조값 필드가 존재한다
- 양방향은 양쪽의 객체 모두 반대쪽 객체로의 참조값 필드가 존재한다
- 정확히 말하자면 양방향은 서로를 향한 단방향이 2개 있는 것과 같다
양방향 연관관계에서 테이블과 객체의 차이점
양방향 연관관계에서 테이블은 외래키 하나만으로 두 테이블이 연관관계를 맺을 수 있지만, 객체는 양쪽 객체의 참조값 필드 즉, 참조가 2군데 존재한다
- 테이블은 외래키를 이용한 조인으로 양쪽 테이블에서 반대 테이블 접근이 가능하다
- 객체는 양쪽 객체에 반대쪽 객체의 참조값 필드가 있는 경우에만 접근이 가능하다
연관관계의 주인
- 위에서 언급한 테이블과 객체의 차이점으로 인해, 객체 측 2군데의 참조 중 테이블 측 1개의 외래키를 관리할 곳을 지정해야한다
- 연관관계의 주인이 아닌 참조는 외래키에 영향을 주지 않고 조회만 가능하다
1. 다대일 관계
1-1. 다대일 단방향
가장 많이 사용하는 연관관계이며 간단하다

- 테이블에서 외래키는 항상 다쪽에 위치한다
- 객체에서 단방향 연관관계 역시 한쪽에만 참조가 존재한다
- 단순히 하나의 외래키와 참조를 매핑하면 된다
1-2. 다대일 양방향

- 테이블에서 외래키는 마찬가지로 항상 다쪽에 위치한다
- 객체에서 양방향 연관관계는 양쪽 객체에 모두 참조가 생겨 총 2개의 참조가 존재한다
- 필요에 따라 단방향에서 양방향으로 바꾸는 경우에는 참조가 필요한 객체 측에서 참조값 필드만 추가해주면 된다
- 어차피 해당 참조값 필드로는 조회만 가능하고 테이블에는 영향을 미치지 않는다
- 코드에서는
@OneToMany를 추가하고mappedBy속성을 넣어주면 된다
- 필요에 따라 단방향에서 양방향으로 바꾸는 경우에는 참조가 필요한 객체 측에서 참조값 필드만 추가해주면 된다
- 테이블의 외래키를 다대일 중 다 측의 객체에서 관리한다
2. 일대다 관계
실무에서 거의 사용하는 경우가 드물다
2-1. 일대다 단방향

- 특이하게 테이블 측에서 다쪽에 위치한 외래키를 연관관계의 주인인 객체 측 일쪽에 위치한 참조로 매핑하는 방식이다
- DB에 조회 이외의 작업은 일대다 관계 중 다 측에서밖에 수행할 수 없다
- 아래 코드를 보면 더 쉽게 이해가 갈 것이다
//기존 로직
member.setTeam(team);
//일대다 단방향에서의 로직
team.members.add(member);
- 이렇게 헷갈리게 설계하는 것보다 차라리 다 측의 객체에도 참조를 추가하여 양방향으로 만들고 해당 참조에서 외래키를 관리하도록 하는 것이 좋다
- 즉, 일대다 단방향을 사용해야 한다면 차라리 다대일 양방향을 사용하자
2-2. 일다다 양방향

- 공식적으로 존재하지 않는 매핑이다
- 대신 다대일 양방향을 사용하자
3. 일대일 관계
일대일 중 어느쪽 테이블에 외래키를 넣을지 선택할 수 있다. 단, 외래키에 DB unique 제약조건을 추가해줘야 한다
3-1. 일대일 단방향
일대일 단방향 연관관계에서 외래키가 있는 테이블의 반대편 객체에서 연관관계의 주인으로써 동작하는 것은 JPA가 지원하지 않는다

- 왜래키가 있는 곳이 연관관계의 주인이다
- 다대일 관계와 마찬가지로 연관관계의 주인 측에는
@JoinColumn을 적고, 반대 측에는mappedBy속성을 명시한다
3-2. 일대일 양방향
외래키가 있는 테이블의 반대편 객체에서 연관관계의 주인으로써 동작하는 것은 일대일 단방향 관계에서 불가하기 때문에 이는 일대일 양방향 연관관계를 이용하여 해결한다

- 다대일 양방향 연관관계와 마찬가지로 양방향 연관관계를 이용하여 외래키와 참조값이 서로 반대에 위치하는 문제를 해결한다
3-3. 일대일 연관관계의 딜레마
일대일 연관관계는 어느쪽 테이블이든 외래키를 넣을 수 있기 때문에 DB 설계시에 양측의 장단점을 살펴보고 선택해야한다
- 주 테이블에 외래키를 놓는 경우
- 주 테이블만 조회해도 대상 테이블의 데이터 유무가 확인 가능하고 JPA 매핑이 편리하다는 장점을 가진다
- 대상 테이블 데이터가 없다면 외래키에 null값을 허용한다는 단점이 존재한다
- 대상 테이블에 외래키를 놓는 경우
- 일대일 양방향 연관관계를 이용하여 해결한다
- 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변강할때 테이블 구조가 유지된다는 장점을 가진다
- JPA 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩된다는 단점이 있다
4. 다대다 관계
@ManyToMany는 실무에서 사용하지 않는다
객체는 다대다 관계를 지원하지만 테이블에서는 다대다관계가 따로 존재하지 않고 일대다, 다대일 관계를 통해 풀어내야 한다는 차이점이 존재한다
- JPA에서
@ManyToMany를 통해 중간 테이블을 자동으로 만들어주기는 하지만, 해당 테이블은 양쪽 테이블의 PK값만을 외래키로 들고 나머지 필드값들을 추가할 수 없다는 명확한 단점이 존재하기 떄문에 실무에서 사용하지 않는다 - 이를 해결하기 위해 중간 테이블을 개발자가 직접 엔티티로 만들어 일대다 다대일 관계로 풀어낸다
Leave a comment