728x90
Spring JPA Entity 연관관계 및 즉시로딩, 지연로딩
개요
Spring Data JPA는 엔티티 간의 연관관계를 설정하고 관리하는 강력한 기능을 제공합니다. 엔티티 간의 연관관계는 데이터베이스의 테이블 간의 관계와 유사합니다. JPA에서는 엔티티 간의 관계를 맵핑하고, 데이터 로딩 방식을 제어할 수 있는 다양한 옵션을 제공합니다. 이 글에서는 JPA의 엔티티 연관관계와 즉시로딩(Eager Loading), 지연로딩(Lazy Loading)에 대해 자세히 설명하겠습니다.
목차
- 엔티티 연관관계 개념
- 연관관계 유형
- 연관관계 매핑 예제
- 즉시로딩과 지연로딩
- 로딩 전략 선택 시 고려사항
- 예제 코드
- 요약
1. 엔티티 연관관계 개념
엔티티 연관관계는 데이터베이스 테이블 간의 관계를 엔티티 객체 간의 관계로 매핑한 것입니다. 이를 통해 객체 지향적으로 데이터를 처리할 수 있습니다.
2. 연관관계 유형
JPA에서는 다음과 같은 엔티티 간의 연관관계를 지원합니다:
- 일대일(One-to-One) 관계
- 일대다(One-to-Many) 관계
- 다대일(Many-to-One) 관계
- 다대다(Many-to-Many) 관계
3. 연관관계 매핑 예제
일대일(One-to-One) 관계
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne
@JoinColumn(name = "profile_id")
private Profile profile;
}
@Entity
public class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String bio;
}
일대다(One-to-Many) 관계
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "user")
private List<Post> posts = new ArrayList<>();
}
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
private String content;
}
다대다(Many-to-Many) 관계
@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 Set<Course> courses = new HashSet<>();
}
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany(mappedBy = "courses")
private Set<Student> students = new HashSet<>();
}
4. 즉시로딩과 지연로딩
즉시로딩 (Eager Loading)
즉시로딩은 엔티티가 로딩될 때 연관된 엔티티도 즉시 함께 로딩되는 방식입니다. 연관된 엔티티를 즉시 필요로 하는 경우 유용하지만, 불필요한 데이터까지 로딩할 수 있어 성능 저하를 초래할 수 있습니다.
@Entity
public class User {
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
private List<Post> posts;
}
지연로딩 (Lazy Loading)
지연로딩은 연관된 엔티티가 실제로 접근될 때 로딩되는 방식입니다. 초기 로딩 시 불필요한 데이터를 로딩하지 않아 성능을 최적화할 수 있습니다. 단, 연관된 데이터를 사용하기 전에 트랜잭션이 종료되면 LazyInitializationException
이 발생할 수 있습니다.
@Entity
public class User {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private List<Post> posts;
}
5. 로딩 전략 선택 시 고려사항
- 성능: 즉시로딩은 필요하지 않은 데이터를 로딩하여 성능에 영향을 줄 수 있습니다. 지연로딩은 필요한 데이터를 나중에 로딩하여 초기 로딩 시간을 줄일 수 있습니다.
- 트랜잭션 범위: 지연로딩을 사용할 때는 데이터가 사용되기 전까지 트랜잭션이 유지되어야 합니다. 트랜잭션이 종료되면
LazyInitializationException
이 발생할 수 있습니다. - 사용 빈도: 자주 사용되는 연관 데이터는 즉시로딩을 사용하여 편의성을 높일 수 있습니다. 드물게 사용되는 데이터는 지연로딩을 사용하여 초기 성능을 최적화할 수 있습니다.
6. 예제 코드
지연로딩 예제
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private List<Post> posts;
}
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
private String content;
}
// 서비스 클래스
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public User getUserWithPosts(Long userId) {
User user = userRepository.findById(userId).orElseThrow(() -> new RuntimeException("User not found"));
// 지연로딩된 posts를 명시적으로 초기화
Hibernate.initialize(user.getPosts());
return user;
}
}
// 테스트 코드
@Test
public void testLazyLoading() {
UserService userService = new UserService();
User user = userService.getUserWithPosts(1L);
// posts에 접근하면 지연로딩이 발생
for (Post post : user.getPosts()) {
System.out.println(post.getContent());
}
}
7. 요약
- 엔티티 연관관계: JPA는 엔티티 간의 연관관계를 지원하며, 이를 통해 객체 지향적으로 데이터를 처리할 수 있습니다.
- 즉시로딩(Eager Loading): 연관된 엔티티를 즉시 로딩하는 방식으로, 초기 로딩 시 모든 데이터를 함께 로딩합니다.
- 지연로딩(Lazy Loading): 연관된 엔티티를 실제로 접근할 때 로딩하는 방식으로, 초기 로딩 시 불필요한 데이터를 로딩하지 않습니다.
- 로딩 전략 선택: 성능, 트랜잭션 범위, 사용 빈도를 고려하여 적절한 로딩 전략을 선택해야 합니다.
'Spring Boot' 카테고리의 다른 글
[Spring Boot] Redis 설명 및 예제 (0) | 2024.08.22 |
---|---|
[Spring Boot] 엔티티 관리와 영속성 컨텍스트: Spring Data JPA와 @Transactional (0) | 2024.07.15 |
[Spring Boot] Spring Security @EnableMethodSecurity 설명 및 예제 (0) | 2024.07.10 |
[Spring Boot] @Component와 @Configuration의 특징과 차이점 (0) | 2024.07.09 |
[Spring Boot] BCrypt, SCrypt, Argon2 비밀번호 암호화 기법 (0) | 2024.07.09 |