Unique Index {mongodb} {prisma}

MongoDB에서 고유제약조건을 걸기 위해선 어떻게 해야할까? 그리고 PrismaORM을 사용할 때 @unique 속성만 추가한다고 바로 적용이 되지 않는데 prisma push를 해야하는걸까?

AI Response (ChatGPT 4o)

좋은 질문이에요. MongoDB와 PrismaORM 모두에서 고유 제약 조건 (unique constraint) 을 다룰 때 주의할 점이 있습니다. 하나씩 정리해드릴게요.


✅ MongoDB에서 고유 제약 조건 걸기

MongoDB는 스키마리스(NoSQL) 이지만, 인덱스를 이용해서 유일 제약 조건을 설정할 수 있습니다.

방법 1. MongoDB 쉘이나 드라이버에서 인덱스 생성

db.users.createIndex({ email: 1 }, { unique: true })

방법 2. Mongoose 사용 시

const userSchema = new Schema({
  email: { type: String, unique: true }
})

단, Mongoose의 unique: trueMongoDB 인덱스를 생성하라는 힌트일 뿐이고, 자동으로 보장되지 않기 때문에 실제 인덱스가 생성됐는지 확인이 필요합니다.


✅ Prisma ORM에서 @unique 설정의 동작 방식

Prisma ORM에서는 다음처럼 모델에 @unique 데코레이터를 붙여 유니크 제약을 정의합니다.

model User {
  id    String @id @default(auto()) @map("_id") @db.ObjectId
  email String @unique
}

하지만! Prisma에서는 이걸 정의했다고 해서 바로 DB에 반영되는 건 아닙니다.


💡 Prisma에서 @unique 사용 후 해야 할 작업

작업 설명
npx prisma db push 현재 Prisma schema를 기반으로 MongoDB에 인덱스를 생성하거나 스키마 변경사항을 반영합니다. 빠르게 반영할 때 사용.
npx prisma migrate dev PostgreSQL, MySQL 등 관계형 DB에서 마이그레이션 파일을 생성하고 실행. MongoDB에서는 비추천.

MongoDB에서는 보통 prisma db push를 사용해야 합니다.

✔️ 요약: @unique 속성을 선언하고, 반드시 npx prisma db push를 실행해야 MongoDB에 unique 인덱스가 생성됩니다.


🔍 주의사항

  1. 이미 중복된 데이터가 존재하면 db push 시 실패합니다.
    • MongoDB는 인덱스를 생성할 때, 기존 데이터에도 유일성을 검사합니다.
    • 중복 데이터가 있다면 인덱스 생성이 거부됩니다.
  2. Prisma에서는 현재 MongoDB에 대해 마이그레이션을 지원하지 않으며, db push 방식만 사용해야 합니다.
  3. Prisma MongoDB는 내부적으로 _id 외 필드에도 인덱스를 생성할 수 있지만, 인덱스 상태를 관리하지는 않기 때문에 MongoDB Compass나 CLI로 확인하는 습관이 좋습니다.

2025-04-22 Troubleshooting) @unique attribute는 null 중복을 허용하지 않는다.

In MongoDB (and by extension, Prisma with MongoDB), a unique index that allows multiple null values behaves differently than in traditional SQL databases:

If you want a field to be conditionally unique only when it’s not null, you need to manually create a partial index in MongoDB outside of Prisma, since Prisma doesn’t currently support partial indexes natively.

🔧 Step-by-step workaround:

  1. Remove @unique from Prisma schema:
model MyModel {
  id        String  @id @default(auto()) @map("_id") @db.ObjectId
  email     String? // ← we want this to be unique only if NOT null
}
  1. Generate Prisma Client:
npx prisma generate
  1. Create the partial index manually in MongoDB shell:
db.mymodels.createIndex(
  { email: 1 },
  {
    unique: true,
    partialFilterExpression: { email: { $exists: true, $ne: null } }
  }
)

This ensures:


🧪 예제

model Product {
  id     String @id @default(auto()) @map("_id") @db.ObjectId
  sku    String @unique
  name   String
}
npx prisma db push

MongoDB에 접속해서 인덱스 확인:

db.product.getIndexes()

결과:

[
  { "key": { "_id": 1 }, "name": "_id_", "unique": true },
  { "key": { "sku": 1 }, "name": "Product_sku_key", "unique": true }
]

✨ 추가 팁

@@unique([firstName, lastName])

필요하다면, Prisma + MongoDB 구조에서의 실전 유스케이스 (e.g. 회원 가입 시 중복 이메일 처리, 유니크 실패 시 예외 핸들링) 도 알려드릴게요. 원하시나요?