이 영역을 누르면 첫 페이지로 이동
개발다이어리 블로그의 첫 페이지로 이동

개발다이어리

페이지 맨 위로 올라가기

개발다이어리

저만의 개발일지를 만들어가는 공간입니다.

JPA필수코스 N+1문제 해결하기

  • 2022.06.25 23:06
  • 에러모음

들어가기에 앞서

JPA를 처음 사용하면 정말 어쩔 수 없이 필수적으로 마주하는 문제가 바로 N+1문제이다. 연관관계와 무관하게 select절에 조회한 데이터만 가져오고 나머지는 프록시로 가져오는 JPA의 특성상 조회한 엔티티의 연관관계에 속해있는 엔티티를 조회하면 해당 엔티티를 조회하는 수 만큼 쿼리가 새로 나가는 현상이다.

 

 

 

 

 

N+1문제 발견하기

처음부터 코드를 잘 짜면 좋겠지만 이번 프로젝트 자체가 공부를 하면서 진행한 프로젝트이다보니 N+1이란 존재도 나중에 알게되었다. 동작하는 쿼리문을 하나씩 살펴보면서 문제가 발생하는 곳을 찾았고 바로 수정하였다.

 

해당 문제는 Board와 Image테이블에서 나타났다.

 

현재 게시글 엔티티인 Board와 게시글안에 저장할 수 있는 Image엔티티가 1:N관계로 이루어져 있다. 그리고 당연하게도 Board만 조회해서 게시글 리스트를 뿌릴 떄 Image를 조회하는 형식으로 사용하고 있었다.

 

그랬더니 게시글 10개를 뿌리는데 이미지 조회만 10번... 아 이게 바로 N+1이구나 라는 생각으로 바로 수정에 들어갔다.

 

 

 

 

 

N+1문제 해결하기

N+1문제를 해결하는 방법으로는 크게 3가지가 있다.

  • fetch join 사용
  • BatchSize 사용
  • DTO로 변환해서 사용

 

보통 1:N관계에서 페이징을 사용할 때는 데이터가 늘어나는 현상이 있어서 페치조인을 사용하기가 힘들다. 이럴 때 주로 사용하는 것이 BatchSize이다.

DTO는 필요시에는 사용 할 수 있겠지만 지금은 DTO가 아닌 엔티티를 반환하고 있기떄문에 이것도 사용하지 않겠다.

 

결국 페치조인을 사용해서 문제를 해결했다. 지금 상황에서 가장 효율적이고 간단한 방법이다.

 

바꾸기 전의 쿼리는 그냥 메소드 호출로 가져왔다.

List<Board> findByMember_idAndDate(@Param("memberId") Long memberId, @Param("date") String date);

 

페치조인을 사용한 쿼리는 다음과 같다.

@Query("select b from Board b left join fetch b.images join b.member m where b.date = :date and m.id = :memberId")
List<Board> findByMember_idAndDate(@Param("memberId") Long memberId, @Param("date") String date);

이렇게 수정한 뒤 조회를 해봤을 때 깔끔하게 하나의 쿼리로 조회되는 것을 확인할 수 있었다.

저작자표시 (새창열림)

'에러모음' 카테고리의 다른 글

JPA 일대다 조인 데이터 부풀려지기 방지하기  (0) 2022.06.27
스프링부트 gradle build 실패  (0) 2022.06.15
[Error] Mockito를 사용한 단위테스트(form데이터 전송)  (0) 2022.05.17
[Error] JPQL에서 엔티티조인 후 내부의 엔티티 조회  (0) 2022.05.03
[Error] TransientPropertyValueException에러..  (0) 2022.05.02

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • JPA 일대다 조인 데이터 부풀려지기 방지하기

    JPA 일대다 조인 데이터 부풀려지기 방지하기

    2022.06.27
  • 스프링부트 gradle build 실패

    스프링부트 gradle build 실패

    2022.06.15
  • [Error] Mockito를 사용한 단위테스트(form데이터 전송)

    [Error] Mockito를 사용한 단위테스트(form데이터 전송)

    2022.05.17
  • [Error] JPQL에서 엔티티조인 후 내부의 엔티티 조회

    [Error] JPQL에서 엔티티조인 후 내부의 엔티티 조회

    2022.05.03
다른 글 더 둘러보기

정보

개발다이어리 블로그의 첫 페이지로 이동

개발다이어리

  • 개발다이어리의 첫 페이지로 이동

검색

메뉴

  • 홈
  • Github
  • 방명록

나의 외부 링크

카테고리

  • 분류 전체보기 (66)
    • Spring (19)
      • MVC (7)
      • Boot (3)
      • Core (8)
      • Security (1)
    • Java (1)
    • 네트워크 (7)
    • JPA (6)
    • IntelliJ (2)
    • Database (1)
      • h2 (1)
      • postgreSQL (0)
    • 토이 프로젝트 (5)
      • 여행일지작성 (5)
    • 에러모음 (7)
    • 테스트코드 (2)
    • Git (8)
    • Nginx (2)
    • AWS (1)
    • 책 리뷰 (1)
    • Kotlin (2)
    • 회고 (1)
      • 24년도 회고 (1)
    • API문서 (0)

최근 글

인기 글

댓글

공지사항

아카이브

태그

  • 연관관계 매핑
  • 네트워크 #TCP #IP #인터넷 통신
  • http 헤더
  • 테스트코드 실행안됨
  • HTTP
  • 단방향 매핑
  • HTTP상태코드
  • JPA

정보

ssung의 개발다이어리

개발다이어리

ssung

블로그 구독하기

  • 구독하기
  • RSS 피드

방문자

  • 전체 방문자
  • 오늘
  • 어제

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. © ssung. Designed by Fraccino.

티스토리툴바