Fetch Join (패치 조인) 이란? (w/ N+1 문제)

Soyun_p·2025년 3월 16일
0

📖 지식

목록 보기
6/10
post-thumbnail

fetch joinJPA에서 N+1 문제를 해결하고, 연관된 엔티티를 한 번의 쿼리로 효율적으로 조회하기 위해 사용하는 기능이다.

🪼 1. 기본 개념

🔹 일반 JOIN: 연관된 엔티티를 가져오지만, 조회된 엔티티는 지연 로딩(Lazy Loading)이 적용되어 필요할 때 쿼리가 추가로 발생한다
🔹 FETCH JOIN: 연관된 엔티티를 즉시 로딩(Eager Loading)으로 가져오며, 한 번의 SQL로 연괸된 모든 데이터를 조회한다


🪼 2. 기본 문법

SELECT m FROM Member m JOIN FETCH m.team;

🔹 JOIN FETCH를 사용하면 MemberTeam을 한 번의 쿼리로 가져온다
🔹 JOIN만 사용하면 Member만 즉시 로딩되고 Team은 지연로딩된다


🪼 3. N+1 문제란?

N+1 문제는 데이터베이스와 연동된 애플리케이션에서 발생하는 성능 문제 중 하나로, 하나의 쿼리를 실행할 때 추가로 N개의 쿼리가 더 실행되는 현상을 말한다

📌 N+1 문제의 원인

연관된 엔티티를 조회할 때 지연 로딩(Lazy Loading) 방식으로 데이터를 가져올 경우 발생한다

  1. N+1 문제 시나리오
    🔹 게시글 1개에 댓글이 여러 개인 상황에서, 게이글 목록(10개)를 조회한다고 가정해보자!
List<Post> posts = postRepository.findAll();
for(Post post : posts){
	System.out.println(post.getComments().size();
}

🔹 postRepository.findAll() ➡️ 게시글을 조회하는 1개의 쿼리 실행
🔹 post.getComments() ➡️ 각 게시글의 댓글을 조회하는 N개의 쿼리 실행
✨ 따라서 게시글 10개를 조회하면 1 + 10 = 11번의 쿼리가 실행된다

📌 N+1 문제의 영향

🔹 성능 저하: 불필요한 쿼리가 다수 발생해 데이터베이스 부하 증가
🔹 네트워크 오버헤드: 쿼리 실행 횟수 증가로 인한 응답 시간 지연
🔹 트래픽 증가: 애플리케이션과 DB 서버 간의 트래픽 과부하


🪼 4. JOIN vs FETCH JOIN

예제 코드

@Entity
public class Member {
    @Id @GeneratedValue
    private Long id;
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;
}

@Entity
public class Team {
    @Id @GeneratedValue
    private Long id;
    private String name;
}

JOIN

public List<Member> findMembers() {
    return em.createQuery("SELECT m FROM Member m JOIN m.team", Member.class)
             .getResultList();
}

🔹 Member를 조회한 후 Team을 지연로딩으로 가져온다
🔹 회원이 100명이면 1+100번의 쿼리가 실행된다(N+1 문제 발생)

FETCH JOINN

public List<Member> findMembersWithTeam() {
    return em.createQuery("SELECT m FROM Member m JOIN FETCH m.team", Member.class)
             .getResultList();
}

🔹 MemberTeam을 한 번의 쿼리로 모두 가져온다
🔹 성능 최적화에 유리하다


🪼 5. FETCH JOIN의 주의점

🔹fetch join은 복잡한 쿼리에서 과도하게 사용하면 성능 저하를 초래할 수 있으므로 적절하게 활용해야 한다
🔹fetch join 대상에는 별칭을 줄 수 없다 (JPA 표준에서는 금지, Hibernate에서는 가능하지만 권장X)
🔹 둘 이상의 컬렉션은 fetch join이 불가능하다
🔹 컬렉션을 fetch join 하면 페이징 API를 사용할 수 없다(일대다 관계에서)


🪼 6. 정리

🔹 fetch join은 JPA에서 N+1 문제를 해결하기 위한 강력한 도구이다
🔹 연관된 엔티티를 한 번의 쿼리로 가져오므로 성능 최적화에 유리하다

0개의 댓글