개발 공부/서버
[서버 성능 최적화] DB 쿼리 성능 최적화 전략, 인덱스, N+1 문제, 정규화/비정규화
악마의 개발자
2025. 5. 22. 20:00
반응형

💡 “API는 빠른데, DB가 느리면 의미가 없어요”
서버 응답 속도 문제의 주범은 의외로 많습니다.
“로직은 간단한데 결과가 늦게 와요.”
“SELECT 하나 날렸는데 2~3초 걸리네요…”
→ 이럴 때 대부분 원인은 DB 쿼리 구조와 인덱스 설계입니다.
🔎 DB 쿼리 속도를 떨어뜨리는 3대 요인
| 문제 | 설명 |
| ❌ 인덱스 미사용 | WHERE 조건에 맞는 인덱스가 없어 전체 탐색 |
| ❌ N+1 쿼리 | 반복적으로 DB에 여러 번 접근 |
| ❌ 과도한 JOIN | 복잡한 테이블 관계로 인해 쿼리 지연 발생 |
🧱 1. 인덱스(Index) 최적화
인덱스는 책의 목차와 같아요.
원하는 데이터를 빨리 찾게 해주는 도우미!
하지만 너무 많으면 오히려 삽입·수정 속도 저하 발생 ⚠️
✅ 인덱스 기본 전략
- 자주 검색하는 컬럼에 인덱스 생성 (ex. user_id, email)
- WHERE, ORDER BY, JOIN ON 등에 자주 쓰이면 인덱스 고려
- 복합 인덱스는 사용 순서 주의!
CREATE INDEX idx_user_email ON users(email);
✅ 인덱스 쓰면 SELECT가 1초 → 0.01초로 줄기도 해요!
🔁 2. N+1 문제
N+1 쿼리란?
→ 하나의 쿼리(N) 실행 후,
→ N개의 결과마다 추가 쿼리(+1)를 반복하는 비효율적인 구조
예시 (Node.js + ORM)
const posts = await Post.findAll();
for (const post of posts) {
const user = await post.getUser(); // N번 호출
}
✅ 해결 방법: JOIN 또는 Include
const posts = await Post.findAll({
include: [{ model: User }]
});
✅ DB에 한 번만 요청해서, 포스트 + 사용자 정보 한꺼번에 가져오기
🔄 3. 정규화 vs 비정규화
정규화
테이블을 나누고 관계로 관리
→ 데이터 중복 줄임, 구조적 → 성능 저하 가능성도 있음
비정규화
데이터를 중복해서라도 빠르게 읽기
→ 조회 속도 향상, INSERT/UPDATE는 불편해질 수 있음
| 비교 | 정규화 | 비정규화 |
| 장점 | 구조적, 무결성 ↑ | 읽기 속도 빠름 |
| 단점 | JOIN 많아져 느림 | 중복 데이터 많음 |
| 예시 | user_id만 저장 | user_name까지 같이 저장 |
✅ 읽기가 잦고 변경이 적은 데이터라면 비정규화도 고려!
🔧 쿼리 최적화 실무 팁
| 팁 | 이유 |
| SELECT * 지양 | 불필요한 데이터까지 조회 |
| 쿼리 실행 계획(EXPLAIN) 확인 | 인덱스 사용 여부 확인 |
| 슬로우 쿼리 로그 분석 | 오래 걸리는 쿼리 찾아서 개선 |
| LIMIT, OFFSET 조절 | 페이징 성능 관리 |
| 캐싱 가능한 쿼리는 Redis 활용 | 인기 데이터 반복 조회 방지 |
🧠 정리 한마디!
DB 성능 최적화는 결국 “적게 읽고, 빠르게 찾고, 반복하지 않기”
✔️ 최적화 핵심 전략
- 인덱스: 빠르게 찾아라
- N+1 제거: 반복하지 마라
- 정규화/비정규화: 상황에 따라 나누거나 합쳐라
반응형