티스토리 뷰

728x90
반응형

목차

     

    _id

    몽고디비는 컬렉션에 도큐먼트가 생성될 때마다 자동으로 생성되는 고유한 필드로,

    ObjectId라는 특수한 데이터 타입을 가진다.

    이 타입은 12바이트의 숫자, 정확하게는 24글자의 16진수로 표현된다.

     

    이 숫자는 다시 네 개의 요소로 나뉘는데, 각 요소에 대한 설명은 다음과 같다.

     

    • Timestamp: ObjectId가 생성된 시간. 이를 이용한 시간순 정렬도 가능
    • Machine ID: 디비가 돌아가는 머신(컴퓨터)의 식별자이다. 이를 이용해 같은 머신에서 생성된 객체를 구별할 수 있다.
    • Process ID: 몽고디비 프로세스의 ID. 동일한 머신에서 돌아가는 다른 몽고디비 프로세스가 생성한 객체와 구별할 수 있다.
    • Counter: 랜덤값으로 시작하는 카운터 값이다. 동일한 시간, 머신, 프로세스에서 생성된 객체를 구별할 수 있다.

    이러한 구조를 가진 덕분에 도큐먼트의 고유성, 생성시점 등의 정보를 읽어낼 수 있다.

    이대로 _id를 식별자로 사용해도 되지만, 개발자 혹은 환경에 따라 기존과 같은 순차적인 식별자(ex. seq)가 필요할 때가 있다.

    그 이유는 크게 아래의 세 가지 정도가 있다.

     

    • 디비 간 마이그레이션: SQL 기반 디비를 사용하다가 몽고로 마이그레이션 하는 경우, 사용하던 ID를 그대로 사용하고 싶다.
    • 가독성: '_id'는 사람이 한눈에 파악하기 어렵다. 반면 증가하는 숫자로 된 ID는 읽기도 관리하기도 쉽다.
    • 편의성
      위와 비슷하지만 조금 더 현실적인데, '_id'와 같은 값을 URL에 넣기는 힘들다. 특히 RESTful API 설계에는
      숫자로 된 자동 증가하는 ID가 유용하다.

    추가로 회사에 들어와서 배운 거지만, 당연하게 별개의 아이디를 만들어 관리하는 것 같았다.

     

    그래서 이어지는 글에서는 Node.js 환경에서 몽고디비를 사용할 때, 자동 증가하는 PK를 별개로 생성하는 법을 알아본다.

     

    Auto-Increment

     

    이 글에선 Node.js와 타입스크립트를 사용하고 있으며, 각 개발환경 및 mongoose 라이브러리는 이미 설치되었다 가정한다.

     

    노드와 몽구스에서 자동 증가를 구현하는 방법을 검색하면 몇 가지 라이브러리가 나오지만, 

     

    모두 몽구스 최신버전과는 호환성 문제가 있다고 한다. 왜 그런가 해서 좀 더 알아보니 몽구스에서 자체적으로

     

    자동 증가 기능을 포함시켰다고.

     

    따라서 몽구스 최신버전이 설치되어 있다면 추가로 뭔가 더 설치할 필요는 없다.

     

    자신이 사용하는 모델 모듈에 다음과 같이 추가한다.

    import mongoose, { Schema, Document, Model } from 'mongoose';
    
    interface IFeed extends Document {
      seq: number;
      title: string;
      body: string;
    }
    
    const feedSchema: Schema<IFeed> = new Schema({
      seq: { type: Number, unique: true, required: true, default: 1 },
      title: { type: String, required: true },
      body: { type: String, required: true },
    });
    
    feedSchema.pre('save', async function (next) {
      if (this.isNew) {
        const FeedModel = this.constructor as Model<IFeed>;
        const lastFeed = await FeedModel.findOne({}, {}, { sort: { seq: -1 } });
        if (lastFeed) {
          this.seq = lastFeed.seq + 1;
        }
      }
      next();
    });
    
    const Feed = mongoose.model('Feed', feedSchema);
    
    export default Feed;

    기존의 모듈에서 추가한 부분에 대해서 짧게 설명해 보겠다.

      seq: number;
    ...
      seq: { type: Number, unique: true, required: true, default: 1 },

    자동 증가를 구현할 필드를 인터페이스와 스키마에 추가한다. 기본값을 1로 주어야 한다.

    feedSchema.pre('save', async function (next) {
      if (this.isNew) {
        const FeedModel = this.constructor as Model<IFeed>;
        const lastFeed = await FeedModel.findOne({}, {}, { sort: { seq: -1 } });
        if (lastFeed) {
          this.seq = lastFeed.seq + 1;
        }
      }
      next();
    });

    위 코드는 'pre'를 사용해서 'save'가 호출되기 전에 실행되는 미들웨어이다.

     

    새로운 문서가 저장되는 로직 이전에 직전 문서의 seq 필드 값을 가져와 1 증가시킨 뒤 현재 문서에 갱신한다.

     

    위와 같이 수정한 뒤 서버를 다시 올리고 문서를 저장하면 정상적으로 자동 증가가 되는 것을 확인할 수 있다.

     

    반응형

    'Development > Database' 카테고리의 다른 글

    [Database]postgreSQL  (0) 2023.10.18
    [DB]Vector DB  (0) 2023.09.19
    [Database]NoSQL(mongoDB)에서 1:N, N:M 구현  (0) 2023.07.09
    [Database]MariaDB  (0) 2023.05.10
    [Database]WebFlux에서 R2DBC 기본설정  (0) 2023.05.06
    [Database]SQLite  (0) 2023.04.07
    댓글
    공지사항
    최근에 올라온 글
    최근에 달린 댓글
    Total
    Today
    Yesterday
    링크
    «   2024/11   »
    1 2
    3 4 5 6 7 8 9
    10 11 12 13 14 15 16
    17 18 19 20 21 22 23
    24 25 26 27 28 29 30
    글 보관함