밤빵's 개발일지
[TIL]20240807 연관관계 본문
연관관계는 숙련주차 때 강의듣다가 긴 강의시간에 너무 지쳐서 흘려들었던거같다. 그리고 팀 프로젝트에 오니 연관관계를 심심치 않게 쓰고있다. 강의를 다시듣기엔 시간이 부족하고.. 어떤기능을 구현하게 될 진 몰라도 알아둬야 할 거같아서 미루고미루다 오늘 정리하기로 했다.
연관관계는 객체지향 프로그래밍에서 매우 중요한 개념 중 하나로, 데이터베이스 테이블 간의 관계를 객체 모델에서 어떻게 표현하고 관리할 것인지를 결정하는 것이다. 연관관계를 잘 이해하고 올바르게 설계하는 것은 애플리케이션의 성능과 유지보수성에 큰 영향을 미친다. 오늘 개발일지에서는 엔터티(Entity) 간의 연관관계에 대한 개념과 종류, 구현 방법, 그리고 코드 예시와 함께 이해한 내용을 정리해 보았다.
😵💫엔터티 간의 연관관계란?
연관관계는 객체 모델에서 두 엔터티 간의 관계를 나타내는 것으로, 객체지향 프로그래밍과 데이터베이스 설계 모두에서 중요한 역할을 한다. 연관관계는 크게 일대일(One-to-One), 일대다(One-to-Many), 다대일(Many-to-One), 다대다(Many-to-Many) 네 가지로 구분할 수 있다. 각각의 연관관계는 서로 다른 비즈니스 요구사항을 충족하기 위해 사용되며, 데이터베이스에서 테이블 간의 관계로 표현된다.
▶연관관계의 종류와 개념
→ 일대일(One-to-One) 연관관계:
두 엔터티 간에 1:1로 대응되는 관계이다. 예를 들어, 회원(Member) 엔터티와 회원의 상세 정보(MemberDetail) 엔터티가 1:1 관계일 수 있다. 한 회원은 하나의 상세 정보만 가지며, 상세 정보도 하나의 회원만을 가진다.
→ 일대다(One-to-Many) 연관관계:
하나의 엔터티가 여러 엔터티와 연관될 수 있는 관계이다. 예를 들어, 팀(Team) 엔터티와 팀에 속한 여러 회원(Member) 엔터티가 일대다 관계가 될 수 있다. 한 팀은 여러 회원을 가질 수 있지만, 한 회원은 하나의 팀에만 속한다.
→ 다대일(Many-to-One) 연관관계:
일대다의 반대 개념으로, 여러 엔터티가 하나의 엔터티와 연관될 수 있는 관계이다. 회원(Member) 엔터티와 팀(Team) 엔터티의 관계를 다대일로 표현할 수 있다. 여러 회원이 하나의 팀에 속할 수 있다.
→ 다대다(Many-to-Many) 연관관계:
여러 엔터티가 여러 엔터티와 연관될 수 있는 관계이다. 예를 들어, 학생(Student) 엔터티와 강의(Course) 엔터티는 다대다 관계가 될 수 있다. 한 학생은 여러 강의를 수강할 수 있고, 한 강의도 여러 학생이 수강할 수 있다. 다대다 관계는 중간 테이블을 사용해 연결하는 방식으로 구현된다.
▶연관관계 매핑을 위한 주요 어노테이션
- @OneToOne: 1:1 연관관계를 매핑하기 위한 어노테이션이다.
- @OneToMany: 1연관관계를 매핑하기 위한 어노테이션이다.
- @ManyToOne: N:1 연관관계를 매핑하기 위한 어노테이션이다.
- @ManyToMany: N연관관계를 매핑하기 위한 어노테이션이다.
- @JoinColumn: 외래 키(Foreign Key) 컬럼을 지정하기 위해 사용된다.
- @JoinTable: 다대다(N) 관계에서 중간 테이블을 정의하기 위해 사용된다.
▶연관관계 매핑 예시 코드
아래는 회원(Member)와 팀(Team) 엔터티 간의 일대다(One-to-Many)와 다대일(Many-to-One) 관계를 매핑한 간단한 예시 코드이다.
▽Member.java
import jakarta.persistence.*;
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 회원 ID
private String name; // 회원 이름
@ManyToOne // 다대일(N:1) 관계를 나타내는 어노테이션
@JoinColumn(name = "team_id") // 외래 키(Foreign Key) 컬럼을 지정
private Team team; // 팀 정보
// Getter and Setter
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Team getTeam() {
return team;
}
public void setTeam(Team team) {
this.team = team;
}
}
▽Team.java
import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 팀 ID
private String name; // 팀 이름
@OneToMany(mappedBy = "team") // 일대다(1:N) 관계를 나타내는 어노테이션
private List<Member> members = new ArrayList<>(); // 팀에 속한 회원 목록
// Getter and Setter
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Member> getMembers() {
return members;
}
public void setMembers(List<Member> members) {
this.members = members;
}
}
→ Member 엔터티는 @ManyToOne 어노테이션을 사용하여 Team과 다대일(N:1) 관계를 매핑하였다.
→ @JoinColumn 어노테이션을 사용하여 외래 키 컬럼명을 team_id로 설정하였다.
→ Team 엔터티는 @OneToMany 어노테이션을 사용하여 Member와 일대다(1) 관계를 매핑하였다.
→ mappedBy 속성을 사용하여 연관 관계의 주인을 Member 엔터티의 team 필드로 지정하였다.
→ 이 코드는 Member와 Team 간의 관계를 설정하여, 한 팀에 여러 회원이 속할 수 있도록 구성하였다.
▶연관관계 매핑 시 주의사항
연관관계를 매핑할 때 고려해야 할 중요한 사항들은 다음과 같다:
→ 연관관계의 주인(Owner) 설정:
JPA에서는 연관관계의 주인을 설정하는 것이 중요하다. 연관관계의 주인만이 외래 키를 관리할 수 있으며, 주인이 아닌 쪽에서는 읽기만 가능하다. 주인은 @JoinColumn 애너테이션으로 설정한다.
→ 양방향 매핑의 순환 참조 문제:
양방향 관계에서 두 엔터티가 서로를 참조할 경우 순환 참조(Circular Reference) 문제가 발생할 수 있다. 이를 방지하기 위해 mappedBy를 사용하여 관계를 설정하고, 데이터 조회 시 fetch 전략을 잘 설정해야 한다.
→ 지연 로딩(Lazy Loading)과 즉시 로딩(Eager Loading):
엔터티를 로딩할 때, 지연 로딩과 즉시 로딩 중 어떤 방식을 사용할지 결정해야 한다. 필요에 따라 로딩 방식을 설정하여 성능을 최적화할 수 있다.
→ 성능 고려:
다대다(N) 관계는 중간 테이블을 사용하여 표현되므로, 성능 이슈가 발생할 수 있다. 복잡한 다대다 관계를 단방향 또는 양방향 일대다/다대일 관계로 변경하는 것도 고려할 수 있다.
▶정리
엔터티 간의 연관관계 개념과 종류, 그리고 매핑 방법에 대해 공부하면서, 연관관계는 객체 모델과 데이터베이스 모델 간의 불일치를 해결하는 중요한 개념이지만, 처음에는 주인 설정, 양방향 매핑, 성능 최적화 등 다양한 요소를 고려해야 하기 때문에 이해하는 데 어려움이 있었다. 특히, 양방향 매핑에서 발생하는 순환 참조 문제를 이해하는 데에는 많은 시간을 소모했지만 이해가 어려웠다.아무래도 연관관게를 구현해야할 때 마다 다시 공부해야 할 거 같다.
'개발Article' 카테고리의 다른 글
[TIL]20240809 Validation (0) | 2024.08.09 |
---|---|
[TIL]20240808 SSE와 웹소켓 비교 (0) | 2024.08.08 |
[TIL]20240806 RestTemplate (0) | 2024.08.06 |
[TIL]20240805 웹소켓(WebSocket) (0) | 2024.08.05 |
[WIL]20240804 멘토링CRUD에 아티클기능을 추가해주세요..? (1) | 2024.08.04 |