소개
N+1 문제는 데이터베이스 쿼리의 성능 이슈 중 하나로, 특히 Spring Data JPA와 같은 ORM(Object-Relational Mapping) 프레임워크를 사용할 때 발생할 수 있습니다.
이 문제는 관계형 데이터베이스에서 연관된 엔티티를 검색할 때 발생하며, 한 번의 쿼리로 필요한 데이터를 가져오지 않고 추가적인 쿼리를 여러 번 실행하는 상황을 말합니다.
예를 들어, 하나의 Post 엔티티와 여러 개의 Comment 엔티티가 있다고 가정해 봅시다.
예제
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "post", fetch = FetchType.LAZY)
private List<Comment> comments;
// 다른 필드들...
}
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "post_id")
private Post post;
// 다른 필드들...
}
그리고 PostRepository를 만들어서 findAll 메서드를 호출할 때 N+1 문제가 발생하도록 합니다
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
List<Post> findAll();
}
이제 PostService에서 이 리포지토리를 사용하는 예제를 살펴봅니다.
@Service
public class PostService {
@Autowired
private PostRepository postRepository;
@Transactional
public List<Post> getAllPosts() {
List<Post> posts = postRepository.findAll();
// 여기에서 각각의 Post에 접근할 때마다 Comment를 가져오는 추가적인 쿼리가 발생함 (N+1 문제)
for (Post post : posts) {
List<Comment> comments = post.getComments();
// comments를 사용하는 로직...
}
return posts;
}
}
설명
위 코드에서 getAllPosts 메서드에서 postRepository.findAll()을 호출한 후에 각 Post에 대해 getComments()를 호출하면, 추가적인 쿼리가 발생하여 N+1 문제가 발생합니다. 이 경우, FetchType.LAZY로 설정된 comments 필드는 실제로 사용될 때 로딩이 되기 때문입니다.
해결법
N+1 문제를 해결하려면 JOIN FETCH 또는 @EntityGraph와 같은 방법을 사용하여 한 번의 쿼리로 필요한 데이터를 모두 가져오는 것이 좋습니다.
repository 객체에서 동작시킬 쿼리 위에 조인할 연관된 엔티티 설정하는 annotation들의 예제
EntityGraph 예제
- @EntityGraph(attributePaths = "comments")
JOIN FETCH예제
- @Query("SELECT DISTINCT p FROM Post p JOIN FETCH p.comments")
간단설명
쉽게 설명하여
N+1 문제는 쿼리 한번으로 동작해도 되는 작업을 FetchType.LAZY로 설정되어있는 연관된 엔티티가 있는경우 호출하면 호출한 시점에 쿼리를 동작시켜 성능 저하가 될 수 있다는 내용이다
'개발 > Spring Boot' 카테고리의 다른 글
[Spring Boot] JDBC Template이란? (0) | 2023.12.29 |
---|---|
[Spring Boot] Mock MVC란? (0) | 2023.12.14 |
[Spring Boot] Spring에서 사용된 디자인 패턴 (0) | 2023.12.05 |
[Spring Boot] Spring Batch란? (0) | 2023.11.23 |
[Spring Boot] Junit이란? (0) | 2023.11.20 |