10장: MongoDB에서의 트랜잭션
Chapter 10: MongoDB의 트랜잭션 완전정복
애플리케이션이 점점 복잡해질수록 데이터의 일관성과 신뢰성은 필수 조건이 됩니다. 전통적으로 관계형 데이터베이스에서는 안정적인 트랜잭션 지원이 당연하게 여겨져 왔으나, 몽고디비도 최신 버전 이후 강력한 트랜잭션 기능을 제공하기 시작했습니다. 이제는 여러 문서, 컬렉션, 심지어 분산된 샤드 환경까지 아우르는 "multi-document 트랜잭션"이 가능해졌습니다.
몽고디비 트랜잭션의 핵심 원칙
트랜잭션이란 하나의 논리적 작업 단위를 말합니다. 한 트랜잭션 내의 모든 연산은 전부 반영되거나, 하나라도 실패하면 전부 원복되어야 합니다. 몽고디비의 트랜잭션 역시 이 ACID(원자성, 일관성, 고립성, 지속성) 원칙을 충실히 구현합니다. 즉, 일련의 데이터 변경이 전부 적용되는지 아니면 전혀 적용되지 않는지 두 가지 결과만 존재할 뿐, 중간 상태란 없습니다.
4.0 버전부터는 레플리카셋 환경 내에서, 4.2 이상에서는 샤딩 환경까지 포함해 여러 문서와 여러 컬렉션에 동시 적용이 가능합니다. 따라서 복합 비즈니스 로직 또한 신뢰성 있게 처리할 수 있습니다.
트랜잭션 동작 방식과 격리 수준
몽고디비 트랜잭션은 기본적으로 Read Committed isolation을 적용합니다. 즉, 커밋된 데이터만 읽을 수 있습니다. 여기에 더해, Snapshot Isolation도 지원합니다. 트랜잭션이 시작될 때 데이터의 스냅샷을 생성하고, 트랜잭션 내 모든 작업은 이 시점의 데이터에만 영향을 받습니다. 동시 실행되는 트랜잭션의 변경 사항이 서로 간섭하지 않게 되어 데이터를 안전하게 보호합니다.
트랜잭션이 완료되기 전까지는 트랜잭션 내 변경사항을 외부에서 볼 수 없습니다. Commit이 실행되어야만 변경된 데이터가 나타나며, 만일 중간에 오류로 인해 Abort를 호출하면 모든 변경은 깨끗이 되돌려집니다.
실제 코드로 보는 트랜잭션
몽고디비에서 트랜잭션을 다루려면 세션을 사용해야 합니다. 예를 들어, Node.js 드라이버나 Python(PyMongo), 혹은 Java(Spring Data) 환경 모두에서 session을 시작한 뒤 다음과 같은 순서로 트랜잭션을 관리합니다.
const session = await client.startSession();
try {
session.startTransaction();
// 여러 컬렉션에 걸친 조작
await db.collection('orders').insertOne({ ... }, { session });
await db.collection('inventories').updateOne({ ... }, { $inc: { qty: -1 } }, { session });
await session.commitTransaction();
} catch (err) {
await session.abortTransaction();
throw err;
} finally {
session.endSession();
}
모든 데이터 변경은 session 객체를 통해서만 실행해야 트랜잭션 범위로 인식됩니다.
단일 문서 트랜잭션 vs. 다중 문서 트랜잭션
몽고디비는 한 문서에 대한 연산은 원래부터 원자성을 보장합니다. 즉, 한 문서의 변경은 알아서 트랜잭션처럼 처리됩니다. 하지만 여러 문서(혹은 여러 컬렉션)에서 데이터를 동시에 바꿔야 한다면, 앞서 본 multi-document 트랜잭션을 반드시 활용해야 합니다. 물론, 트랜잭션이 자주 쓰이면 시스템 자원 소모가 커지므로, 설계 시 임베디드 문서 모델링(연관 데이터를 한 문서에 모아두기)을 적절히 활용하는 것이 좋습니다.
주의사항 및 실무 팁
트랜잭션은 시스템 리소스를 많이 소모하는 작업입니다. 대량의 데이터를 한 번에 바꾸는 연산에 의존하면 성능 저하와 교착(lock) 문제가 발생할 수 있으니, 꼭 필요한 경우에만 사용해야 합니다. 실제 애플리케이션 상황에서는 가능한 단위로 문서를 묶거나, 트랜잭션의 범위를 최소화하는 것이 바람직합니다.
요약하면, 몽고디비는 이제 단일 문서의 원자성을 넘어 복잡한 실전 환경에서도 신뢰성 있는 데이터 트랜잭션을 제공할 만큼 발전했습니다. 올바른 모델링과 트랜잭션 패턴만 잘 선택한다면, 관계형 데이터베이스 못지않은 안정성과 확장성을 동시에 누릴 수 있습니다.


