NoSQL은
데이터 양이 급격하게 증가하면서 기존 RDBMS로는 데이터베이스 서버의 확장이 어려운 경향이 있습니다. 확장이 가능하지만 수직적 확장으로 인해 비용이 더 늘어나는 구조인 RDBMS로는 한계가 있습니다.
또한, 현대 어플리케이션이 복잡해지면서 데이터 구조가 자주 변경되고 다양한 데이터 구조가 요구되기 때문에 기존 RDBMS에서 저장할 수 있는 형태에 한계가 발생했습니다.
이러한 현대적 경향으로 확장성과 비정형 데이터를 저장하는 NoSQL (Not Only SQL) 가 등장하였습니다.
NoSQL의 대표적인 특징은 확장성과 가용성입니다. 데이터 모델이 유연하고 스키마를 따로 작성할 필요 없이 다양한 데이터를 저장할 수 있고, 수평적으로 확장이 가능합니다. 키-값 쌍, 문서, 그래프, 열 기반 등 다양한 데이터 유형을 저장할 수 있습니다. 따로 고정된 스키마가 없기 때문에 수평적 확장, 즉 많은 서버를 실행시켜 데이터 서버의 용량을 키우기 수월합니다. 수평적 확장이 있음은 가용성으로 이어지기도 합니다. 다양한 서버에서 사용 가능하기 때문에 한 서버에서 에러가 발생해도 타 지역 서버는 얼마간 사용 가능합니다. 그러나 이러한 경향으로 같은 데이터를 중복해서 저장해야 한다는 점과, 업데이트 시 모든 DB에 업데이트되는 데 시간이 걸린다는 특징이 있습니다. 또한 읽기/쓰기 성능이 빠르기 때문에 실시간 어플리케이션이나 빅데이터 처리에 적합한 데이터베이스라고 할 수 있어 현대 어플리케이션 개발에 필수적이라고 할 수 있습니다.
MongoDB는 이러한 구조로 되어 있습니다.
이름 | 설명 | RDBMS 비교 |
---|---|---|
Document | 데이터 저장 기본 단위,키-값 쌍으로 구성됩니다. | 튜플 |
Collection | Document들의 집합으로, 스키마가 유연합니다. | 테이블 |
Database | Collection들의 집합으로, MongoDB에서 최상위 구조를 가집니다. | DB |
* _id | Document가 Collection 단위로 갖는 고유 값 | 튜플의 PK |
MongoDB는 NoSQL로써, RDBMS와 같은 ACID 트랜잭션을 지원하지 않습니다. 단일 Document 트랜잭션, 즉 여러 필드의 업데이트는 가능하지만 여러 Document의 동시 업데이트는 MongoDB 버전에 따라 제한된 기능으로 사용해야 합니다. 따라서 조인 연산이 필요하지 않도록 관련 데이터들을 하나의 Document에 묶는(Embed) 방식으로 진행하는 것이 NoSQL에서는 더 효율적입니다.
MongoDB가 다양한 데이터 타입을 저장할 수 있는 것은 binary json, 이진 데이터 형식으로 인코딩하여 저장하기 때문입니다.
내용 | 쿼리 |
---|---|
db 생성 및 선택 | use db |
컬렉션 생성 | db.createCollections(”mangoc”) |
단일 문서 삽입 | db.mangoc.insertOne({ key1: “value1”, key2: “value2”}) |
단일 문서 삭제 | db.mangoc.deleteOne({key: “key1”}) |
collection 내 모든 문서 조회 | db.mangoc.find() |
collection 내 조건부 문서 조회 | db.mangoc.find({key:”key1”}) |
집계 쿼리 | db.mangoc.aggregate([ { match : {key: key1”}}, // 조건 { $group: {_id : “group_key”, total: {amount”}}} // 그룹화 및 합계]) |
Redis는 키-값 구조로 비정형 데이터를 저장합니다. Redis가 유명한 이유 중 하나는 인메모리 DB이기 때문입니다. 디스크가 아닌 메모리에 저장하여 CPU와의 통신이 디스크에서보다 훨씬 빠르기 때문에 빠르게 조회해야 하거나 많은 양은 아니지만 실시간으로 처리해야 하는 기능이 있을 때 유용하게 사용될 수 있습니다. 주로 세션 정보를 저장하고 빠르게 로그인 정보를 확인하는 데 많이 사용되며, 실시간 통신에도 유용합니다.
Redis의 구조는 다음과 같습니다.
이름 | 설명 | RDBMS 비교 |
---|---|---|
Key | 데이터 구분 pk, 각 키는 db 안에서 유일해야 하고, 문자열, 해시, 리스트, 집합 등 다양한 타입이 가능함 | pk |
Value | 데이터. 문자열, json, 바이너리 등 다양한 형식의 데이터가 저장이 가능함 | 테이블 |
DB | 데이터베이스 | DB |
mongodb는 mysql 사용하듯, spring 프로젝트에서 mongodb 관련 dependency를 추가한 후 MongoRepository 인터페이스를 사용해 JPA ORM과 연계하여 사용합니다. MongoDB의 GUI 도구인 Compass를 사용해 확인하면 실제로는 BSON 형태로 저장되어 있는 데이터를 JSON 형태로 확인할 수 있습니다.
yml 설정은 단순히
data:
mongodb:
host: localhost
port : 27017
database: [db 이름, 생성되어있어야 한다]
다음과 같이 작성하면 되고 기본 port는 27017입니다.
Redis역시 redis 설치 후 의존성을 추가합니다. Redis는 ORM을 사용하지 않고 CLI나 Lettuce, Jedis 등 클라이언트 라이브러리를 따로 사용합니다.(이것은 redis dependency를 사용하면 자동으로 사용할 수 있습니다) 그 이유는 redis는 키-값 형태로 매우 단순하고 SET, GET, INCR, ZADD
등 고유한 명령어를 사용하며, Pub/Sub 등의 기능과 같이 기존 데이터베이스와 다소 다른 데이터베이스 시스템이기 때문에 복잡한 쿼리를 구성하여 여러 테이블이나 Collection을 연계하여 다루는 데에 최적화되어 있는 ORM은 Redis에서 사용하기 적합하지 않습니다. 따라서 cli를 따로 사용하여 직접적으로 빠르게 전송하게 됩니다. 이러한 설정은 spring에서 제공하는 @Configuration 어노테이션을 사용해 redis template, redis client를 정의할 수 있습니다. 기본 port는 6379 이며, redisTemplate를 활용해 redis에 명령어를 보내는 방식은 기존 rds와 통신하는 방식과 상당히 다른 함수를 사용합니다.
몇 가지 간단한 예시를 보자면 다음과 같은 함수들을 사용합니다.
내용 | 함수 |
---|---|
단일 키에 값 저장 | redisTemplate.opsForValue().set(”key1”,”value1”); |
단일 키 값 조회 | String value = redisTemplate.opsForValue().get(”key1”); |
단일 키 값 삭제 | redisTemplate.delete(”key1”); |
→ 쿼리 속도가 빠른 임시 데이터 스토리지의 경우 Redis를 사용하세요. 풍부한 쿼리를 지원하면서 복잡한 데이터를 장기간 영구 저장하고 더 높은 수준의 가용성을 요구하는 경우 MongoDB를 사용하세요. - AWS [Redis와 MongoDB의 차이점은 무엇인가요?]