개발자 팁SQL 팁 › N+1 쿼리를 발견하는 법 — 로그를 보면 바로 보인다

N+1 쿼리를 발견하는 법 — 로그를 보면 바로 보인다

2026-08-28 · SQL 팁
한 줄 요약

ORM에서 흔한 N+1 문제의 판별과 해결. 즉시 로딩이 항상 답은 아닌 이유.

증상

목록 화면이 항목 수에 비례해 느려진다. 10건일 때는 괜찮은데 100건에서 눈에 띄게 느리다.

원인은 대개 이 패턴이다.

```

1회: SELECT * FROM posts LIMIT 100

100회: SELECT * FROM users WHERE id = ?

```

목록 1번 + 각 항목마다 1번 = N+1번의 쿼리.

발견하는 법

추측하지 말고 쿼리 로그를 본다. 대부분의 ORM이 개발 환경에서 SQL 로그를 켤 수 있다.

로그에서 볼 것:

```

같은 형태의 쿼리가 반복되는가

반복 횟수가 목록 건수와 일치하는가

```

이 둘이 맞으면 N+1이다. 로그를 켜는 것만으로 대부분 즉시 발견된다.

배포 환경이라면 APM 도구의 트랜잭션 상세에서 같은 패턴을 볼 수 있다.

해결 1 — 함께 가져오기

ORM마다 이름이 다르지만 개념은 같다. 연관 데이터를 미리 함께 조회한다.

```

문제

posts = Post.all

for p in posts: print(p.author.name) # 여기서 매번 쿼리

해결

posts = Post.all.includes(:author) # 미리 함께 조회

```

내부적으로는 두 가지 방식이 쓰인다.

ORM에 따라 어느 쪽을 쓰는지 다르고, 선택할 수 있는 경우도 있다.

해결 2 — 필요한 컬럼만

연관 객체 전체가 아니라 특정 필드만 필요한 경우가 많다.

```sql

SELECT p.id, p.title, u.name

FROM posts p JOIN users u ON u.id = p.user_id

```

객체 전체를 가져오는 대신 필요한 것만 조회하면 전송량과 메모리가 함께 줄어든다.

즉시 로딩이 답이 아닌 경우

includes를 습관적으로 붙이면 다른 문제가 생긴다.

1. 안 쓰는 데이터를 가져옴

목록에서 저자 이름만 쓰는데 저자 객체 전체와 그 하위 연관까지 로딩되면 오히려 느려진다.

2. 조인 결과 폭증

1:N 관계 여러 개를 한 번에 조인하면 행 수가 곱으로 늘어난다.

```

게시글 100 × 댓글 평균 10 × 태그 평균 5 = 5,000행

```

이 경우 조인 대신 별도 쿼리(IN 절)로 나누는 편이 낫다.

3. 페이지네이션과 충돌

1:N 조인 후 LIMIT을 걸면 의도한 건수가 안 나온다. 행이 중복되기 때문이다.

판단 순서

  1. 쿼리 로그로 N+1 확인
  2. 그 화면에서 실제로 쓰는 필드를 확인
  3. 필요한 것만 함께 조회
  4. 1:N이 여러 개면 조인 대신 분리 조회
  5. 다시 로그로 쿼리 수 확인

5번이 빠지면 고쳤다고 생각했는데 다른 곳에서 N+1이 남아 있는 경우가 흔하다.

예방

코드 리뷰에서 볼 만한 신호:

세 번째가 자주 빠진다. 컨트롤러 코드는 깨끗한데 템플릿에서 N+1이 발생하는 경우다.

최종 수정 2026-08-28

자주 묻는 질문

N+1이 무엇인가요?

목록 1건을 조회한 뒤 각 항목마다 추가 쿼리가 나가는 패턴입니다. 100건이면 101번의 쿼리가 발생합니다.

즉시 로딩으로 바꾸면 항상 해결되나요?

아닙니다. 필요 없는 데이터까지 가져오게 되거나 조인 결과가 커져 오히려 느려질 수 있습니다.

어떻게 발견하나요?

쿼리 로그를 켜고 같은 형태의 쿼리가 반복되는지 보면 즉시 보입니다.

DB Linker로 지금 시작하기

AI 채팅으로 데이터베이스를 조회·관리하는 로컬 전용 개발자 도구. 자체 서버 없이 이용자의 기기에서만 동작합니다.

App Store에서 받기 →

안내

이 글은 일반적인 데이터베이스 관리 원칙과 개발 관행을 다루는 콘텐츠이며, 특정 프로젝트·프로덕션 환경에 대한 전문적 조언을 대체하지 않습니다. 구체적 버전·수치가 언급되더라도 실제 사용 중인 도구·버전에서 반드시 재확인하시기 바랍니다.

글 중 일부는 AI 도구의 도움을 받아 초안을 작성한 뒤 발행됩니다. 내용 중 사실과 다르거나 수정이 필요한 부분을 발견하시면 GitHub Issues로 알려주세요.