개발 이론/JPA

엔티티

jeonghoe21 2025. 2. 2. 03:16

엔티티(Entity) 개념과 활용

1) 엔티티(Entity)란?

JPA에서 엔티티(Entity) 는 데이터베이스 테이블과 매핑되는 자바 클래스를 의미합니다. @Entity 어노테이션을 사용하여 선언하며, 반드시 @Id로 기본 키(Primary Key)를 지정해야 합니다.

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "user_name", nullable = false, length = 100)
    private String name;
    
    @Column(name = "email", unique = true)
    private String email;
    
    @Column(name = "created_at", updatable = false)
    private LocalDateTime createdAt;
}

3. 엔티티 연관 관계 매핑

1) 관계 매핑 종류 및 사용 예시

(1) 일대일 관계 (@OneToOne)

  • 주로 상세 정보 테이블을 별도로 분리할 때 사용됩니다.
  • 예: User - UserProfile (사용자와 프로필 정보)
@Entity
public class UserProfile {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;
}

(2) 일대다 / 다대일 관계 (@OneToMany, @ManyToOne)

  • @ManyToOne은 일반적인 관계로, 대부분의 경우 외래 키(FK)가 존재하는 쪽에 설정합니다.
  • @OneToMany는 주 테이블에서 여러 개의 하위 데이터를 관리할 때 사용됩니다.
  • 예: User - Order (사용자와 주문 내역)
@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;
}
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Order> orders = new ArrayList<>();
}

(3) 다대다 관계 (@ManyToMany)

  • 중간 테이블을 만들어야 하며, 보통 @JoinTable을 활용합니다.
  • 예: Student - Course (학생과 강의)
@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<>();
}

4. Fetch 전략 (즉시 로딩과 지연 로딩)

1) FetchType.LAZY vs FetchType.EAGER

Fetch 유형설명

FetchType.LAZY (지연 로딩) 연관된 엔티티를 필요할 때만 조회 (기본값)
FetchType.EAGER (즉시 로딩) 연관된 엔티티를 함께 조회

2) FetchType.LAZY (지연 로딩) 사용 예시

@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;
}
  • user 엔티티는 실제 조회할 때까지 로드되지 않음 (프록시 객체로 유지)
  • 성능 최적화에 유리하지만, LazyInitializationException 발생 가능성 있음

3) FetchType.EAGER (즉시 로딩) 사용 예시

@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id")
    private User user;
}
  • user 엔티티를 Order 조회 시 즉시 불러옴 (JOIN 수행)
  • 불필요한 데이터 조회로 성능 저하 가능성 있음

4) 어떤 경우에 LAZY 또는 EAGER를 사용할까?

시나리오 권장 Fetch 타입
성능 최적화가 중요한 경우 LAZY (기본값)
반드시 연관된 엔티티가 필요할 경우 EAGER
복잡한 객체 그래프 조회 시 JOIN FETCH 또는 EntityGraph 활용

5) JOIN FETCH를 활용한 최적화

@Query("SELECT o FROM Order o JOIN FETCH o.user WHERE o.id = :orderId")
Order findOrderWithUser(@Param("orderId") Long orderId);
  • LAZY 설정이 되어 있어도 JOIN FETCH를 사용하여 즉시 조회 가능

6) EntityGraph를 활용한 최적화

@EntityGraph(attributePaths = {"user"})
@Query("SELECT o FROM Order o")
List<Order> findAllWithUserGraph();
  • EntityGraph를 사용하면 특정 관계를 즉시 로딩할 수 있음

'개발 이론 > JPA' 카테고리의 다른 글

정적 / MVC + 템플릿 엔진 / API  (0) 2025.03.02
레포지토리  (0) 2025.02.02
JPA 정의  (1) 2025.02.02