본문 바로가기
컴퓨터과학

NoSQL 데이터베이스 설계 (MongoDB, Cassandra) – 최적의 설계 전략

by 코드그래피 2025. 1. 30.
반응형

데이터베이스는 현대 IT 시스템의 핵심 요소이며, NoSQL 데이터베이스는 대규모 데이터를 유연하고 효율적으로 처리하는 데 강력한 도구가 됩니다. 본 글에서는 MongoDBCassandra를 중심으로 NoSQL 데이터베이스의 개념, 장점, 설계 원칙, 그리고 실제 활용 사례를 다루겠습니다.

 

1. NoSQL 데이터베이스란?

 

NoSQL은 “Not Only SQL“의 약자로, 관계형 데이터베이스(RDBMS)와 달리 스키마리스(Schema-less) 구조와 수평적 확장(Scale-out) 기능을 지원하는 데이터베이스를 의미합니다. 일반적으로 다음과 같은 특징을 가집니다.

비정형 및 반정형 데이터 저장: JSON, XML, Key-Value, Wide-column 형식으로 데이터를 저장.

유연한 스키마: 사전 정의된 테이블 구조 없이 데이터를 동적으로 저장 가능.

수평적 확장: 샤딩(Sharding)과 복제(Replication)를 통해 확장 용이.

고성능 처리: 대량의 읽기/쓰기 작업을 빠르게 처리.

 

대표적인 NoSQL 유형에는 문서(Document)형, 키-값(Key-Value)형, 열(Column)형, 그래프(Graph)형이 있으며, MongoDB와 Cassandra는 각각 문서형과 열형 데이터베이스를 대표합니다.

2. MongoDB 개요 및 설계 원칙

 

MongoDB란?

 

MongoDB는 문서(Document) 기반의 NoSQL 데이터베이스로, JSON과 유사한 BSON 포맷을 사용하여 데이터를 저장합니다. 유연한 스키마와 강력한 쿼리 기능 덕분에 웹 애플리케이션, 빅데이터 처리, IoT 시스템에서 많이 사용됩니다.

 

MongoDB의 주요 특징

  • 스키마리스 구조: 컬렉션(Collection) 내 문서(Document)마다 다른 필드를 가질 수 있음.
  • 강력한 인덱싱: B-tree 기반의 인덱싱과 복합 인덱스를 지원.
  • 샤딩 및 복제: 데이터 노드를 자동으로 분산하여 고가용성을 보장.
  • Aggregation Framework: 강력한 데이터 분석 기능 제공.

 

MongoDB 설계 원칙

 

1) 문서 구조 최적화

 

MongoDB는 데이터를 JSON 문서 형태로 저장하므로, 데이터 모델을 어떻게 구성하느냐가 성능에 직접적인 영향을 줍니다.

  • 중첩(Nesting) vs. 참조(Referencing)
  • 중첩(Nested Documents): 관계가 깊은 데이터를 한 문서에 저장.
  • 참조(Referenced Documents): 데이터 중복을 줄이고 개별적으로 관리할 필요가 있을 경우.

예를 들어, 전자상거래 시스템의 주문 정보를 저장하는 방법을 보면:

중첩 방식:

{
  "order_id": "12345",
  "customer": { "name": "홍길동", "email": "hong@example.com" },
  "items": [
    { "product": "노트북", "price": 1500000 },
    { "product": "마우스", "price": 25000 }
  ]
}

 

참조 방식:

{
  "order_id": "12345",
  "customer_id": "67890",
  "items": ["98765", "87654"]
}

 

2) 샤딩(Sharding) 전략

 

MongoDB는 샤딩을 통해 데이터 수평 분할(Scale-out)이 가능합니다. 샤딩 키(Sharding Key)를 잘 선택해야 성능 최적화가 가능합니다.

  • 해시 샤딩(Hash Sharding): 데이터 균등 분배 (장점: 균등 분포, 단점: 범위 쿼리 비효율)
  • 범위 샤딩(Range Sharding): 특정 범위 기준으로 데이터 배치 (장점: 범위 쿼리 효율, 단점: 특정 샤드에 부하 집중)

 

3) 복제(Replication) 및 인덱싱 최적화

  • 복제 세트(Replica Set)를 사용하여 장애 발생 시 자동 페일오버(Failover) 지원.
  • 인덱스 최적화를 위해 Compound Index, TTL Index를 활용.

3. Cassandra 개요 및 설계 원칙

 

Cassandra란?

 

