본문 바로가기
Database/MongoDB

[MongoDB] ObjectId가 유일성을 보장하는 원리

by SpiralMoon 2025. 4. 3.
반응형

ObjectId가 유일성을 보장하는 원리

MongoDB가 어떻게 분산 환경에서 ObjectId의 유일성을 보장하는지 알아보자.

ObjectId

MongoDB에서 ObjectId는 각 문서의 고유 식별자 타입으로 사용되며, 데이터베이스 내에서 문서의 유일성을 보장하는 매우 중요한 역할을 한다.

 

기본적으로 문서의 _id 필드에 자동으로 추가되기 때문에 빈 문서를 생성하려고 해도 MongoDB Driver가 강제로 ObjectId를 할당한다.


ObjectId의 구조

object id

ObjectId는 총 12bytes로 구성되어 있으며, 각 bytes는 다음과 같은 정보를 담고 있다.

 

  • 4bytes : 문서가 생성된 시간 (UNIX timestamp, 초 단위까지 구별)
  • 5bytes (3bytes + 2bytes) : MongoDB 인스턴스가 실행되는 머신과 MongoDB client driver가 실행되는 로컬 프로세스를 식별하는 값
  • 3bytes : 임의의 값으로 초기화되는 증분 카운터

중간에 서술된 5bytes 덕분에 머신, 프로세스마다 고유한 값이 생성되므로 분산 저장 환경에서도 충돌 없는 ObjectId가 생성된다.


ObjectId는 정말 충돌하지 않을까?

매우 낮은 확률이지만 이론상으로는 충돌이 가능하다.

 

연속적인 _id

 

한 프로세스에서 동일 시각(초)에 여러개의 문서를 생성하는 경우 위 처럼 연속적으로 보이는 ObjectId가 할당된다.

 

동일 프로세스, 동일 시각에 생성되는 ObjectId는 앞의 9bytes가 고정되므로, 충돌 가능성은 뒤의 3bytes인 카운터(2²⁴ = 16,777,216) 범위 내에서 결정된다.

 

저 조건에서 1600만개 이상의 문서를 생성하면 충돌할 수 있지만... 실제 환경에서는 아래와 같은 이슈들이 동시에 발생하기 때문에 이 수치를 넘기기 불가능에 가깝다.

  • 단일 프로세스의 처리 성능 한계
  • 네트워크 지연
  • 디스크 I/O 속도
  • (분산 트랜잭션 환경의 경우) WriteConcern으로 인한 저장 지연

충돌 가능성이 있음에도 UUID 기반 식별자를 사용하지 않는 이유

다른 고유 식별자 체계로 UUID가 있는데 16bytes로 구성되어 ObjectId보다 충돌 가능성이 낮다. 그럼에도 MongoDB가 ObjectId를 사용하는 이유는 다음과 같다.

ObjectId는 정렬 가능한 ID이다.

ObjectId는 생성된 시간 순서대로 증가하며 _id를 기본 인덱스로 사용하므로 디스크에 연속적으로 저장되며 write 성능이 향상된다.

반면, UUID를 사용하면 완전히 랜덤하므로, 인덱스를 계속 재정렬해야 하고 성능 저하가 발생한다.

ObjectId는 생성이 가볍고 빠르다.

ObjectId는 MongoDB 드라이버에서 자체 생성된다. 시스템 시간 + 머신 ID + 프로세스 ID + 카운터만 조합하면 되기 때문에 외부 의존 없이 생성 가능하다.

ObjectId는 충분히 안전하다.

위에서 설명했듯 이미 충분히 안전한 수준이기 때문에 굳이 성능을 포기하며 과도하게 안전한 UUID을 선택할 이유가 없다.

 

 

반응형

댓글