같은 목표, 다른 문법 Eager Loading은 ORM 이름과 상관없이, 주문을 읽는 첫 쿼리에 연관 로딩 계획을 같이 실어 보내는 방식입니다.

핵심은 API 이름을 외우는 것이 아니라, 나중에 건별 조회처음 조회의 일부로 바꾸는 것입니다.

Before
주문만 먼저 읽음

`order.user`, `order.items`에 접근할 때마다 추가 조회가 붙어 N+1로 번집니다.

Plan
첫 SELECT에 연관 로딩 계획 포함

user는 JOIN, items는 prefetch·batch처럼 관계에 맞는 방식으로 함께 가져옵니다.

Result
쿼리 수가 고정된 패턴으로 수렴

주문 수가 늘어도 조회 계획은 유지되므로, 반복 접근이 추가 쿼리 폭증으로 이어지지 않습니다.

ORM
어떻게 쓰나
실제로 일어나는 일
JPA Java
JOIN FETCH
@EntityGraph
@BatchSize(size = 100)
to-one은 같이 JOIN하고, 큰 컬렉션은 배치 조회로 제어

연관 엔티티를 조회 계획에 포함하고, 컬렉션은 한 번에 너무 크게 붙이지 않도록 배치 전략을 섞어 씁니다.

Django Python
select_related("user")
prefetch_related("items")
관계 종류에 따라 JOIN과 후속 배치를 분리

FK·OneToOne은 JOIN으로 붙이고, 역참조·ManyToMany는 별도 쿼리 1회 후 메모리에서 결합합니다.

TypeORM TypeScript
relations: { user: true }
leftJoinAndSelect(...)
간단하면 선언형, 제어가 필요하면 QueryBuilder

관계를 미리 포함하거나 직접 JOIN을 작성해서, 이후 프로퍼티 접근이 별도 SELECT를 만들지 않게 합니다.

Prisma TypeScript
include: {
  user: true,
  items: true
}
응답에 포함할 연관 데이터를 미리 선언

결과 모양을 정의하는 순간 연관 로딩 계획도 함께 정해지므로, 조회 후 접근 시점의 추가 쿼리를 줄이기 쉽습니다.

읽는 법은 같습니다: "나중에 찾아오기"를 "처음부터 같이 읽기"로 바꾸는 것.

ORM마다 키워드는 달라도, 결국 주문과 연관 엔티티를 한 덩어리의 조회 계획으로 묶어 N+1을 제어합니다.