이번에 혼자 `WebSocket`, `SockJS`, `STOMP`에 관해 학습을 진행하며
채팅 서비스를 개발하는 것을 목표로 정했다.
이때 채팅 메시지에 관한 영구 저장소를 선택하기 위해 고민을 했는데 처음 떠오르고 선택하게 된 것은 `MongoDB`이다.
대부분?의 사람들이 알고 있듯 채팅하면 `MongoDB`라는 말은 많이 들었을 것이다.
하지만, 알고만 있고 그 이유는 특별하게 몰랐다.
또한, 여태까지 `NoSQL` DB는 `Redis`만 사용해왔기에 `MongoDB`는 새로운 접근이였다.
그래서 `MongoDB`에 관해 알게 된 내용들을 정리하려 한다.
MongoDB란?
`MongoDB`는 문서 지향적인 `NoSQL` 데이터베이스로, 대량의 비정형 데이터를 저장하고 처리하는 데 사용된다.
문서 지향적이란?
문서 지향적(`Document-oriented`)이란 데이터베이스 시스템의 한 종류이다.
`MongoDB`에서는 비정형 데이터를 저장하고 관리하기 위해 문서(`Document`)라는 개념을 중심으로 데이터를 구성한다.
// 데이터베이스 선택
MongoDatabase database = mongoClient.getDatabase("mydatabase");
// 컬렉션 선택
MongoCollection<Document> collection = database.getCollection("mycollection");
// 새로운 문서 생성
Document document = new Document("name", "John")
.append("age", 30)
.append("email", "john@example.com");
// 문서 삽입
collection.insertOne(document);
System.out.println("새로운 문서가 삽입되었습니다. ID: " + document.get("_id"));
위의 코드 처럼 새로운 `document`를 생성한 후, `colleciton`에 직접적으로 삽입할 수 있다.
위의 코드를 실행하면 다음과 같은 `document`가 생성된다.
{
"name": "John",
"age": 30,
"email": "john@example.com"
}
컬렉션(Colleciton)이란?
컬렉션(`Collection`)은, 비정형 데이터인 문서(`Document`)들의 그룹이다.
비슷한 유형의 문서들을 논리적으로 모아서 저장하는 단위라고 할 수 있다.
아래의 코드는 `Person document`이다.
`id`, `name`, `gender`, `age`, `address`라는 field를 만들고 데이터를 저장한다.
{
"_id": ObjectId("61e0d934a4b2d43e3aef3e6f"),
"name": "John",
"gender": "남",
"age": 30,
"address": "New York"
}
중괄호로 둘러싸인 부분이 하나의 문서이며, 아래와 같이 3개의 문서가 1개의 `collection`을 이룬다.
주의할 점은, 하나의 `colletion`에 있는 각 문서는 동일한 `field`를 가져야 한다는 것이다.
(물론, 필드가 추가돼도 저장은 잘 된다)
[
{
"_id": ObjectId("61e0d934a4b2d43e3aef3e6f"),
"name": "John",
"gender": "남",
"age": 30,
"address": "New York"
},
{
"_id": ObjectId("61e0d934a4b2d43e3aef3e70"),
"name": "Alice",
"gender": "여",
"age": 25,
"address": "London"
},
{
"_id": ObjectId("61e0d934a4b2d43e3aef3e71"),
"name": "Michael",
"gender": "남",
"age": 35,
"address": "Los Angeles"
}
]
NoSQL 이란?
NoSQL은 "Not Only SQL"의 약어이다.
관계형 데이터베이스(MySQL 등)와 달리 쿼리가 아닌 메소드를 사용한다.
예를 들어 `Document` 클래스를 사용하여 문서를 생성하고 필드와 값을 추가하며,
`insertOne()`, `find()`, `updateOne()`, `deleteOne()` 등의 메소드를 사용하여 데이터를 조작한다.
비정형 데이터란?
`MongoDB`는 `JSON `형식의 문서로 데이터를 저장한다.
문서는 `BSON(Binary JSON)` 형태로 저장되며, 하나의 문서에는 여러 필드와 값이 포함될 수 있다.
따라서, 애플리케이션의 요구사항에 맞게 데이터를 조직화할 수 있는 장점이 있다.
`MongoDB`는 여러 개의 문서를 하나의 컬렉션으로 그룹화한다.
컬렉션은 `RDBMS`의 테이블에 해당하며, 각 문서는 유일한 식별자인 `ObjectId`를 갖는다.
이 `ObjectId`는 자동으로 생성되며, 각 문서를 고유하게 식별하는 데 사용된다.
BSON 이란?
`BSON`은 `MongoDB`에서 사용되는 이진 직렬화 형식으로,
`원격 프로시저 호출(RPC)`과 같은 분산 시스템에서 데이터를 저장하고 전송하기 위해 만들어졌다.
이진 형식이기 때문에 텍스트 형식보다 적은 용량을 사용하며, 처리 속도가 빠르다.
또한, 길이 정보가 포함되어 있어 `데이터 트래버스`를 용이하게 한다.
`BSON`은 문자열, 숫자(정수, 부동 소수점, 십진수), 날짜, 이진 데이터, ObjectId 등 다양한 데이터 유형을 지원하고,
이러한 데이터 유형을 효율적으로 저장할 수 있으며 이 덕분에 데이터를 빠르게 찾고 처리할 수 있다.
`Bson`에서 제공하는 타입에 대해서는 아래 링크에서 자세하게 확인이 가능하다.
좀 더 자세히 살펴 보자면
원격 프로시저 호출(RPC)은 한 시스템에서 다른 시스템의 프로시저(함수)를 호출할 수 있게 해주는 프로토콜이다.
분산 시스템에서는 시스템 간의 상호 작용이 필요하기 때문에 `RPC`가 자주 사용된다.
예를 들어, 두 개의 서비스가 서로 통신해야 하는 상황을 생각해보자.
한 서비스는 상품 데이터를 저장하고 있는 `MongoDB`를 사용하고,
다른 서비스는 상품 검색 기능을 제공하는 `Postgres`를 사용한다.
이 상황에서 두 서비스가 서로 통신하려면, 각 서비스의 데이터를 직렬화하고 이해할 수 있는 형식으로 전송해야 한다.
이 때 BSON의 장점이 나타난다.
- 이진 직렬화: `BSON`은 이진 형식으로 데이터를 직렬화하므로, 데이터의 크기가 작아진다.
이로 인해 데이터 전송 시 소요되는 시간이 줄어들어 시스템 간의 통신이 빠르게 이루어질 수 있다.
이는 특히 대용량 데이터를 전송해야 하는 경우에 유리하다. - 처리 속도: `BSON`은 이진 형식으로 인해 처리 속도가 빠르다고 앞서 언급했다.
서로 다른 시스템 간의 통신에서 데이터를 받아들이고 처리하는 속도가 빠르다면 전체 응답 시간이 감소하게 된다. - 다양한 데이터 유형 지원: `BSON`은 문자열, 숫자(정수, 부동 소수점, 십진수), 날짜, 이진 데이터, ObjectId 등 다양한 데이터 유형을 지원한다.
이로 인해 서로 다른 시스템 간에 다양한 데이터 유형을 쉽게 전송하고 저장할 수 있다.
이진 직렬화 형식은 데이터를 이진 형태로 변환하여 저장하거나 전송하는 방식으로,
텍스트 형식에 비해 저장 공간을 효율적으로 사용하고 처리 속도가 빠르다.
이진 직렬화 형식은 트래버스, 즉 데이터 구조를 순회하거나 탐색하는 것이 쉽기 때문에
BSON 데이터를 빠르게 찾고 처리할 수 있다.
인코딩 및 디코딩 과정에서 BSON은 높은 성능을 보인다.
이진 형식 덕분에 처리 속도가 빠르며, 길이 정보가 포함되어 있어 데이터의 시작과 끝을 쉽게 파악할 수 있다.
이러한 특징들로 인해 `BSON`은 `MongoDB`에서 뛰어난 성능을 발휘한다.
하지만,
BSON 자체의 사용으로 데이터 용량이 다른 데이터베이스 형식에 비해서는 상대적으로 크다.
BSON의 데이터 용량 관련 특성
`BSON`의 데이터 용량이 다른 데이터베이스 형식에 비해 상대적으로 큰 이유는
데이터 구조 정보를 포함하고 있기 때문이다.
`BSON`은 각 필드에 대해 데이터 유형, 필드 이름, 길이 등의 메타데이터를 추가로 저장한다.
이로 인해 텍스트 형식보다 크기는 작을 수 있지만,
`JSON`과 비교했을 때 `JSON`의 간단한 구조와 달리 `BSON`의 메타데이터가 용량을 증가시킨다.
- 메타데이터 포함: `BSON`은 각 데이터 항목에 데이터 타입과 길이 정보를 저장한다.
- 이를 통해 `MongoDB`에서 `BSON` 데이터를 빠르게 탐색하고 수정할 수 있지만, 추가 메타데이터가 데이터의 총 크기를 증가시킨다.
- 텍스트 형식 대비 효율성: `BSON`은 이진 형식이므로 `JSON`과 같은 텍스트 형식보다 저장과 전송에 있어 더 효율적이다.
- 이는 텍스트 기반의 `JSON` 형식에서 발생하는 불필요한 공백이나 들여쓰기와 같은 요소를 제거하기 때문이다.
- 다른 데이터베이스와의 비교: `JSON`을 저장하는 데이터베이스나 압축 기술을 사용하는 다른 형식보다 `BSON`은 더 많은 공간을 차지할 수 있다.
- `BSON`은 속도와 효율성에 중점을 두고 설계되었으며, 특히 `MongoDB`에서 빠른 읽기 및 쓰기 작업을 지원하는 데 최적화되어있다.
MongoDB의 특징 3가지
- 문서 지향적(Document-Oriented)
JSON 형식의 문서를 중심으로 데이터를 저장한다. - 스케일아웃 가능(Scalable)
분산 아키텍처로 수평적인 확장이 가능하며 대용량 데이터 처리에 용이하다. - 유연한 데이터 모델(Flexible Schema)
스키마를 사전에 정의하지 않고 유연하게 데이터를 저장하고 수정할 수 있다.
MongoDB의 장단점
장점
스키마-리스 디자인
RDBMS는 데이터 요구 사항이 변경될 때 미리 정의된 스키마를 필요로 하는 것과 다르게,
몽고디비의 유연한 스키마 디자인은 데이터 요구 사항이 변경될 때 매끄럽게 적응할 수 있도록 한다.
이는 희소한 데이터 소스 또는 변경되는 데이터 모델을 갖는 애플리케이션에서 특히 유용하다.
확장성
몽고디비는 `read` 기능에 대한 확장을 위한 레플리카 세트와 `write` 확장을 위한 샤딩을 제공하여 수평적 확장에서 뛰어나다.
이 기능은 여러 대의 컴퓨터에 데이터를 분산하여 성능과 오류 허용성을 향상시키는 데 도움이 된다.
반면 `RDBMS` 솔루션은 비슷한 수준의 확장성을 달성하기 위해 비싼 하드웨어 업그레이드를 필요로 한다.
확장성 샤딩을 통해 수평적 확장을 지원한다.
높은 성능 인덱싱, 캐싱 및 메모리 내 저장을 지원하여 빠른 쿼리 처리가 가능하다.
높은 가용성 `replica sets`을 지원함.
단점
트랜잭션 지원의 한계
`MongoDB`는 다중 `document` 트랜잭션을 지원하지만, 관계형 데이터베이스와 같이 엄격하지 않다.
`MongoDB`의 트랜잭션 처리는 `ACID`가 아닌 `BASE` 기반이다.
이러한 차이로 인해, `MongoDB`의 트랜잭션 처리는 관계형 데이터베이스의
엄격한 `ACID` 트랜잭션 처리와 비교하여 덜 엄격하게 수행된다.
`ACID`(원자성, 일관성, 고립성, 지속성)는 데이터베이스 트랜잭션 처리의 전통적인 특성이다.
`ACID` 트랜잭션은 데이터의 일관성을 보장하고, 복잡한 트랜잭션 처리를 안전하게 수행할 수 있도록 한다.
관계형 데이터베이스는 `ACID`를 기반으로 하여 엄격한 트랜잭션 처리를 제공한다.
반면, `MongoDB`는 `BASE`(Basically Available, Soft state, Eventual consistency)를 기반으로 한다.
`BASE` 기반의 트랜잭션 처리는 `ACID`보다 느슨한 일관성 모델을 사용하며,
높은 가용성과 분산 시스템에 적합한 성능을 목표로 한다.
`MongoDB`에서의 `BASE` 기반 트랜잭션 처리는 다음과 같은 특징을 갖는다.
- 기본적으로 사용 가능(Basically Available): 시스템은 항상 응답을 제공하며, 일시적인 고장이나 네트워크 지연에도 높은 가용성을 유지한다.
- 소프트 상태(Soft state): 시스템의 상태는 시간에 따라 변할 수 있으며, 일관성이 항상 보장되지 않는다.
- 최종 일관성(Eventual consistency): 시스템은 일정 시간이 지난 후에야 최종적으로 일관된 상태를 달성한다.
이러한 `BASE` 기반 트랜잭션 처리의 특성 때문에,
`MongoDB`는 높은 성능과 확장성을 제공할 수 있지만,
관계형 데이터베이스의 ACID 트랜잭션 처리만큼 엄격한 트랜잭션 처리를 보장하지 않는다.
대용량 데이터 저장
`BSON` 형식으로 인해 다른 데이터베이스에 비해 저장 공간이 더 많이 필요할 수 있다.
특히 대량의 작은 `Document`를 다룰 때 더 그렇다.
모든 용도에는 적합하지 않다.
`MongoDB`는 구조화되지 않은 데이터를 처리하는 데 우수하지만,
복잡한 트랜잭션, 엄격한 일관성 또는 전통적인 조인 연산이 필요한 애플리케이션에는 적합하지 않을 수 있다.
참고
https://colevelup.tistory.com/45