블로그 본문

[MongoDB 실습] MongoDB 로컬/클라우드 설치, BSON 데이터 구조, 기본 CRUD 쿼리 및 Aggregation Framework(집계 파이프라인) 기초

📌 목차 바로가기

    지난 포스팅에서는 단일 DB 만능주의를 깨부수고, NoSQL의 4대 핵심 데이터 모델(Key-Value, Document, Wide-Column, Graph)의 구조적 차이와 비즈니스 도메인별 최적 DB를 매핑하는 폴리글랏 퍼시스턴스(Polyglot Persistence) 전략을 다루었습니다.

    이번 포스팅에서는 MongoDB의 설치 및 접속 환경 구성부터, BSON 데이터 포맷의 특성, 원자적 수정자($set, \(inc, \)push)를 활용한 기본 CRUD 쿼리, 그리고 RDBMS의 GROUP BY를 대체하는 Aggregation Framework(집계 파이프라인) 기초 체계를 설명하겠습니다.

    1. MongoDB 설치, 접속 환경 구성 및 BSON(Binary JSON) 스토리지 구조

    MongoDB를 다루기 위해서는 개발 서버 환경에 데이터베이스 엔진을 가동하고, 텍스트 CLI 및 시각적 GUI 클라이언트를 연결해야 합니다.

    ■ MongoDB 구축 및 접속 환경

    1. MongoDB Community Server: 백엔드 데이터베이스 엔진 본체로, 로컬 리눅스/Mac/Windows 환경이나 AWS EC2 인스턴스에 데몬(Daemon) 서비스 형태로 가동합니다.
    2. MongoDB Shell (mongosh): 대화형 터미널 인터페이스로, 자바스크립트 기반 문법을 사용하여 쿼리를 직접 실행하고 테스트할 수 있는 CLI 도구입니다.
    3. MongoDB Compass: 직관적인 시각화 GUI 클라이언트 프로그램입니다. 컬렉션 내부의 문서들을 한눈에 확인하고, 인덱스 생성 및 집계 파이프라인을 파이프라인 빌더로 손쉽게 조작할 수 있습니다.

    ■ JSON vs BSON (Binary JSON) 스토리지 구조 비교

    개발자는 직관적인 JSON 포맷으로 데이터를 다루지만, MongoDB 내부 스토리지 엔진은 이를 BSON(Binary JSON) 포맷으로 변환하여 디스크에 보관합니다.

    • JSON (JavaScript Object Notation): 사람이 읽기 쉬운 텍스트 포맷이지만, 데이터 형식이 단순 문자열(String), 숫자(Number), 불리언(Boolean) 등으로 제한되고, 텍스트 파싱 연산 오버헤드가 발생합니다.
    • BSON (Binary JSON): JSON의 제한된 데이터 타입을 확장하여 Date (날짜/시간), BinData (이진 파일), Int32/Int64 (정수 스펙 구분), 그리고 고유 식별자인 ObjectId 타입을 기본 지원합니다. 또한 이진 바이너리 형태로 스캔하므로 스토리지 공간 효율성과 기계의 데이터 탐색 속도가 압도적으로 뛰어납니다.

    2. MongoDB 기본 CRUD 쿼리 및 원자적 수정자(Modifier) 연산자

    MongoDB는 SQL의 INSERT, SELECT, UPDATE, DELETE 명령을 대체하는 유연한 자바스크립트 메소드를 제공합니다.

    ① Create (문서 생성): insertOne(), insertMany()

    // 단일 문서 삽입
    db.products.insertOne({
      prod_cd: "P001",
      prod_name: "오버핏 베이직 후드티",
      price: 49000,
      category: "TOP",
      tags: ["신상품", "무료배송"],
      reg_date: new Date()
    });
    
    // 다중 문서 일괄 삽입
    db.products.insertMany([
      { prod_cd: "P002", prod_name: "데님 와이드 팬츠", price: 59000, category: "BOTTOM" },
      { prod_cd: "P003", prod_name: "클래식 셔츠", price: 39000, category: "TOP" }
    ]);
    

    ② Read (문서 조회): find(), findOne() 및 조건 연산자

    • 비교 연산자: $gt (초과), $gte (이상), $lt (미만), $lte (이하), $in (포함), $ne (불일치)
    • 논리 연산자: $or, $and
    // TOP 카테고리 중 가격이 40,000원 이상인 상품 조회
    db.products.find({
      category: "TOP",
      price: { $gte: 40000 }
    });
    
    // OR 조건 검색 및 필요한 필드만 프로젝션(Projection) 추출 (price > 50000 또는 BOTTOM 카테고리)
    db.products.find(
      { $or: [{ price: { $gt: 50000 } }, { category: "BOTTOM" }] },
      { prod_name: 1, price: 1, _id: 0 }
    );
    

    ③ Update (문서 수정): updateOne(), updateMany() 및 수정자 연산자

    RDBMS와 달리 MongoDB는 개별 필드를 수정할 때 반드시 원자적 수정자(Atomic Modifier) 연산자를 사용해야 합니다. 연산자 없이 객체를 전달하면 문서 전체가 덮어씌워지는 대참사가 발생하므로 주의해야 합니다.

    • $set: 지정한 필드의 값을 수정하거나 신규 필드를 생성합니다.
    • $inc: 수치형 필드의 값을 지정한 숫자만큼 증감시킵니다.
    • $push / $pull: 배열(Array) 필드에 요소를 신규 추가하거나 특정 요소를 제거합니다.
    // P001 상품의 가격을 52,000원으로 변경하고 재고수량을 100개 증감
    db.products.updateOne(
      { prod_cd: "P001" },
      {
        $set: { price: 52000 },
        $inc: { stock_qty: 100 },
        $push: { tags: "베스트셀러" }
      }
    );
    

    ④ Delete (문서 삭제): deleteOne(), deleteMany()

    // 조건에 일치하는 단일 문서 또는 다중 문서 삭제
    db.products.deleteOne({ prod_cd: "P003" });
    

    3. Aggregation Framework (집계 파이프라인) 동작 원리

    RDBMS에서 복잡한 통계를 낼 때 사용하던 GROUP BY, HAVING, SUM(), AVG() 연산은 MongoDB에서 Aggregation Framework (집계 파이프라인)가 담당합니다.

    집계 파이프라인은 마치 공장의 파이프라인 컨베이어 벨트처럼, 이전 단계(Stage)의 출력 결과가 다음 단계의 입력 데이터로 연속 전달되어 가공되는 배열 구조를 지닙니다.

    MongoDB Compass / mongosh 클라이언트에서 발송된 BSON 문서가 CRUD 연산을 거쳐, \(match(필터링) -> \)group(카테고리별 \(avg, \)sum 집계) -> \(project(출력 재구성) -> \)sort(정렬) 단계의 집계 파이프라인을 연속 통과하는 처리 흐름도

    ■ 집계 파이프라인 5대 핵심 스테이지

    1. $match: 조건을 만족하는 문서만 선별 필터링합니다. (SQL의 WHERE 역할)
    2. $group: 지정한 키(_id)를 기준으로 문서를 그룹화하고, $sum, $avg, $max, $min 집계를 집행합니다. (SQL의 GROUP BY 및 집계 함수)
    3. $project: 출력 문서의 필드를 선택, 인코딩, 삭제하거나 신규 산술 연산 필드를 생성합니다. (SQL의 SELECT 역할)
    4. $sort: 결과 문서를 정렬합니다. (1: 오름차순, -1: 내림차순)
    5. $limit: 최종 결과 집합의 개수를 제한합니다.
    // 카테고리별 평균 가격 및 총 상품 수 산출 파이프라인
    db.products.aggregate([
      // 1단계: 재고가 0개 초과인 상품만 필터링
      { $match: { stock_qty: { $gt: 0 } } },
    
      // 2단계: 카테고리별 그룹화 및 평균 가격, 총 수량 집계
      {
        $group: {
          _id: "$category",
          avg_price: { $avg: "$price" },
          total_count: { $sum: 1 }
        }
      },
    
      // 3단계: 출력 필드 이름 재정의 및 소수점 정돈
      {
        $project: {
          category_name: "$_id",
          avg_price: { $round: ["$avg_price", 0] },
          total_count: 1,
          _id: 0
        }
      },
    
      // 4단계: 평균 가격 내림차순 정렬
      { $sort: { avg_price: -1 } }
    ]);

    마치며: 유연하고 강력한 NoSQL 데이터 연산력을 확보했습니다!

    이번 포스팅에서는 MongoDB의 설치 및 BSON 데이터 스토리지 구조를 이해하고, 원자적 수정자($set, \(inc, \)push)를 활용한 기본 CRUD 메소드, 그리고 연속 가공을 보장하는 Aggregation Framework(집계 파이프라인)의 기초 작동 원리를 다루었습니다.

    "고정된 스키마라는 과거의 틀을 탈출하여 BSON 문의 유연한 객체 구조와 원자적 수정자 연산, 그리고 연속 집계 파이프라인을 가동해 대용량 비정형 데이터를 고속 가공하는 NoSQL 실전 역량을 완성한 것입니다."

    mongosh 상에서의 기초 CRUD 및 집계 연산력이 준비되었으니, 이제 이 MongoDB 인프라를 실제 Node.js 백엔드 서버 애플리케이션과 유기적으로 결합할 차례입니다.

    다음 포스팅 [Express-MongoDB 연동] Node.js에서 mongodb 클라이언트 드라이버 연동, db.js 모듈화 및 RESTful API 구현 편에서는 mongodb 공식 드라이버 패키지 구성, 보안 URI 환경변수 관리, 싱글톤 패턴의 db.js 연결 모듈 설계, 그리고 사용자 관리 RESTful API 서비스 모듈 구축법을 설명하겠습니다.

    오늘 실습한 CRUD 메소드나 집계 파이프라인 Stage 연산에 관해 궁금한 점이 있으시다면 주저하지 마시고 운영자 메일로 질문 남겨주세요. 오늘도 안전하고 똑똑한 클라우딩 라이프 하세요. 감사합니다! 😉

    출처

    • 이현호. 실무 프로젝트로 완성하는 클라우드 환경에서 DB 구축과 웹 개발. 길벗캠퍼스. 2026.04. (10.3장 'MongoDB 개요 및 환경구축', 290-295페이지 및 10.4장 '기본 CRUD 및 Aggregation Framework', 296-305페이지 참조)
    • 이현호. "10장. NoSQL 데이터베이스_설명오디오.m4a" 및 "13장. NoSQL 기반 개발 코드로의 전환_설명오디오.m4a" 설명 오디오 가이드 스크립트 기반 BSON 스토리지 특성, ObjectId 메커니즘, 원자적 수정자(\(set, \)inc, \(push) 필치 및 Aggregation 파이프라인(\)match, \(group, \)project) 연산 가이드 비하인드 대화록 완벽 반영.
    • MongoDB Manual - Aggregation Operations (https://www.mongodb.com/docs/manual/aggregation/) 및 CRUD Operations Specifications.

    자주 묻는 질문 (FAQ)

    Q. MongoDB에서 데이터를 디스크에 저장할 때 사용하는 BSON(Binary JSON) 포맷의 핵심 이점은 무엇인가요? 

    A. 데이터 타입 확장 및 바이너리 파싱 고속화입니다. 일반 JSON과 달리 Date, BinData, ObjectId 등 정교한 타입을 지원하며, 바이너리 형식을 취해 텍스트 파싱 오버헤드를 줄여 기계의 디스크 탐색 및 조회 속도를 대폭 향상시킵니다.

    Q. MongoDB 문서 수정(Update) 시 \(set, \)inc 같은 원자적 수정자(Atomic Modifier) 연산자를 사용해야 하는 이유는 무엇인가요? 

    A. 문서 전체 덮어쓰기 방지 및 정합성 보장입니다. 수정자 연산자 없이 객체를 전달하면 해당 문서의 기존 데이터가 덮어씌워져 유실되므로, 지정 필드만 원자적으로 변경하는 \(set, 수치를 증감하는 \)inc, 배열을 조작하는 \(push/\)pull을 대입해야 합니다.

    Q. MongoDB의 Aggregation Framework(집계 파이프라인)는 어떤 원리로 동작하나요? 

    A. 단계별 파이프라인 컨베이어 벨트 처리 원리입니다. \(match(필터링) 연산 결과를 다음 단계인 \)group(그룹화 및 \(avg/\)sum 계산)의 입력으로 전달하고, 이어 \(project(필드 선택)와 \)sort(정렬)를 거쳐 대용량 비정형 데이터를 순차적으로 고속 가공합니다.