티스토리 뷰
목차
_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
- RX100M5
- Backjoon
- 유럽여행
- 세계일주
- 파이썬
- 기술면접
- 여행
- 면접 준비
- Algorithm
- BOJ
- java
- spring
- 스프링
- 맛집
- 자바
- 리스트
- 스트림
- a6000
- 세계여행
- 유럽
- 칼이사
- 남미
- 백준
- 세모
- 알고리즘
- 동적계획법
- 야경
- 지지
- 중남미
- Python
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |