이전 이야기
https://record47584.tistory.com/89
Spring 프로젝트 되살리기 4 - 코드 리펙토링 2 (@Valid 적용)
이전 이야기https://record47584.tistory.com/88 Spring 프로젝트 되살리기 3 - 코드 리펙토링 1 (중첩 if문 제거 등)이전 이야기https://record47584.tistory.com/87 Spring 프로젝트 되살리기 2 - ArgumentResolver 이슈이전 이
record47584.tistory.com
시나리오 5
이제 코드 리팩토링은 어느 정도 끝난 것 처럼 보인다.
그럼 지난번에 문제였던 N+1 처리가 똑바로 되어있는지 체크해보자.
(참고 : https://record47584.tistory.com/73)
N+1 문제의 개념과 해결 방법
N+1 문제란? 처음 조회를 위해 1번의 SQL이 실행되고, 연관된 데이터를 조회하기 위해 N번의 SQL이 추가로 실행되는 현상 지연 로딩(Lazy Loading) 된 연관 엔티티를 반복적으로 조회할 때 발생처음에는
record47584.tistory.com
리팩토링
@Transactional(readOnly = true)
public Page<TodoResponse> getTodos(int page, int size) {
Pageable pageable = PageRequest.of(page - 1, size);
Page<Todo> todos = todoRepository.findAllByOrderByModifiedAtDesc(pageable);
return todos.map(todo -> new TodoResponse(
todo.getId(),
todo.getTitle(),
todo.getContents(),
todo.getWeather(),
new UserResponse(todo.getUser().getId(), todo.getUser().getEmail()),
todo.getCreatedAt(),
todo.getModifiedAt()
));
}
N+1이 발생할 가능성이 있는 service 코드이다.
Hibernate:
select
t1_0.id,
t1_0.contents,
t1_0.created_at,
t1_0.modified_at,
t1_0.title,
t1_0.user_id,
u1_0.id,
u1_0.created_at,
u1_0.email,
u1_0.modified_at,
u1_0.password,
u1_0.user_role,
t1_0.weather
from
todos t1_0
left join
users u1_0
on u1_0.id=t1_0.user_id
order by
t1_0.modified_at desc
limit
?
디버그 콘솔을 확인해보니 query를 N+1번 호출하지 않고 한 번으로 처리가 잘 되어 있다.
@Query("SELECT t FROM Todo t LEFT JOIN FETCH t.user u ORDER BY t.modifiedAt DESC")
Page<Todo> findAllByOrderByModifiedAtDesc(Pageable pageable);
repository 코드를 확인해보니까 JPQL로 처리가 되어있다. 기능적으로는 아무 문제 없다.
@EntityGraph(attributePaths = "user")
Page<Todo> findAllByOrderByModifiedAtDesc(Pageable pageable);
그래도 위와 같이 @EntityGraph를 이용한다면 코드를 조금 더 간결하게(가독성 좋게) 만들 수 있다.
주의! - @EntityGraph로 바꾸지 않는 편이 나은 경우
- 여러 연관관계를 동시에 fetch 하면서 복잡한 WHERE 조건을 걸어야 하는 경우
- DISTINCT가 필요한 컬렉션 fetch join의 경우
'Spring > - [시리즈] Spring 프로젝트 되살리기' 카테고리의 다른 글
| Spring 프로젝트 되살리기 7 - 코드 리팩토링 4 (record, 정적 팩토리 메서드 적용) (0) | 2026.07.26 |
|---|---|
| Spring 프로젝트 되살리기 6 - 유닛 테스트 코드 고치기 (0) | 2026.07.25 |
| Spring 프로젝트 되살리기 4 - 코드 리팩토링 2 (@Valid 적용) (0) | 2026.07.25 |
| Spring 프로젝트 되살리기 3 - 코드 리팩토링 1 (중첩 if문 제거 등) (0) | 2026.07.24 |
| Spring 프로젝트 되살리기 2 - ArgumentResolver 이슈 해결 (0) | 2026.07.24 |