Spring Boot/JPA

JPA - fetch join시 연관 엔티티 1차 캐시에 저장

최-코드 2025. 5. 29. 20:33

배경

  • 스터디 상세 조회 API 테스트하던 중, 댓글 유무의 차이로 쿼리 개수가 달라지는 것을 보았다.
    • 스터디 작성자와 댓글 작성자가 같은 상황이었고, 실수로 스터디를 조회할 때 user를 fetch join하지 않았다.
    • 하지만 댓글을 조회할 때 user를 fetch join했다. 이러다 보니 나중에 GetStudyDetailsResponse할 때 유저 정보를 조회할 때의 쿼리 수가 달라졌다.

깨달음

  • fetch join 시에 연관 엔티티도 1차 캐시에 저장한다는 것이다.
  • 그래서 댓글에서 유저를 fetch join할 때도 유저 엔티티의 정보가 1차 캐시에 있으므로 스터디에서 유저 정보를 조회할 때 추가 쿼리가 안 나가는 것이다.
  • 이를 통해 이미 불러온 엔티티가 있을 때, 불필요한 join이 발생하는 로직이 없는지 확인한 결과 아래와 같은 코드를 찾았다.
@Transactional
public GetStudyDetailsResponse getStudyDetails(Long studyId, UUID userId) {
    Study study = studyRepository.findByIdWithUserAndRecruitmentPosition(studyId)
            .orElseThrow(() -> new GlobalException(NOT_FOUND, "study not found"));

    UserInteractionInfo userInteractionInfo = getUserInteractionInfo(studyId, userId);

    List<ImageInfo> imageInfos = getImageInfos(studyId);

    List<RecruitmentPositionDetailsInfo> recruitmentPositionDetailsInfos =
            getRecruitmentPositionDetailsInfo(study.getStudyRecruitmentPositions());

    PageResponse<GetStudyParentCommentResponse> pageComment = getGetStudyCommentResponsePageResponse(studyId);

    ParticipationStatusInfo participationStatusInfo = getParticipationStatusInfo(studyId, userId);

    studyRepository.incrementViewCountById(studyId);

    return GetStudyDetailsResponse.of(
            study,
            userInteractionInfo,
            recruitmentPositionDetailsInfos,
            imageInfos,
            pageComment,
            participationStatusInfo
    );
}
  • ParticipationStatusInfo를 불러올 때, RecruitmentPositionTitle 정보를 불러와야 하므로 StudyParticipation을 조회할 때 StudyRecruitmentPosition을 fetch join했다.
  • 하지만 스터디를 조회할 때부터 RecruitmentPosition을 fetch join 하므로 StudyParticipation을 조회할 때 RecruitmentPosition을 fetch join할 필요없고, 1차 캐시에서 데이터를 가져오면 된다.