사이드 프로젝트에서 DB 스키마를 구성하려는데, 스키마 구성이 어떻게 될 지 정해지지 않아 일단 NoSQL로 로그 데이터를 저장하고자 하였습니다.
이때 가능한 솔루션들은 Firebase의 Realtime Database, MongoBD, DynamoDB 등이 있지만 Realtime Database와 DynamoDB는 클라우드 서비스다보니 설정 및 관리가 간?편하지만 사용량에 따라 요금이 부과되는 형태라 간단한 프로젝트에는 맞지 않다 생각하여 MongoDB를 선택하였습니다.
MongoDB는 컬렉션과 페이지로 나뉜다
RDBMS에서는 데이터베이스가 테이블로 구성되듯, MongoDB에서는 데이터베이스가 컬렉션(Collection)과 도큐먼트(Document)로 구성됩니다. 여기서 컬렉션은 테이블과 연관되고, 도큐먼트는 하나의 ROW와 연관되죠. 물론 정확히 1:1 매핑은 아니고, 처음 접할때는 이렇게 이해하면 됩니다.
document는 아래와 같습니다.

컬렉션은 document들이 배열처럼 들어가있다 생각하면 됩니다!
왜 위와 같이 이해하면 되는가?
RDBMS에서 할 수 있는 대부분의 작업들을 할 수 있기 때문입니다.
예를 들면...
그럼 어느 것을 주의하면 되는가?
NoSQL은 어느 값이든 넣을 수 있다, MongoDB는 한 도큐먼트의 크기가 16MB로 제한되어있다
즉,
1. 데이터가 난잡하지 않게 어느정도는 설계를 해야하고
2. 한 도큐먼트, 즉 JSON의 크기가 16MB를 넘지 않아야 한다.
이것만 지켜준다면 크게 문제는 없습니다
MongoDB는 어느 값이든 넣을 수 있다
MongoDB는 BSON이라고 불리는 Binary JSON 형식을 따르고 있습니다. JSON이 사람이 보기 좋으라고 해놓은 형식이라면, BSON은 컴퓨터가 저장하고 파싱하기 편한 형식입니다. 따라서 JSON보다 빠르죠!
하지만 걱정하지 않아도 되는 것이, 데이터를 넣을 때는 JSON 형식으로 넣어주고, MongoDB가 처리할 때는 BSON으로 처리합니다. 사용자에게 보여줄 때는 Driver를 통해 JSON으로 변환하기에 BSON 파싱 로직도 만들 필요가 없고요!
이 말은 곧, MongoDB는 문자열, 숫자, 날짜, 배열, 객체뿐 아니라 Binary 데이터나 ObjectId, 정수 타입 구분 등 JSON이 직접 지원하지 않는 값들도 저장할 수 있다는 뜻입니다.
하지만 이런 강력한 기능에는 큰 힘이 따르는 법. 도큐먼트, 즉 하나의 BSON은 최대 크기가 16MB입니다. 하나의 족쇄인 것이죠.
다행인 점은 이 제약 조건은 컬렉션에는 적용되지 않는다는 점입니다. 따라서 한 컬렉션에 수십,수백만개의 도큐먼트를 넣는다고 해도 큰 문제가 없죠! 조회 시 느려지는 것은 어쩔 수 없지만요...
docker image pull
docker pull mongo
# mongo:latest로 pull
# docker-compose.yaml
services:
mongodb:
image: mongo:latest
container_name: mongodb
ports:
- 27017:27017
restart: always
environment:
- MONGO_INITDB_ROOT_USERNAME=root # 나중에
- MONGO_INITDB_ROOT_PASSWORD=root # 바꿀것!
container 진입
docker exec -it mongodb /bin/bash
mongosh -u USERNAME -p PASSWORD
db 선택 및 collection 생성
> show dbs
admin 100.00 KiB
config 48.00 KiB
local 72.00 KiB
# 기본은 위와 같이 admin, config, local 3개밖에 없음
# 사용할 DB 선택, 이 시점에서는 DB가 없다면 생성되지 않음
> use DB_NAME
# 컬렉션 생성, 이 시점에 DB 생성
> db.createCollection(COLLECTION_NAME)
# 컬렉션에 데이터 삽입
> db.COLLECTION_NAME.insertOne(JSON_OBJECT)
# 컬렉션에 인덱스 생성. 2번째 인자는 Optional 인자
# 첫번째 인자의 value들의 값은
# 1: 오름차순
# -1: 내림차순
> db.COLLECTION_NAME.createIndex({ KEY: 1 }, { unique: true })
# 컬렉션의 인덱스 삭제. 2가지 방식 모두 사용 가능
> db.COLLECTION_NAME.dropIndex(INDEX_NAME)
> db.COLLECTION_NAME.dropIndex({ key: 1})
없는 내용만 넣는 방법?
직접 지원하는 것은 없습니다. 하지만 다른 방법으로 할 순 있죠.
만약 unique 제약조건이 있는 키라면
db.comments.insertMany([Objects], { ordered: false }) 를 쓰면 되긴 합니다. 하지만 오류가 계속 쌓이는 구조라 추천하지는 않습니다.