MongoDB Atlas를 운영하다 보면 Performance Advisor에서 Drop Indexes, Unused Indexes, Redundant Indexes 같은 권고를 발견할 수 있습니다.
이때 권고된 인덱스를 Atlas 화면이나 MongoDB Shell에서 바로 삭제하는 것만으로 작업을 끝내기 쉽습니다. 하지만 불필요한 인덱스가 만들어진 원인을 코드에서 제거하지 않으면 다음 배포나 서버 재시작 과정에서 같은 인덱스가 다시 생성될 수 있습니다.
따라서 MongoDB Performance Advisor의 권고는 단순한 데이터베이스 정리 작업이 아니라, 사용하지 않는 API와 모델, 중복된 스키마 설정, 오래된 기능 등 이른바 ‘죽은 코드’를 점검하는 출발점으로 활용하는 것이 좋습니다.
MongoDB Performance Advisor란?
MongoDB Atlas의 Performance Advisor는 실제 데이터베이스 사용 패턴을 분석해 성능 개선 항목을 제안하는 기능입니다.
대표적인 인덱스 제거 권고는 다음과 같습니다.
- Unused Indexes: 일정 기간 쿼리에 사용되지 않은 인덱스
- Redundant Indexes: 다른 복합 인덱스가 동일한 역할을 대신하는 중복 인덱스
- Hidden Indexes: 쿼리 실행 계획에서는 제외됐지만 계속 유지되고 있는 인덱스
불필요한 인덱스는 저장 공간만 사용하는 것이 아닙니다. 문서가 추가되거나 수정되고 삭제될 때마다 관련 인덱스도 함께 갱신되기 때문에 쓰기 성능과 운영 비용에 영향을 줄 수 있습니다.
MongoDB 공식 문서에서도 불필요하거나 중복된 인덱스를 제거하면 저장 공간을 확보하고 쓰기 성능을 개선할 수 있다고 안내합니다.
MongoDB 중복 인덱스는 왜 발생할까?
다음과 같은 인덱스가 있다고 가정해 보겠습니다.
{ area: 1 }
{ area: 1, published: 1 }
{ area: 1, published: 1 } 복합 인덱스는 첫 번째 필드인 area를 기준으로 시작합니다. 따라서 다음 쿼리를 모두 지원할 수 있습니다.
db.fashionshops.find({
area: "seoul"
});
db.fashionshops.find({
area: "seoul",
published: true
});
특별한 옵션 차이가 없다면 { area: 1 } 단일 인덱스의 역할을 { area: 1, published: 1 } 복합 인덱스가 대신할 수 있습니다.
MongoDB Performance Advisor에서는 이런 단일 인덱스를 Redundant, 즉 중복 인덱스로 표시합니다.
다만 복합 인덱스의 필드 순서는 중요합니다. 다음 쿼리는 area 없이 published만 조회하기 때문에 위 복합 인덱스를 효율적으로 사용하지 못할 수 있습니다.
db.fashionshops.find({
published: true
});
따라서 인덱스를 삭제하기 전에는 단순히 필드 이름만 비교하지 말고 실제 쿼리 조건과 정렬 순서까지 함께 확인해야 합니다.
MongoDB 권고에서 죽은 코드의 흔적을 찾을 수 있다
Performance Advisor에서 사용하지 않는 인덱스가 발견됐다고 해서 해당 기능 전체가 죽은 코드라고 단정할 수는 없습니다.
하지만 다음과 같은 문제를 발견할 수 있는 중요한 신호가 됩니다.
- 삭제된 화면에서 사용하던 검색 인덱스
- 더 이상 호출되지 않는 API Route
- 운영이 종료된 게시판이나 콘텐츠 유형
- 이전 검색 조건에 맞춰 생성했던 인덱스
- 모델에 중복 선언된 인덱스
- 리팩터링 이후 남아 있는 Repository 또는 Service
- 일회성 데이터 이전 스크립트
- 사용하지 않는 필드와 정렬 조건
- 배포할 때마다 실행되는 오래된 인덱스 생성 코드
예를 들어 특정 컬렉션의 category, area, author 인덱스가 장기간 사용되지 않았다면 해당 필드를 사용하는 API가 현재도 존재하는지 확인할 필요가 있습니다.
인덱스만 삭제할 것이 아니라 다음 구조를 따라가야 합니다.
MongoDB 인덱스
→ 모델 및 스키마
→ Repository 또는 데이터 접근 코드
→ API Route 및 Server Action
→ 실제 화면과 사용자 기능
이 과정을 통해 데이터베이스뿐만 아니라 애플리케이션 코드 전체를 함께 정리할 수 있습니다.
MongoDB 인덱스 삭제 전 코드에서 확인할 항목
Mongoose를 사용하는 프로젝트에서는 다음과 같이 필드 단위 인덱스와 복합 인덱스가 동시에 선언될 수 있습니다.
const fashionShopSchema = new Schema({
area: {
type: String,
index: true,
},
published: {
type: Boolean,
default: false,
},
});
fashionShopSchema.index({
area: 1,
published: 1,
});
이 코드는 다음 두 개의 인덱스를 만들 수 있습니다.
{ area: 1 }
{ area: 1, published: 1 }
단일 인덱스가 필요하지 않다면 index: true를 제거합니다.
const fashionShopSchema = new Schema({
area: {
type: String,
},
published: {
type: Boolean,
default: false,
},
});
fashionShopSchema.index({
area: 1,
published: 1,
});
프로젝트 전체에서 인덱스 관련 코드를 찾으려면 다음 명령어를 활용할 수 있습니다.
rg "index: true|schema\.index|createIndex|createIndexes|syncIndexes|ensureIndexes" .
특정 필드를 검색하려면 다음과 같이 확인합니다.
rg "area|area_1|area_1_published_1" .
검색 결과에서는 다음 항목을 중점적으로 점검합니다.
- Mongoose Schema의
index: true schema.index()복합 인덱스 선언- MongoDB Driver의
createIndex() - 인덱스를 생성하는 배포 스크립트
syncIndexes()실행 코드- 사용하지 않는 API와 Service
- 해당 필드가 포함된 검색 및 정렬 쿼리