핵심은 API 이름을 외우는 것이 아니라, 나중에 건별 조회를 처음 조회의 일부로 바꾸는 것입니다.
`order.user`, `order.items`에 접근할 때마다 추가 조회가 붙어 N+1로 번집니다.
user는 JOIN, items는 prefetch·batch처럼 관계에 맞는 방식으로 함께 가져옵니다.
주문 수가 늘어도 조회 계획은 유지되므로, 반복 접근이 추가 쿼리 폭증으로 이어지지 않습니다.
JOIN FETCH @EntityGraph @BatchSize(size = 100)
연관 엔티티를 조회 계획에 포함하고, 컬렉션은 한 번에 너무 크게 붙이지 않도록 배치 전략을 섞어 씁니다.
select_related("user")
prefetch_related("items")
FK·OneToOne은 JOIN으로 붙이고, 역참조·ManyToMany는 별도 쿼리 1회 후 메모리에서 결합합니다.
relations: { user: true }
leftJoinAndSelect(...)
관계를 미리 포함하거나 직접 JOIN을 작성해서, 이후 프로퍼티 접근이 별도 SELECT를 만들지 않게 합니다.
include: {
user: true,
items: true
}
결과 모양을 정의하는 순간 연관 로딩 계획도 함께 정해지므로, 조회 후 접근 시점의 추가 쿼리를 줄이기 쉽습니다.
ORM마다 키워드는 달라도, 결국 주문과 연관 엔티티를 한 덩어리의 조회 계획으로 묶어 N+1을 제어합니다.