Cassandra는 분산형(NoSQL) 컬럼 패밀리 데이터베이스로, Facebook에서 개발하여 오픈소스로 공개된 이후, 대규모 데이터 처리에 강한 성능을 제공하는 데이터베이스입니다.

 

Cassandra의 주요 특징

  • 완전한 분산형(Decentralized): 특정 마스터 노드 없이 모든 노드가 동일한 역할을 수행.
  • 수평적 확장(Linear Scalability): 노드 추가만으로 성능 확장 가능.
  • 고가용성(High Availability): 여러 데이터 센터에 복제 가능.
  • 튜닝 가능한 일관성(Consistency): QUORUM, ONE, ALL 등의 일관성 수준 설정 가능.

 

Cassandra 설계 원칙

 

1) 테이블 구조 설계

 

Cassandra는 열(Column) 기반 스토리지이며, 데이터는 Key-Value 구조를 기반으로 구성됩니다.

  • Row Key: 기본 키 역할 (데이터 파티셔닝의 기준).
  • Column Family: 비슷한 성격의 데이터를 저장하는 테이블 개념.

 

예를 들어, 사용자 로그인 데이터를 저장하는 테이블 설계를 보면:

CREATE TABLE user_logins (
    user_id UUID PRIMARY KEY,
    last_login_time TIMESTAMP,
    ip_address TEXT
);

2) 파티셔닝 전략

 

Cassandra는 데이터를 분산 저장하기 위해 Consistent Hashing을 활용합니다. 파티셔닝 키를 적절히 설정하면 부하 분산이 가능합니다.

  • RandomPartitioner: 균등한 데이터 분배.
  • ByteOrderedPartitioner: 범위 기반 검색에 유리하지만 특정 노드에 부하 집중 가능.

 

3) 데이터 복제 및 일관성

 

Cassandra는 튜닝 가능한 일관성 수준을 지원하며, Replication Factor(RF) 설정을 통해 데이터 내구성을 조정할 수 있습니다.

  • Replication Factor 3: 3개의 노드에 동일한 데이터를 저장.
  • Consistency Level: QUORUM: 다수 노드 응답 시 트랜잭션 확정.

4. MongoDB vs. Cassandra 비교

항목MongoDBCassandra

데이터 모델 문서(JSON) 컬럼 패밀리
확장성 수평적 확장(샤딩) 수평적 확장(노드 추가)
쓰기 성능 비교적 낮음 (트랜잭션 지원) 매우 빠름 (쓰기 최적화)
읽기 성능 높은 성능 노드 간 복제 지연 발생 가능
사용 사례 웹 애플리케이션, IoT 로그 분석, 데이터 웨어하우스

 

5. 예제 SQL 및 쿼리 코드

MongoDB와 Cassandra의 설계 원칙을 보다 명확하게 이해할 수 있도록 예제 SQL 및 쿼리 코드를 간단하게 살펴보겠습니다.

MongoDB에서는 "MongoDB Query Language(MQL)"을, Cassandra에서는 "CQL(Cassandra Query Language)"을 사용합니다.

MongoDB 설계 및 예제 코드

 

1) 컬렉션 생성 및 데이터 삽입

 

MongoDB에서는 use 명령어를 사용하여 데이터베이스를 선택한 후, insertOne() 또는 insertMany()를 사용하여 데이터를 삽입할 수 있습니다.

 

예제: 전자상거래 주문 데이터 저장

use ecommerce

db.orders.insertOne({
    "order_id": "ORD12345",
    "customer": {
        "customer_id": "CUST67890",
        "name": "홍길동",
        "email": "hong@example.com"
    },
    "items": [
        {"product": "노트북", "price": 1500000, "quantity": 1},
        {"product": "마우스", "price": 25000, "quantity": 2}
    ],
    "order_date": new Date(),
    "status": "shipped"
})

2) 데이터 조회

MongoDB에서는 find() 메서드를 사용하여 데이터를 조회할 수 있습니다.

 

예제: 특정 고객의 주문 조회

db.orders.find({"customer.customer_id": "CUST67890"})

예제: 주문 상태가 shipped인 주문 조회

db.orders.find({"status": "shipped"})

예제: 특정 가격 이상의 제품을 포함한 주문 조회 ($gt 연산자 사용)

db.orders.find({"items.price": {$gt: 1000000}})

3) 인덱스 설정

MongoDB에서는 성능 최적화를 위해 인덱스(Index) 를 설정할 수 있습니다.

 

예제: customer_id 필드에 인덱스 추가

db.orders.createIndex({"customer.customer_id": 1})

이는 주문 데이터를 고객 ID 기준으로 빠르게 검색할 수 있도록 도와줍니다.

