TIL - 2/19

헨도·2025년 2월 19일
0

TIL

목록 보기
6/21
post-thumbnail

N+1 문제..직면하다!

  • 가게 엔티티와 카테고리 엔티티 작업 중 가게는 여러 카테고리를 가질 수 있게 설계를 했고 구현하는 과정에서 문제를 직면했다.
    오늘 날짜인 2/19 기준으로 해결하지는 못했지만, 우선 N+1 문제에 대한 개념을 정리해보고 접근하려고 한다.

N+1 이란?

  • JPA 에서 N+1 문제란 쿼리 최적화의 중요한 이슈로, RDBMS 에서 데이터를 가져올 때 예상치 못한 불필요한 추가 쿼리가 발생하는 문제이다.
  • 이 문제는 JPA 사용 시, 관계를 설정한 엔티티를 조회할 때 자주 발생한다.

설명

  • N+1 문제는 크게 2가지 상황에서 발생한다.

1. 1개의 엔티티를 조회하는 쿼리

  • 예를 들어, 부모 엔티티를 조회하는 쿼리

2. 각 부모 엔티티와 관련된 N개의 자식 엔티티를 조회하는 쿼리

  • 부모 엔티티 하나에 자식 엔티티를 조회하는 추가적인 쿼리 N개가 발생

따라서, 1+N 개의 쿼리가 실행되며 이로 인해 성능 저하 및 불필요한 쿼리 실행이 발생하게 된다.

예시

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

    @OneToMany(mappedBy = "store")
    private List<Category> categories;
}

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

    @ManyToOne
    @JoinColumn(name = "store_id")
    private Store store;
}
  • 위와 같은 2개의 엔티티가 있을 때, Store 와 Category 는 1:N 관계를 가진다.
    즉, Store 는 여러 Category 를 가질 수 있다.
public List<Store> getStores() {
    List<Store> stores = storeRepository.findAll(); // Store 조회
    for (Store store : stores) {
        List<Category> categories = store.getCategories(); // 각 Store에 대한 Category 조회
    }
    return stores;
}
  • 위 코드에서 findAll() 메서드로 모든 Store 를 조회한다.
    그 후 각 Store 객체마다 store.getCategories() 가 호출되는데, 이 때 Store 에 대한 추가 쿼리가 실행된다.
  1. 첫 번째 쿼리: SELECT * FROM Store; (모든 Store 조회)
  2. 두 번째 쿼리: 각 Store 에 대한 SELECT * FROM Category WHERE store_id = ?;
    (각 Store에 대한 Cateogory 조회)

따라서 1+N 개의 쿼리가 실행되며, 100개의 Store가 조회되면 1 + 100 개의 쿼리가 실행된다.

문제점

성능 저하

  • 불필요하게 많은 쿼리가 실행되며, 데이터베이스에 부담을 주고 성능이 크게 저하될 수 있다.

불필요한 DB 트래픽

  • 실제로는 하나의 쿼리로 끝낼 수 있는 작업이 여러 번의 쿼리로 분리되어 DB 부하를 증가시킨다.

해결 방법

  • 해결 방법은 여러 개가 있고, 우리가 익히 알고 있는 fetch join 을 사용하는 방법이 있지만!
    자세한건 해결한 방법에 대해 추후 작성 예정이고, 어떤 종류가 있는지만 알아보려한다.

1. Fetch Join

2. LAZY -> EAGER

3. @EntityGraph 사용

4. Batch Size 설정

고민

  • N + 1 문제는 JPA 에서 자주 발생하는 성능 문제이다.
    이 문제를 해결하기 위해서는 위 방법을 적절히 사용하면 되는데...
    가장 중요한 점은 데이터 로딩 전략을 필요한 데이터만 효율적으로 가져오는 방식으로 설계하는 것이다.
profile
Junior Backend Developer

0개의 댓글