전통적인 relational DBMS가 서비스 확장의 부하를 견디지 못하는 상황에서 확장성을 고려한 제품이 필요한 시대가 도래하였습니다. 이러한 요구는 스마트폰, IOT(사물인터넷)등으로 인한 빅데이터 시대가 도래하면서 서버의 데이터 저장용량 뿐 아니라 사용자 증가에 대한 확장성을 요구하고 있기 때문입니다.
Table Of Contents
NoSQL의 급부상
설명드린것처럼 사용자 증가와 빅데이터에 대한 요구사항으로 인해서 확장성을 요구하는 시스템을 찾기 시작하였습니다. 그에따라, NoSQL이라는 제품은 DBMS의 ACID를 100% 보장하지 않지만, 확장성은 뛰어난 구조의 아키텍처를 찾아서 개발하였고, 고객에 요구에 따라 이러한 제품들이 선택되게 되었습니다.
NoSQL 개념과 데이터 처리 방식에 따른 분류
NoSQL이란 RDB 형태, 그리고 SQL을 사용하는 관계형 데이터베이스가 아닌 다른 형태의 데이터 저장 기술을 의미합니다.
또한 NoSQL에서는 RDBMS와는 달리 테이블 간 관계를 정의하지 않습니다.
데이터 테이블은 그냥 하나의 key를 갖는 테이블이며 테이블 간의 관계를 정의하지 않아 일반적으로 테이블 간 Join은 대부분 불가능합니다.
데이터와 트래픽이 기하급수적으로 증가함에 따라 RDBMS에 단점인 확장성과 성능을 향상시키기 위해 나타난 기술입니다.
이 기술은 비용을 크게 요구하며 확장에 한계가 있는 Scale-Up의 문제를 개선하기 위해 나온 기술입니다.
일관성은 포기하되 비용을 고려하여 여러 대의 데이터에 분산하여 저장하는 Scale-Out을 목표로 등장하였습니다.
확장성을 위해서, 하나의 Key로 분산하는 방식을 채택한 것입니다.
NoSQL을 하면 가장 유명한 Document 기반의 MongoDB를 많이 떠올리지만 MongoDB는 NoSQL한 종류로 NoSQL은 하기와 같이 다양한 형태의 저장 기술을 지원하고 있습니다.
이 다양한 형태의 저장기술은 RDBMS 스키마에 맞추어 데이터를 관리해야 된다는 제약없이 수평적 확장성(Scale-out)을 쉽게 할 수 있다는 장점을 가지고 있습니다.
1. Key-Value Database
- Key-Value Database는 데이터가 Key와 Value의 쌍으로 저장됩니다. Key는 Value에 접근하기 위한 용도로 사용되며, 값은 어떠한 형태의 데이터라도 담을 수 있습니다. 이미지나 비디오도 가능합니다. 또한 간단한 API를 제공하여 속도가 굉장히 빠른 편입니다.
- 대표적인 NoSQL Key-Value Model로는 Redis, Riak, Amazon Dynamo DB 등이 있다.
참고: https://db-engines.com/en/ranking/key-value+store
2. Document Database
- Document Database 데이터는 Key와 Document의 형태로 저장된다. Key-Value 모델과 다른 점이라면 Value가 계층적인 형태인 도큐먼트로 저장된다는 것이다. 객체지향에서의 객체와 유사하며, 이들은 하나의 단위로 취급되어 저장된다. 다시 말해 하나의 객체를 여러 개의 테이블에 나눠 저장할 필요가 없어진다는 뜻이다.
- 주요한 특징으로는 객체-관계 매핑이 필요하지 않다. 객체를 Document의 형태로 바로 저장 가능하기 때문이다. 또한 검색에 최적화되어 있는데, 이는 Ket-Value 모델의 특징과 동일하다.
- 단점이라면 사용이 번거롭고 쿼리가 SQL과는 다르다는 점이다. 도큐먼트 모델에서는 질의의 결과가 JSON이나 xml 형태로 출력되기 때문에 그 사용 방법이 RDBMS에서의 질의 결과를 사용하는 방법과 다르다.
- 대표적인 NoSQL Document Model로는 MongoDB, CouthDB 등이 있다.
참고: https://db-engines.com/en/ranking/document+store
참고: https://khj93.tistory.com/entry/Database-RDBMS와-NOSQL-차이점
레디스 CRUD
Java를 사용하여 Redis에 데이터를 삽입하고 키를 사용하여 해당 데이터를 검색하는 예제는 다음과 같습니다. 이 예제에서는 Jedis 라이브러리를 사용하며, 이를 사용하려면 먼저 의존성을 프로젝트에 추가해야 합니다.
import redis.clients.jedis.Jedis;
public class RedisExample {
public static void main(String[] args) {
// Redis 서버에 연결
Jedis jedis = new Jedis("localhost");
// 데이터 삽입
jedis.set("myKey", "Hello, Redis!");
// 데이터 검색
String value = jedis.get("myKey");
System.out.println("Retrieved value: " + value);
}
}
이 코드는 로컬에서 실행 중인 Redis 서버에 연결하고, "myKey"라는 키에 "Hello, Redis!"라는 값을 저장한 후, 해당 키를 사용하여 값을 검색합니다.
몽고 DB CRUD
몽고DB에서 테이블은 컬렉션이라고 부른다.
Date나 정규표현식 같은 자바스크립트 객체를 자료형으로 사용할 수 있고 , Binary Date, ObjectId, Int, Long, Decimal, Timestamp, JavaScript 등의 추가적인 자료형이 있다. ObjectId는 MySQL에서 기본키로 쓰이는 값과 비슷한 역할을 한다. 고유한 값을 가지므로 다큐먼트를 조회할 때 사용할 수 있다.
Java를 사용하여 MongoDB에 컬렉션을 생성하고 문서를 삽입한 후, 키를 사용하여 해당 문서를 검색하는 예제는 다음과 같습니다. 이 예제에서는 MongoDB Java Driver를 사용하며, 이를 사용하려면 먼저 의존성을 프로젝트에 추가해야 합니다.
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class MongoDBExample {
public static void main(String[] args) {
// MongoDB 서버에 연결
MongoClientURI uri = new MongoClientURI("mongodb://localhost:27017");
MongoClient mongoClient = new MongoClient(uri);
// 데이터베이스 선택
MongoDatabase database = mongoClient.getDatabase("myDatabase");
// 컬렉션 생성
database.createCollection("myCollection");
// 컬렉션 선택
MongoCollection<Document> collection = database.getCollection("myCollection");
// 문서 생성 및 삽입
Document doc = new Document("_id", "1")
.append("name", "MongoDB")
.append("type", "database")
.append("count", 1)
.append("info", new Document("x", 203).append("y", 102));
collection.insertOne(doc);
// 문서 검색
Document query = new Document("_id", "1");
Document foundDoc = collection.find(query).first();
System.out.println(foundDoc.toJson());
}
}
이 코드는 myDatabase라는 데이터베이스에 myCollection이라는 컬렉션을 생성하고, 그 컬렉션에 하나의 문서를 삽입한 후, _id 필드를 키로 사용하여 해당 문서를 검색합니다.
JavaScript를 사용하여 MongoDB에서 키가 아닌 다른 필드를 사용하여 문서를 검색하는 예제는 다음과 같습니다. 이 예제에서는 MongoDB Node.js Driver를 사용하며, 이를 사용하려면 먼저 의존성을 프로젝트에 추가해야 합니다.
const { MongoClient } = require('mongodb');
async function main() {
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);
try {
await client.connect();
const database = client.db('myDatabase');
const collection = database.collection('myCollection');
// 객체 저장
const doc = { _id: "1", name: "MongoDB", type: "database", count: 1, info: { x: 203, y: 102 } };
const result = await collection.insertOne(doc);
console.log(`Document inserted with _id: ${result.insertedId}`);
// 객체 검색
const query = { name: "MongoDB" };
const foundDoc = await collection.findOne(query);
console.log(foundDoc);
} finally {
await client.close();
}
}
main().catch(console.error);
이 코드는 myDatabase라는 데이터베이스에 myCollection이라는 컬렉션에 객체를 저장하고, “name” 필드를 사용하여 해당 문서를 검색합니다.
쿼리에 샤드 키가 포함되지 않은 경우, 몽고디비는 클러스터의 모든 샤드로 쿼리를 전달해야 합니다. 이러한 분산 수집 쿼리는 비효율적일 수 있습니다. 대규모 클러스터에서는 분산 수집 쿼리가 일상적인 작업에는 적합하지 않습니다.(https://www.mongodb.com/docs/manual/core/distributed-queries/)
Key 관련하여
MongoDB에서는 각 문서가 고유한 _id 필드를 가져야 합니다. 이 필드는 기본 키 역할을 합니다. 문서를 삽입할 때 _id 필드를 명시적으로 제공하지 않으면, MongoDB 드라이버는 자동으로 ObjectId를 생성하여 _id 필드에 할당합니다. 이는 upsert가 true인 업데이트 작업을 통해 삽입된 문서에도 적용됩니다.
upsert: update를 찾아보고 없으면 insert하는 기능
결론적으로, MongoDB에 키가 없는 문서를 삽입하는 것은 실질적으로 불가능합니다_id 필드가 없는 문서를 삽입하려고 하면 MongoDB가 자동으로 _id 필드를 생성합니다.
https://www.mongodb.com/docs/manual/tutorial/insert-documents/
NoSQL의 사용사례
가장 쉽게 찾아볼 수 있는 Key-Value와 Document를 모두 지원하는 AWS의 Dynamo의 사용사례를 볼 수 있습니다. 아마존 AWS의 Dynamo는 다음과 같은 다양한 사례와 고객을 유치하고 있습니다.
- 콘텐츠 메타데이터 및 캐시 용도
- 실시간 동영상 스트리밍 및 대화형 컨텐츠와 같은 워크로드의 동시성 및 처리량 개선
- 인터넷 쇼핑몰 장바구니, 재고추적, 고객 데이터 관리 작업 등 상대적으로 덜 미션 크리티컬한 소매 정보 처리
- 게임 데이터 처리