본문 바로가기

백엔드

[MongoDB] Mongoose에서 트랜잭션 처리

트랜잭션(Transaction)

Tansactions let you execute multiple operations in isolation and potentially undo all the operations if one of them fails. This guide will get you started using transactions with Mongoose.

 

 

사용 예시: Q&A 게시글

Q&A는 하나의 질문글과 그 질문에 해당하는 답변글로 이루어져있다. 그 둘은 각각 다른 모델이며, 현재 질문글만 생성되어있고 관리자 유저가 해당 질문에 대한 답변을 작성하는 요청을 한다고 가정할 시,

 

먼저, 트랜잭션을 위한 startSession 객체를 몽구스에서 가져오고, 모델을 import한다.

const {startSession} = require('mongoose')
const Question = require('../schemas/question');
const Answer = require('../schemas/answer');

 

그다음 라우터 요청에서 다음과 같이 처리한다.

  • try...catch문 밖에서 세션 객체를 획득한다. (promise라 await에 유의)
  • try문 안에서 startTransaction()으로 트랜잭션을 시작한 뒤 이어서 쿼리문들을 작성한다.
  • 쿼리문이 끝난 시점에서 await session.commitTransaction()으로 트랜잭션을 커밋한다.
  • 마지막으로 세션을 종료한다.
  • 중요한 점은 두 쿼리문 중 하나라도 오류가 발생할 시 catch문의 await session.abortTransaction()이 발생해 모든 쿼리문을 실패 처리한다.
router.post('/answer',async(req,res,next)=>{
    const session = await startSession();
    try{
        session.startTransaction();
        const answer = await Answer.create({
                uid: req.body.uid,
                answer: req.body.answer,
        },{session});
        const question = await Question.update({_id:req.body.question_id},{answer:answer._id, isAnswered:true},{session});
        await session.commitTransaction();
        session.endSession();
        res.send(formatWriteResult(question));
    }catch(err){
        await session.abortTransaction();
        session.endSession();
        console.error(err);
        next(err);
    }
});

 

참고