[Spring] 구인구직 서비스 Join & page 문제 해결

춤인형의 개발일지·2025년 3월 19일

Spring실습

목록 보기
39/40

fetchJoin()이란?

JPA의 JPQL 또는 QueryDSL에서 연관된 엔티티를 한 번의 SQL 조회로 함께 가져오는 방법.

  • SQL의 Join과 동일한 코드

OneToMany관계에서 기본적으로 지연 로딩(Lazy Loading) 이 적용된 연관 엔티티들은 처음에는 조회되지 않고, 실제 사용할 때 추가적인 N+1 문제를 발생시킴
이를 해결하기 위해 페치 조인(fetch join) 을 사용하면 한 번의 SQL 쿼리로 필요한 데이터를 모두 가져올 수 있음.

fetchJoin()이 필요한 이유?

  • N+1 문제 해결
  • 한 번의 쿼리로 연관된 데이터 모두 조회 (SQL문의 Join)
  • 쿼리 수 감소로 인해 성능 향상

FetchJoin예시

fetchJoin은 DB에서 table이 나누어져 있어 DB에서 JOIN을 할 수 있으면 가능하다. 직접참조(@ManyToOne / @ElementCollection) 일 때만 사용하고 간접참조일 때는 Join자체를 하지 않는다.

  • 한명의 개발자가 여러개의 개발 종목을 가지고 있으니까 ManyToOne / OneToMany 관계이다. 따라서 아래처럼 코드를 작성할 수 있다.
public List<Programmer> findAll(
        List<Field> fieldNames,  
        Integer personalHistory,   
        Pageable pageable
) {
    return jpaQueryFactory
            .selectFrom(programmer)
            .leftJoin(programmer.fieldName, QField.field).fetchJoin() // fetchJoin 추가
            .where(
                    fieldNameCriteria(fieldNames),
                    personalHistoryCriteria(personalHistory)
            )
            .orderBy(programmer.likeCount.desc())
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize())
            .fetch();
}

이런식으로 fetchJoin을 하게 되면 N+1문제를 해결할 수 있는 가장 큰 해결방법이다.

문제 발생

구인구직 서비스같은 경우에는 전체 조회할 때 개발자의 분야까지 보여줘야하기 때문에 개발자와 개발자 분야에 대해 join도 해야하고, 데이터가 너무 많아짐을 방지해 페이징도 해야한다.

  1. sql이 너무 많이 실행됨
  2. 조인을 해서 sql을 줄임
  3. 페이징하니까 같이가 안되네,,,?
  4. 페이징을 먼저 하면 되지
  5. 페이징을 하고 조인은 쿼리 dsl에서 지원을 하지 않는다.
    -> 근데 쿼리dsl이 서브쿼리를 지원 안하네?
    -> 서브쿼리가 where절에는 가능하지만, from절에서는 불가능

이게 왜 문제가 되냐면 페이징을 나중에하면 너무 많은 데이터를 join을 하게 되니까 페이징을 먼저 하고 싶었다. 그런 방법이 없을까,,ㅜ

0개의 댓글