익명의 개발노트

[Sequelize-Transaction] 본문

코딩일기/TIL

[Sequelize-Transaction]

캡틴.JS 2019. 10. 23. 22:45
반응형

예를 들어 회원가입하는데, 회원가입정보가 각기 다른 테이블에 저장된다면?? 

비밀번호만 따로 저장된다고 치면, 로직을 어떻게 세워야하나?

기본정보 테이블 저장 후 비밀번호 테이블에 비밀번호를 기본정보테이블의 값을 가지고 FK로 저장할 것이다.

그냥 저장을 해버리면, 기본정보만 저장되고, 비밀번호는 저장되지 않는 경우가 발생할 수 있다.

이렇게 동시에 다른 테이블에 저장을 해야할 때는 트랜젝션을 이용해야한다.

트랜젝션의 중요한 4가지 속성이 있다.

  • 원자성(atomicity): 트랜잭션은 모두 실행되거나 아예 실행되어서는 안된다. 성공적인 트랜잭션은 commit 하고 실패한 트랜잭션은 abort 한다. commit은 데이터베이스를 변경하여 영속적이게 하며, abort는 데이터베이스 변경을 undo 하거나 삭제한다.
  • 일관성(consistency): 트랜잭션은 데이터베이스의 내부 일관성을 지켜야 한다. 각 트랜잭션은 일관성을 보장하도록 프로그램을 작성한다.
  • 고립성(isolation): 트랜잭션은 독립적으로 실행되어야 하고, 다른 트랜잭션과 섞여 실행되면 안된다. 트랜잭션의 집합을 실행한 결과가 이들을 한 번에 하나씩 실행하는 결과와 동일해야 한다. 이런 동작방식을 직렬성이라고 하며 잠금에 의해서 이행된다.
  • 영속성(durability): 트랜잭션의 결과는 시스템 실패로 유실되면 안된다. 정전이나 운영체제 장애 시에도 보존될 수 있도록 디스크 등의 저장장치에 저장한다.

이중 Atomicity 속성(all or nothing)에 의거, 하나의 테이블에 입력이 실패하면 전부 롤백 되게 해야하기때문에

트랜젝션을 사용한다.

기본정보 입력 => 기본정보 + 키값 조회 => 비밀번호테이블 입력을 한다고 가정하자.

 insertNewUserInfo(param){
        return new Promise((resolve, reject) => {
            const  models  = require('../../models/index.js');
            let successMessge = {
                err_code : 0,
                msg : 'ok',
                data : {}
            }
            let failedMessage = {
                err_code : -1,
                msg : 'failed',
                data : {}
            }
            let userData = {
                adminEmail: param.adminEmail,
                adminName: param.adminName,
                telegramId: param.telegramId,
                hpNumber: param.hpNumber,
                department: param.department,
                employeeNumber: param.employeeNumber,
                roleId: param.roleId,
                adminStatus: param.adminStatus,
                lastLoginIp: param.lastLoginIp,
                loginFailCount: param.loginFailCount
            }
           
            models.sequelize.transaction(t=> {
              
                return models.admin.create(userData,{transaction: t}).then(result =>{
                  
                    models.admin.findOne({where:{adminEmail:result.adminEmail}},{transaction: t}).then(result1 =>{
                        let userPassword ={
                            adminAdminSeq : result1.dataValues.adminSeq,
                            adminPassword: param.adminPassword
                        }
                      
                        models.adminPassword.create(userPassword).then(result2 => {
                            if(result2 !== null){
                                resolve(successMessge);
                            }else{
                                resolve(failedMessage);
                            }
                        }).catch(err => {
                            console.log(err);
                        })
                    })
                })
            })            
        });
    }

위 코드에서 트랜젝션을 사용하려면, sequelize.transcation으로 감싸주어야 한다. (지금 이 코드는 Managed Transaction)

그 후 트랜젝션을 ORM의 두번째 인자로 넣어서 관리를 한다. 마지막에는 안넣어도 된다. 

트랜젝션은 Managed Transaction / UnManaged Transaction 으로 구분된다.

전자는 커밋, 롤백을 자동으로 관리해주고, 후자는 개발자가 수동으로 관리해야 한다.

//UnManaged Transaction

return sequelize.transaction().then(t => {
  return User.create({
    firstName: 'Bart',
    lastName: 'Simpson'
  }, {transaction: t}).then(user => {
    return user.addSibling({
      firstName: 'Lisa',
      lastName: 'Simpson'
    }, {transaction: t});
  }).then(() => {
    return t.commit();  //커밋
  }).catch((err) => {
    return t.rollback(); //롤백 설정
  });
});

 

공식문서 : https://sequelize.org/master/manual/transactions.html

반응형

'코딩일기 > TIL' 카테고리의 다른 글

[mocha] 실행방법  (0) 2019.10.30
[babel] polyfill과 preset-env  (0) 2019.10.28
[Mysql] 원격접속  (0) 2019.10.23
[sequelize] 정의 및 설치법  (0) 2019.10.21
[babel 정리] feat. 실전 리액트 프로그래밍  (0) 2019.10.07
Comments