SPRING&BOOT/JPA

JPA Entity 연관 관계

jki09871 2024. 8. 26. 10:03
JPA(Java Persistence API)는 자바 애플리케이션에서 데이터베이스와 객체 간의 매핑을 관리하는 강력한 도구다. 엔티티(Entity) 간의 연관 관계를 제대로 이해하고 설정하는 것은 JPA를 효율적으로 사용하는 데 필수적이다. 이 글에서는 JPA에서 엔티티 연관 관계를 어떻게 매핑하는지, 그리고 그 관계들이 애플리케이션 설계에서 어떤 역할을 하는지 알아보겠다.

1. 엔티티 연관 관계의 기본 개념

엔티티(Entity)는 데이터베이스의 테이블과 매핑되는 자바 클래스다. 실제 데이터베이스 구조를 객체 모델로 표현할 때, 엔티티 간의 연관 관계를 정의하는 것이 중요한데, 이를 통해 데이터베이스의 관계형 데이터를 객체 지향적으로 다룰 수 있다.

JPA에서 지원하는 주요 연관 관계는 다음과 같다:

  • 1대1 관계 (One-to-One)
  • 1대N관계 (One-to-Many)
  • N대M관계 (Many-to-Many)

각 연관 관계는 @OneToOne, @OneToMany, @ManyToOne, @ManyToMany 어노테이션을 사용하여 매핑된다. 이 관계들은 실제 비즈니스 로직에서 엔티티 간의 상호작용을 정의하는 데 사용된다.

2. 1:1 관계 매핑

1:1 관계는 두 엔티티가 서로 하나씩만 연결되는 경우를 의미한다. 예를 들어, User 엔티티와 Profile 엔티티가 있을 때, 각 User는 하나의 Profile을 가질 수 있고, 각 Profile도 하나의 User에만 속한다.

예시 코드:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "profile_id", referencedColumnName = "id")
    private Profile profile;

    // getters and setters
}

@Entity
public class Profile {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(mappedBy = "profile")
    private User user;

    // getters and setters
}

여기서 User 엔티티는 Profile 엔티티와 1:1 관계를 맺고 있으며, 외래 키 profile_id를 통해 연결된다.

3. 1:N관계 매핑

1:N관계는 한 엔티티가 여러 개의 다른 엔티티와 연관되는 경우를 의미한다. 예를 들어, 하나의 Category가 여러 Product를 가질 수 있다. 각 Product는 하나의 Category에만 속한다.

예시 코드:

@Entity
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
    private List<Product> products = new ArrayList<>();

    // getters and setters
}

@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "category_id")
    private Category category;

    // getters and setters
}

이 코드에서는 Category 엔티티가 여러 개의 Product 엔티티를 포함하며, Product 엔티티는 하나의 Category에 속해 있다.

4. N:M관계 매핑

N:M 관계는 두 엔티티가 서로 여러 개의 관련 엔티티를 가질 수 있는 경우다. 예를 들어, Student와 Course 엔티티가 있을 때, 하나의 Student가 여러 Course를 수강할 수 있고, 하나의 Course도 여러 Student에 의해 수강될 수 있다.

예시 코드:

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToMany
    @JoinTable(
        name = "student_course",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id")
    )
    private List<Course> courses = new ArrayList<>();

    // getters and setters
}

@Entity
public class Course {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToMany(mappedBy = "courses")
    private List<Student> students;

    // getters and setters
}

여기서 Student와 Course는 student_course라는 중간 테이블을 통해 N

관계를 맺는다. 이 조인 테이블은 student_id와 course_id 두 외래 키로 구성된다.

5. 연관 관계의 지연 로딩과 즉시 로딩

JPA에서는 엔티티 연관 관계를 설정할 때, 데이터를 언제 로드할지 선택할 수 있다. 이를 지연 로딩(Lazy Loading)과 즉시 로딩(Eager Loading)이라고 한다.

  • 지연 로딩(Lazy Loading): 실제로 객체가 필요할 때까지 데이터를 로드하지 않음. 성능을 최적화할 수 있다.
  • 즉시 로딩(Eager Loading): 엔티티가 조회될 때 연관된 모든 데이터를 즉시 로드함. 사용이 간편하지만, 성능에 부담을 줄 수 있다.

어노테이션 @OneToMany, @ManyToOne 등에서 fetch 속성을 사용하여 로딩 전략을 설정할 수 있다.

@OneToMany(fetch = FetchType.LAZY)
private List<Product> products;

6. 엔티티 연관 관계 매핑의 중요성

올바른 엔티티 연관 관계 매핑은 애플리케이션의 성능과 유지 보수성을 크게 향상시킨다. 비즈니스 로직에 따라 적절한 관계를 설정하고, 로딩 전략을 잘 선택하는 것이 중요하다. 관계 매핑이 잘못되면 성능 저하, 데이터 불일치 등 다양한 문제가 발생할 수 있다.

마무리

JPA에서 엔티티 간의 연관 관계를 매핑하는 것은 단순히 데이터를 저장하고 조회하는 것 이상으로, 애플리케이션의 구조와 성능에 큰 영향을 미친다. 1대1, 1대N, N:M관계를 이해하고 적절히 사용하는 것은 견고한 데이터 모델링의 핵심이다. 이를 통해 유지 보수성과 성능이 뛰어난 애플리케이션을 만들 수 있다.