[260729]N+1 문제란?

이상민·2026년 7월 29일

Spring

목록 보기
48/59

N+1 문제란?

N+1 문제란 엔티티를 1개 조회했더니 N개의 추가 쿼리문이 실행되는 경우를 말한다.

보통 N+1문제가 발생하는 경우는 연관관계가 복잡한 데이터를 루프하며 접근할때 자주 발생한다.


N+1 발생시 생기는 문제

N+1이 발생할때 생기는 문제는 다음과 같다.

  • 단일로 요청하는데 수십개의 쿼리가 실행되어 DB에 부하발생
  • 트래픽이 많을수록 병목 가능성 증가
  • 캐싱이 어렵고, 요청이 많아질수록 응답시간이 급증
  • 서버에 문제가 발생하지 않으면 눈치채지 못할 가능성이 높음

N+1 문제 예시

N+1문제가 발생하는 예시 코드는 다음과 같다.

@Entity
public class User {
@Id @GeneratedValue
private Long id;
private String username;


@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Post> posts = new ArrayList<>();
}


@Entity
public class Post {
@Id @GeneratedValue
private Long id;
private String title;
private String content;


@ManyToOne(fetch = FetchType.LAZY)
private User user;


@OneToMany(mappedBy = "post", fetch = FetchType.LAZY)
private List<Comment> comments = new ArrayList<>();
}


@Entity
public class Comment {
@Id @GeneratedValue
private Long id;
private String content;


@ManyToOne(fetch = FetchType.LAZY)
private Post post;
}

다음과 같이 User <-> Post <-> Comment 로 연관관계가 짜여진 엔티티를 3개 생성한다.

이때 특정한 사용자가 작성한 게시글의 댓글을 가져오는 요청을 한다고 가정하면,

public List<PostSummaryDto> getPostSummariesByUser(String username) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new IllegalArgumentException("유저가 없습니다."));

List<PostSummaryDto> result = new ArrayList<>();

for (Post post : user.getPosts()) {
int commentCount = post.getComments().size(); //Lazy 로딩이 발생하는 부분
result.add(new PostSummaryDto(post.getTitle(), commentCount));
}

return result;
}

이런식으로 요청을 할 수 있을것이다.

하지만 이렇게 요청을 하게 된다면, post.getComments() 부분에서 Lazy 로딩이 발생하게 된다.

해당 코드를 실행하면 user.getPosts()를 호출할때 posts를 불러오기 위해

select * from post where user_id = ?;

라는 쿼리문을 실행하게 된다.

그 후,

select * from comment where post_id = ?;
select * from comment where post_id = ?;
select * from comment where post_id = ?;
.
.
.

쿼리를 실행하게 되니 총 1 + 10 = 11 번의 쿼리가 실행되게 된다.

이것이 바로 N+1 문제이다.

profile
백앤드 개발 브이로그

0개의 댓글