cmod.ify
MongoDB 본문
MongoDB 운영 가이드: 설치 및 데이터 구조의 이해
1. 환경 구축 및 네트워크 설정
MongoDB의 원활한 활용을 위해서는 쉘 환경과 데이터 관리 도구의 독립적인 설치가 요구된다.
- MongoDB Shell: 터미널 기반의 조작을 위해 별도로 다운로드하여 압축을 해제한 후 실행한다.
- Database Tools: 외부 파일의 임포트(Import) 및 익스포트(Export) 기능을 수행하려면 해당 도구 패키지를 반드시 추가 설치해야 한다.
- IP 바인딩의 이해:
- 127.0.0.1: 로컬 호스트(Localhost)를 의미하는 루프백 주소이다.
- 0.0.0.0: 모든 네트워크 접속을 허용하는 설정이다.
- 확장 기술:
- 샤딩(Sharding): 대용량 데이터 처리를 위한 수평 분할 기법이다.
- 클러스터링(Clustering): 분산된 샤드들을 체계적으로 조합하여 관리하는 체계이다.
2. 데이터베이스(Database) 계층
데이터베이스는 MongoDB의 최상위 작업 단위로서, 시스템의 동시 처리 성능에 직접적인 영향을 미친다.
- 잠금(Lock) 메커니즘: 컬렉션이나 인덱스의 구조적 변경 시 데이터베이스 수준에서 락이 적용될 수 있음에 유의한다.
- 주요 명령어 요약:
- show dbs: 전체 데이터베이스 목록을 열람한다.
- use [DB명]: 특정 데이터베이스를 선택한다. 존재하지 않을 경우 생성과 동시에 전환된다.
- db: 현재 활성화된 데이터베이스 명칭을 확인한다.
- db.dropDatabase(): 현재 사용 중인 데이터베이스를 즉시 삭제한다.
3. 컬렉션(Collection) 관리 및 제어
컬렉션은 문서(Document)의 집합체이며, 관계형 데이터베이스의 테이블과 유사한 개념이다.
- 생성: 데이터 삽입 시 자동 생성되나, db.createCollection()을 통해 명시적 생성이 가능하다.
- 조회: show collections
- 변경: db.이름.renameCollection(수정할이름)으로 명칭을 수정하거나
- 삭제: db.컬렉션이름.drop()
4. 캡드 컬렉션(Capped Collection)의 특성
고정된 크기를 할당받는 캡드 컬렉션은 가용 용량 초과 시 가장 오래된 데이터를 자동으로 삭제하는 특성을 지닌다.
- 운용 이점: 로그 데이터와 같이 최신 데이터의 중요도가 높고 저장 공간이 제한적인 환경에서 효율적이다.
- 명령어 실무:
- 컬렉션 생성: db.createCollection('이름', {capped: true, size: [크기]})
- 컬렉션 데이터 1개 삽입 : db.cappedCollection.insertOne({x:1})
- 컬렉션 데이터 확인 : db.cappedCollection.find()
- 컬렉션 상태 조회: db.cappedCollection.stats()
- db.createCollection('cappedCollection', {capped:true, size:1000})
- 데이터 순환 테스트: 반복문을 통해 대량의 데이터를 삽입하면, 설정된 size를 기점으로 데이터의 자동 순환(Overwrite)이 발생하는 것을 관찰할 수 있다.
CRUD(Create Read Update Delete)
1. 개요 및 데이터 표기
MongoDB는 도큐먼트 지향 데이터베이스로 JSON 형식을 사용하여 데이터를 관리한다.
- 객체: {키:값, 키:값, ..}의 형태로 구성된다.
- 배열: [데이터 나열]의 형태를 가지며, MongoDB에서 배열이 최상위 루트가 될 수는 없다.
2. 생성(Create) 작업
데이터 삽입은 단일 도큐먼트 레벨에서 원자적으로 실행된다.
- _id 필드: 데이터를 삽입할 때 _id를 지정하지 않으면 시스템이 자동으로 ObjectId를 생성하여 추가한다.
- 함수 종류: insert, save, insertOne, insertMany 등을 사용한다.
- insert와 save의 차이: 동일한 _id가 존재할 때 insert는 에러를 발생시키나, save는 기존 데이터를 수정한다.
- insertOne: 하나의 데이터만 삽입할 때 사용한다.
- 성공 시 해당 데이터의 ObjectId를 리턴한다.
- WriteConcern: 매개변수를 통해 언제 Ack(응답)을 받을지 설정하며, 이를 통해 Lock 관련 설정을 조율한다.
- 예시: db.user.insertOne({username:"karina", password:"karinajjang"})
- insertMany: 여러 개의 데이터를 배열 형태로 삽입할 때 사용한다.
- 매개변수로 WriteConcern과 Ordered를 가진다.
- 예시: db.user.insertMany([{username:"John", ...}, {username:"K", ...}])
- insertMany는 중복 데이터 삽입 시 발생하는 에러 양상이 일반 insert와 다르다.
- insertOne: 하나의 데이터만 삽입할 때 사용한다.
- insert와 save의 차이: 동일한 _id가 존재할 때 insert는 에러를 발생시키나, save는 기존 데이터를 수정한다.
- 중첩 구조: 객체 내부에 다른 객체나 배열을 포함하여 삽입할 수 있다.
- 배열 삽입 시 주의사항: * db.users.insert([{name:"matt"}, {name:"lala"}])와 같이 리스트를 넣으면 개별 도큐먼트로 분할되어 저장된다.
- 그러나 db.users.insert([1, 2])와 같이 키가 없는 단순 배열을 삽입하면 값이 정상적으로 출력되지 않는다.
- Ordered 매개변수: insert 함수의 두 번째 매개변수로, 배열 데이터 삽입 시 스레드 방식을 설정한다.
- true (기본값): 싱글 스레드 사용. 에러 발생 시 이후 작업을 중단한다.
- false: 멀티 스레드 사용. 에러가 발생해도 다른 작업을 계속 수행한다.
db.inventory.insert(
{
item:"ABC1",
details:{
model : "14Q3",
manufacturer : "xyz Company"
},
stock:[{size:"s",qty:25},{size:"M",qty:50}],
category: "clothing"
}
)
3. ObjectId와 유효성 검사
- ObjectId: 12byte로 구성된 일련번호이다. 직접 생성 시에는 new ObjectId()를 이용한다.
- 유효성 검사: MongoDB 엔진은 크기, 인코딩 형식, 자료형만 검사한다. 그 외의 비즈니스 로직은 클라이언트 측(보안 검사)과 서버 측(속도 보완)에서 직접 처리해야 한다.
4. 읽기(Read) 및 쿼리 활용
db.컬렉션이름.find(query, projection) 형식을 사용한다.
- Query: 필터링 조건이며, 속성과 값을 묶어 객체로 설정한다. (쉼표 구분은 AND 조건)
- Projection: 조회할 필드를 설정한다. (1/true는 조회, 0/false는 제외) _id는 명시적으로 false 처리를 하지 않는 한 무조건 조회된다.
- 비교 연산자: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin 등을 지원한다.
- NULL 및 존재 여부: * MongoDB는 속성이 없는 필드도 null로 간주한다.
- 속성이 존재하는 데이터 중 null인 것만 조회하려면 {z: {$eq: null, $exists: true}} 형식을 사용한다.
- 정규표현식($regex): /pattern/ 혹은 $options를 사용하여 복합 문자열 조회를 수행한다. (i: 대소문자 무시, m: 줄바꿈 무시 등)
- 결과 제어: limit(개수)로 제한, skip(개수)으로 건너뛰기, sort({필드: 1/-1})로 정렬한다. $natural: 1은 입력 순서대로 정렬한다.
5. 커서(Cursor) 메커니즘
find() 함수가 리턴하는 데이터는 커서(Iterator)이다.
- hasNext()와 next() 메서드를 통해 데이터에 순차적으로 접근한다.
- 데이터 읽기 직전 위치를 BOF, 마지막 위치를 EOF라고 한다.
6. 수정(Update) 및 교체(Replace)
- replaceOne: 조건에 맞는 도큐먼트 전체를 교체한다. 새로 설정한 속성 외의 기존 값은 사라질 수 있다.
- update 계열: update, updateOne, updateMany를 사용한다.
db.sample.insert({name:"park", score:90})
db.sample.update({name:"park"}, {$set: {score:100}})
- 수정 연산자: $set, $unset, $inc, $currentDate, $min, $max, $mul, $rename, $setOnInsert 등이 존재한다.
- 특징: 연산자를 이용하면 특정 필드값만 선택적으로 변경할 수 있다.
replaceOne(
<query>,
<replacement>,
{
upsert:<boolean>,
writeConcern:<document>,
collation:<document>
})
7. 삭제(Delete) 작업
- remove, deleteOne, deleteMany 함수를 사용하여 데이터를 제거한다.
8. 유효성 검사 및 외부 데이터 로드
- 유효성 검사: MongoDB는 크기, 인코딩, 자료형에 대해서만 검사를 수행한다. 따라서 상세 로직은 클라이언트 측(보안)과 서버 측(속도 보완)에서 각각 처리해야 한다.
- mongoimport: 외부 JSON 파일을 읽어올 때 사용하며, Windows 환경에서는 전용 도구(Database Tools) 설치 및 환경 변수 등록이 필수적이다.
- 실행 예시: mongoimport -d hapi -c area < area.json
Python과 MongoDB 연동: 드라이버 및 ODM 활용 실무
1. PyMongo를 이용한 순수 드라이버 연동
Python에서 MongoDB에 접속하기 위해 pymongo 라이브러리를 사용한다. 이는 가장 기본적인 연결 방식으로, 딕셔너리 구조를 통해 데이터를 제어한다.
연결 및 기본 설정
from pymongo import MongoClient
# MongoDB 서버 연결
conn = MongoClient("127.0.0.1")
db = conn.hapi # 데이터베이스 설정
users = db.users # 컬렉션 설정
CRUD 작업 예시
- 데이터 삭제: users.delete_many({})를 통해 컬렉션 전체를 비울 수 있다.
- 데이터 생성: insert_one()과 insert_many()를 활용한다.
-
doc1 = {'empno': 1, 'name': '해그리드', 'sports': 'boxer'} users.insert_one(doc1) users.insert_many([{'empno': 2, 'name': '말포이', 'sports': 'basketball'}, ...]) - 데이터 수정: update_one()은 조건에 맞는 데이터 중 하나만, update_many()는 전체를 수정한다.
- 데이터 조회: find()의 결과는 커서(Cursor) 형태이므로 반복문을 통해 접근해야 한다.
2. ODM(Object Document Mapper)의 이해와 활용
ODM은 객체와 문서를 매핑하는 도구이다. MongoDB의 JSON 문서를 Python의 클래스처럼 다룰 수 있게 해주어, 딕셔너리 대신 객체를 이용한 직관적인 작업이 가능하다.
ODM vs ORM 비교
| 구분 | ODM | ORM |
| 대상 | MongoDB (문서형 DB) | MariaDB, MySQL (RDBMS) |
| 데이터 구조 | JSON / Document | Table / Row |
| Python 패키지 | MongoEngine, Beanie | SQLAlchemy, Django ORM |
MongoEngine 사용법
가장 널리 사용되는 ODM 중 하나로, 클래스 기반의 모델 설계를 지원한다.
from mongoengine import connect, Document, StringField, IntField, EmailField, DateTimeField
from datetime import datetime
connect(db='hapi', host='localhost', port=27017)
# 모델 설계
class User(Document):
name = StringField(required=True, max_length=50)
age = IntField(min_value=0)
email = EmailField(unique=True)
created_at = DateTimeField(default=datetime.utcnow)
meta = {"collection": "members"} # 저장될 컬렉션 이름 지정
# 데이터 저장 및 조회
user = User(name='해그리드', age=50, email='happyhag@gmail.com')
user.save()
for u in User.objects():
print(u.name)
Beanie (비동기 ODM)
비동기 드라이버인 motor와 데이터 검증 라이브러리인 pydantic을 기반으로 한다. 비동기 환경(FastAPI 등)에서 주로 사용하며, 작업 시 await 키워드를 통해 데이터 처리를 기다려야 한다.
3. 드라이버와 ODM 선택 가이드
기술 스택을 결정할 때는 서비스의 복잡도와 조회 효율을 고려해야 한다.
- 조회 최적화: 복잡한 쿼리가 자주 발생하거나 고성능 조회가 핵심인 경우, 추상화 계층이 있는 ODM/ORM보다는 순수 드라이버(Driver) 사용이 권장된다.
- 커넥션 관리: 순수 드라이버 사용 시 연결을 수동으로 닫아주거나 Connection Pool 설정을 직접 관리해야 하는 번거로움이 있을 수 있다.
- 생산성: 데이터 구조가 정형화되어 있고 객체 지향적인 코드를 선호한다면 ODM이 개발 생산성 측면에서 유리하다.
'BASIC > DATABASE' 카테고리의 다른 글
| Redis (0) | 2026.01.05 |
|---|---|
| 파이썬 & MariaDB 연동 (1) | 2025.12.30 |
| 트리거, 인덱스, 백업, 프로시저 (0) | 2025.12.30 |
| 가상 테이블 (0) | 2025.12.30 |
| DML & TCL (0) | 2025.12.29 |