4) 데이터 업데이트

예제: 특정 주문의 배송 상태 업데이트

db.orders.updateOne(
    {"order_id": "ORD12345"},
    {$set: {"status": "delivered"}}
)

5) 데이터 삭제

예제: 특정 고객의 모든 주문 삭제

db.orders.deleteMany({"customer.customer_id": "CUST67890"})

Cassandra 설계 및 예제 코드

Cassandra에서는 CQL을 사용하여 테이블을 생성하고 데이터를 저장합니다.

1) 테이블 생성

Cassandra에서 테이블을 생성할 때는 PRIMARY KEY를 적절히 설정하여 데이터의 **파티셔닝(Partitioning)**을 고려해야 합니다.

 

예제: 주문 테이블 생성

CREATE TABLE ecommerce.orders (
    order_id UUID PRIMARY KEY,
    customer_id UUID,
    product_name TEXT,
    price DECIMAL,
    quantity INT,
    order_date TIMESTAMP
) WITH CLUSTERING ORDER BY (order_date DESC);

위에서 order_idPRIMARY KEY 역할을 하며, order_date DESC 옵션을 추가하여 최신 주문이 먼저 조회되도록 설정하였습니다.

2) 데이터 삽입

Cassandra에서 데이터를 삽입할 때는 INSERT INTO를 사용합니다.

예제: 주문 데이터 삽입

INSERT INTO ecommerce.orders (order_id, customer_id, product_name, price, quantity, order_date)
VALUES (uuid(), uuid(), '노트북', 1500000.00, 1, toTimestamp(now()));
  • uuid() : UUID를 자동 생성하는 함수.
  • toTimestamp(now()) : 현재 시간을 TIMESTAMP로 변환.

3) 데이터 조회

예제: 특정 고객의 모든 주문 조회

SELECT * FROM ecommerce.orders WHERE customer_id = uuid('550e8400-e29b-41d4-a716-446655440000');

Cassandra는 분산 시스템이므로 WHERE 절에서 반드시 PRIMARY KEY(또는 PARTITION KEY)를 사용해야 합니다.

예제: 최신 10개 주문 조회

SELECT * FROM ecommerce.orders ORDER BY order_date DESC LIMIT 10;

4) 인덱스 추가

Cassandra는 기본적으로 보조 인덱스(Secondary Index)를 권장하지 않지만, 특정 필드에 대해 빠른 검색이 필요할 경우 CREATE INDEX를 사용할 수 있습니다.

예제: 제품명(Product Name)으로 검색할 수 있도록 인덱스 추가

CREATE INDEX ON ecommerce.orders (product_name);

5) 데이터 업데이트

Cassandra는 UPDATE문을 지원하지만, UPSERT 방식으로 동작합니다. 즉, 데이터가 존재하면 업데이트하고, 없으면 삽입됩니다.

예제: 주문 수량 변경

UPDATE ecommerce.orders 
SET quantity = 2 
WHERE order_id = uuid('123e4567-e89b-12d3-a456-426614174000');

6) 데이터 삭제

예제: 특정 주문 삭제

DELETE FROM ecommerce.orders WHERE order_id = uuid('123e4567-e89b-12d3-a456-426614174000');

예제: 특정 고객의 모든 주문 삭제

DELETE FROM ecommerce.orders WHERE customer_id = uuid('550e8400-e29b-41d4-a716-446655440000');

MongoDB vs. Cassandra 예제 코드 비교

기능 MongoDB (MQL) Cassandra (CQL)
테이블(컬렉션) 생성 db.createCollection("orders") CREATE TABLE orders (...)
데이터 삽입 db.orders.insertOne({...}) INSERT INTO orders (...) VALUES (...)
데이터 조회 db.orders.find({...}) SELECT * FROM orders WHERE ...
인덱스 추가 db.orders.createIndex({...}) CREATE INDEX ON orders (...)
데이터 업데이트 db.orders.updateOne({...}) UPDATE orders SET ... WHERE ...
데이터 삭제 db.orders.deleteOne({...}) DELETE FROM orders WHERE ...

5. 결론

MongoDB와 Cassandra는 각각 강력한 기능을 갖춘 NoSQL 데이터베이스로, MongoDB는 유연한 문서 저장 및 분석에 적합하고, Cassandra는 고속 쓰기 및 분산 시스템에 강점이 있습니다. 최적의 NoSQL 데이터베이스를 선택하려면 데이터 특성과 사용 목적을 고려한 설계가 필수적입니다.

반응형