Programming/TWIL

[TWIL] 1:N 문제와 예시

LazyCat 2025. 3. 23. 20:49
반응형

 

1. N + 1 문제란?

N+1 문제는 하나의 쿼리(1)로 N개의 결과를 가져온 후, 각 결과마다 추가 쿼리(N)가 실행되는 상황을 말한다.

 

예를 들어서, Member가 100명이면

  • members 조회 쿼리: 1번
  • 각 member가 가진 Post 조회 쿼리: 100번
  • 총 101번의 쿼리 발생 → 이것이 N+1 문제

 

2. MyBatis에서 발생하는 N+1 문제

public class Member {
    private Long id;
    private String name;
    private int age;
    private List<Post> posts; // 나중에 수동으로 채움
}

public class Post {
    private Long id;
    private String name;
    private Long memberId;
}
public interface MemberMapper {
    List<Member> findAll(); // 전체 회원 조회
}

public interface PostMapper {
    List<Post> findByMemberId(Long memberId); // 특정 회원의 게시글 조회
}
List<Member> members = memberMapper.findAll(); // 쿼리 1번

for (Member member : members) {
    List<Post> posts = postMapper.findByMemberId(member.getId()); // 쿼리 N번
    member.setPosts(posts);
}

 

MyBatis에선 이러한 N+1문제를 방지하기 위해서

 

<select id="findAllMembersWithPosts" resultMap="memberWithPostsMap">
SELECT
    m.id AS m_id, m.name AS m_name, m.age AS m_age,
    p.id AS p_id, p.name AS p_name, p.member_id AS p_member_id
FROM member m
LEFT JOIN post p ON m.id = p.member_id
</select>

 

ResultMap으로 조인해서 한번에 가져온다 → 쿼리 1번에 List<Post> 로드

 

 

3. JPA에서의 연관관계 매핑방식

@Entity
public class Member {

    @Id @GeneratedValue
    private Long id;

    private String name;
    private int age;

    @OneToMany(mappedBy = "member", fetch = FetchType.LAZY) // 핵심!
    private List<Post> posts = new ArrayList<>();
}

@Entity
public class Post {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private Member member;
}

 

그런데 JPA는 객체 간의 관계를 명시적으로 매핑하고, 이를 기준으로 자동으로 데이터를 로딩한다.

따라서 List<Post> 는 별도의 쿼리를 날리지 않아도 @OneToMany 연관관계 매핑을 통해 자동으로 로딩된다.

 

만약 member.getPosts()를 호출한다면?

  • fetch = LAZY인 경우 → 그 시점에 SQL 쿼리 날려서 가져옴
  • fetch = EAGER인 경우 → member를 가져올 때 post도 함께 가져옴 

 

 

4. 결론

항상 모든 것을 다 해주는 JPA만 사용하다가, 직접 쿼리를 조작하는 MyBatis를 사용하며
N+1문제에 대해서 체감하게 되었다...

고대의 프로그래밍 기술로 올라갈 수록 배울 것이 많아 좋다 :>

 

반응형