티스토리 뷰

 

 

 

 

 

Next.js를 배우면서 간단한 백엔드 서버를 만들게 됐는데, Mongoose라는 라이브러리로 MongoDB를 연동했다. 조약하지만 백엔드 서버는 처음 만들어봐서 재밌다ㅎㅎ

 

MongoDB와 Mongoose에 대한 공부는 차차 할 예정이고, 오늘은 실습을 하면서 마주쳤던 에러에 대해 다룰 것이다.

 

 

Mongoose 스키마와 모델


우선 스키마와 모델은 무엇일까?

 

스키마는 MongoDB 컬렉션에 저장되는 document에 어떤 종류의 값이 들어가는지를 정의한다.

모델은 스키마를 기반으로 만들어지는 인스턴스이며, MongoDB 컬렉션에서 도큐먼트를 생성, 읽기, 업데이트, 삭제(CRUD)하는 데 사용된다.

 

나는 URL 단축 기능을 구현하기 위해 아래와 같이 스키마와 모델을 정의했다.

 

아래의 스키마는 title, url, shortUrl 필드를 가진다. 각 필드는 String type이고 기본값은 빈 문자열로 지정했다. timestamps: true 는 document의 생성 및 수정 시간을 자동으로 관리해주는 옵션이다.

// 수정 전

import mongoose from "mongoose";

const shortLinkSchema = new mongoose.Schema(
  {
    title: { type: String, default: "" },
    url: { type: String, default: "" },
    shortUrl: { type: String, default: "" },
  },
  {
    timestamps: true,
  }
);

const ShortLink =
  mongoose.model["ShortLink"] || mongoose.model("ShortLink", shortLinkSchema);

export default ShortLink;

 

 

 

이제 정의된 모델을 기반으로 CRUD로 데이터베이스에 저장할 수 있다.

이 과정에서 OverwriteModelError: Cannot overwrite `ShortLink` model once compiled. 에러를 만났다.

우선 수정 결과를 먼저 보자.

// 수정 후

import mongoose from "mongoose";

const shortLinkSchema = new mongoose.Schema(
  {
    title: { type: String, default: "" },
    url: { type: String, default: "" },
    shortUrl: { type: String, default: "" },
  },
  {
    timestamps: true,
  }
);

const ShortLink =
  mongoose.models["ShortLink"] || mongoose.model("ShortLink", shortLinkSchema);

export default ShortLink;

 

 

 

수정한 부분은 mongoose.model["ShortLink"]을 mongoose.models["ShortLink"]로 변경한 것이다.

const ShortLink =
  mongoose.models["ShortLink"] || mongoose.model("ShortLink", shortLinkSchema);

 

 

 

기존 코드에서는 mongoose.model["ShortLink"]를 사용하여 모델을 참조했다. 그러나 이는 잘못된 접근 방식이다. mongoose.model모델을 정의하거나 반환될 때 사용되며 함수이기 때문이다. 

mongoose.model(<Collectionname>, <CollectionSchema>)

// Collection name: It is the name of the collection.
// Collection Schema: It is the schema of the collection.

 

따라서 모델을 정의하거나 가져올 때는 mongoose.model('ModelName', schema)와 같은 형식을 사용하는데 이전의 잘못된 코드의 경우, mongoose.model["ModelName"] 와 같이 객체처럼 접근하여 undefined가 반환된다.

 

undefined를 반환하므로 오른쪽에 있는 mongoose.model("ShortLink", shortLinkSchema)가 실행되고, 이로 인해 새로운 모델이 정의된다.

 

만약 코드가 여러 번 실행된다면, Mongoose는 동일한 이름의 모델이 이미 존재함에도 불구하고 매번 새 모델을 정의하려고 한다. 이같은 이유로 Cannot overwrite ShortLink model once compiled. 에러가 발생한다.

 

mongoose.models는 모든 정의된 모델을 저장하는 객체이기 때문에, 이미 정의된 모델을 참조할 때 사용한다. 

const ShortLink =
  mongoose.models["ShortLink"] || mongoose.model("ShortLink", shortLinkSchema);

 

따라서 위와 같이 mongoose.models["ShortLink"]가 이미 정의된 모델을 반환하고, 정의되지 않은 경우에만 새로 정의하도록 하여 에러를 고칠 수 있다.