MongoDB에서 여러 필드를 조합한 복합 인덱스(Compound Index)를 생성하면 두 개 이상의 필드 값이 동시에 중복되는 것을 방지할 수 있습니다. 이 글에서는 createIndex() 메서드를 사용해 고정 값 필드로 구성된 복합 인덱스를 설정하고, unique 제약 조건이 실제로 어떻게 작동하는지 단계별로 살펴보겠습니다.
1. 복합 인덱스 생성하기
createIndex() 메서드에 여러 필드를 지정하고 {unique:true} 옵션을 추가하면, 해당 필드 조합의 고유성이 보장됩니다.
> db.compoundIndexDemo.createIndex({"StudentName":1,"StudentAge":1},{unique:true});
{
"createdCollectionAutomatically" : true,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}위 명령을 실행하면 컬렉션이 자동으로 생성되고, 기본 _id 인덱스 외에 StudentName_1_StudentAge_1이라는 이름의 복합 인덱스가 추가로 만들어집니다.
2. 테스트용 문서 삽입하기
인덱스의 동작을 확인하기 위해 문서를 몇 개 삽입해 보겠습니다.
> db.compoundIndexDemo.insertOne({"StudentName":"Chris"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e084c1d25ddae1f53b62207")
}
> db.compoundIndexDemo.insertOne({"StudentName":"Chris","StudentAge":23});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e084c5625ddae1f53b62209")
}
> db.compoundIndexDemo.insertOne({"StudentName":"Chris","StudentAge":22});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e084c5b25ddae1f53b6220a")
}여기서 주목할 점은 첫 번째 문서처럼 StudentAge 필드가 아예 없는 경우에도 삽입이 허용된다는 것입니다. 복합 인덱스는 존재하는 필드 값만을 기준으로 고유성을 판단하기 때문입니다.
3. unique 제약 조건 위반 시 발생하는 오류
이제 이미 존재하는 조합과 동일한 데이터를 다시 삽입하면 어떻게 되는지 확인해 보겠습니다.
> db.compoundIndexDemo.insertOne({"StudentName":"Chris","StudentAge":23});
2019-12-29T12:19:02.225+0530 E QUERY [js] WriteError: E11000 duplicate key error collection: web.compoundIndexDemo index: StudentName_1_StudentAge_1 dup key: { : "Chris", : 23.0 } :
WriteError({
"index" : 0,
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: web.compoundIndexDemo index: StudentName_1_StudentAge_1 dup key: { : \"Chris\", : 23.0 }",
"op" : {
"_id" : ObjectId("5e084c5e25ddae1f53b6220b"),
"StudentName" : "Chris",
"StudentAge" : 23
}
})
WriteError@src/mongo/shell/bulk_api.js:461:48
Bulk/mergeBatchResults@src/mongo/shell/bulk_api.js:841:49
Bulk/executeBatch@src/mongo/shell/bulk_api.js:906:13
Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21
DBCollection.prototype.insertOne@src/mongo/shell/crud_api.js:252:9
@(shell):1:1E11000 duplicate key error(오류 코드 11000)가 발생하며 삽입이 거부됩니다. 즉, StudentName과 StudentAge의 조합이 완전히 동일한 문서는 더 이상 저장할 수 없습니다. 반면 StudentAge가 22인 문서는 이름이 같더라도 정상적으로 저장되었던 것처럼, 조합 전체가 같아야만 중복으로 간주됩니다.
4. 저장된 문서 확인하기
find() 메서드를 사용해 컬렉션의 모든 문서를 조회해 보겠습니다.
> db.compoundIndexDemo.find().pretty();
실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5e084c1d25ddae1f53b62207"), "StudentName" : "Chris" }
{
"_id" : ObjectId("5e084c5625ddae1f53b62209"),
"StudentName" : "Chris",
"StudentAge" : 23
}
{
"_id" : ObjectId("5e084c5b25ddae1f53b6220a"),
"StudentName" : "Chris",
"StudentAge" : 22
}정리
MongoDB의 복합 인덱스에 unique:true 옵션을 적용하면, 인덱스에 포함된 모든 필드의 값 조합이 동일한 문서의 삽입을 자동으로 차단합니다. 이를 통해 애플리케이션 레벨의 검증 없이도 데이터베이스 차원에서 데이터 무결성을 강화할 수 있습니다. 특히 학생 이름과 나이처럼 특정 필드 조합의 유일성이 필요한 상황에서 매우 유용하게 활용할 수 있습니다.