Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
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
Tags more
Archives
Today
Total
관리 메뉴

밤빵's 개발일지

[TIL]20240807 연관관계 본문

개발Article

[TIL]20240807 연관관계

최밤빵 2024. 8. 7. 23:02

연관관계는 숙련주차 때 강의듣다가 긴 강의시간에 너무 지쳐서 흘려들었던거같다. 그리고 팀 프로젝트에 오니 연관관계를 심심치 않게 쓰고있다. 강의를 다시듣기엔 시간이 부족하고.. 어떤기능을 구현하게 될 진 몰라도 알아둬야 할 거같아서 미루고미루다 오늘 정리하기로 했다. 

연관관계는 객체지향 프로그래밍에서 매우 중요한 개념 중 하나로, 데이터베이스 테이블 간의 관계를 객체 모델에서 어떻게 표현하고 관리할 것인지를 결정하는 것이다. 연관관계를 잘 이해하고 올바르게 설계하는 것은 애플리케이션의 성능과 유지보수성에 큰 영향을 미친다. 오늘 개발일지에서는 엔터티(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) 관계는 중간 테이블을 사용하여 표현되므로, 성능 이슈가 발생할 수 있다. 복잡한 다대다 관계를 단방향 또는 양방향 일대다/다대일 관계로 변경하는 것도 고려할 수 있다.

 

▶정리

엔터티 간의 연관관계 개념과 종류, 그리고 매핑 방법에 대해 공부하면서, 연관관계는 객체 모델과 데이터베이스 모델 간의 불일치를 해결하는 중요한 개념이지만, 처음에는 주인 설정, 양방향 매핑, 성능 최적화 등 다양한 요소를 고려해야 하기 때문에 이해하는 데 어려움이 있었다. 특히, 양방향 매핑에서 발생하는 순환 참조 문제를 이해하는 데에는 많은 시간을 소모했지만 이해가 어려웠다.아무래도 연관관게를 구현해야할 때 마다 다시 공부해야 할 거 같다.