ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 트랜잭션 알아보기
    카테고리 없음 2022. 5. 12. 23:27

     

     

      프로젝트를 진행하면서, 책에서 봤던 트랜잭션을 실제로 적용하게 되었다. 사실 이론만 공부할 때는 이해가 잘 되지 않아서 몇 번을 읽어도 계속 까먹기 일쑤였다. 혼자 작업을 할 때에도 트랜잭션이 왜 필요한지를 이해하지 못하고 넘긴 적이 있었다. 페어 프로그래밍을 하면서 우리 코드에서 트랜잭션이 어떤 역할을 하는지 학습하게 되었고, 개념이 더 와닿을 수 있었다. 이번에는 좀 오래 기억하고 싶어서 기초적인 부분을 간단하게 정리해보고자 한다.

     

    트랜잭션이란?

     

      데이터베이스의 상태를 변화시키기 위해 여러 쿼리를 하나의 논리적인 작업 단위로 묶어주는 것

      트랜잭션을 찾아보면 대부분 이렇게 정의된다. 데이터베이스의 상태를 변화시킨다는 건 INSERT, SELECT, UPDATE, DELETE와 같은 쿼리를 날려준다는 뜻으로 이해했는데, 논리적인 작업 단위로 묶어준다는 게 무엇인지 항상 이론 공부할 때 어렵게 느껴졌다.

     

      예제로 가장 많이 사용되는 계좌이체 상황을 보자면, 구매자의 계좌에서 출금을 하는 쿼리 A와 판매자의 계좌에 입금을 하는 쿼리 B는 따로 분리될 수 없다. 구매자의 계좌에서 돈이 나갔으면, 판매자의 계좌에는 반드시 돈이 들어와 있어야 한다. 만약 A는 성공했는데 중간에 오류가 발생해서 B가 실패한다면, A도 돈이 나가지 않은 이전의 상태로 되돌려야 한다.

     

      이렇게 각각의 행위지만, 실제로는 동시에 일어나야 하는 쿼리들이기 때문에 하나의 논리적인 작업 단위로 묶어야 한다는 뜻으로 이해하면 될 것 같다. 이 작업 단위 안에 있는 쿼리들이 모두 성공해야 작업을 마무리하고, 하나라도 실패하면 모든 쿼리들을 이전 상태로 되돌리기 위해 트랜잭션이 필요하다. (예전에 티켓을 예매할 때 다른 사람이 같은 자리를 동시에 결제하면 어떡하지 걱정하고는 했었는데, 트랜잭션을 알았더라면 그런 걱정은 안 했을 것 같다..ㅎㅎ)

     

    트랜잭션 특징(ACID)

     

    • 원자성(Atomicity): 트랜잭션은 DB에 모두 반영되거나, 전혀 반영되지 않아야 한다.(All or Nothing)

      ex. 구매자 출금 쿼리와 판매자 입금 쿼리가 둘 다 성공하면 모두 반영되겠지만, 구매자 출금 쿼리는 성공했는데 판매자 입금 쿼리가 실패하면 성공한 쿼리까지 이전의 상태로 되돌려야 한다.

     

    • 일관성(Consistency): 트랜잭션의 작업 처리 결과는 항상 일관되어야 한다.

      - 데이터에 적용된 규칙이나 제약 조건을 어기는 트랜잭션은 거부된다.

      ex. NOT NULL 조건이라면, 해당 조건을 위반해서는 안 됨. int형 타입만 허용한다면 다른 타입은 올 수 없음. 글자 수가 정해져 있는데, 해당 글자 수를 넘어간다면 허용할 수 없음 등.. (아직 이해가 좀 어려워서 예시는 더 살펴봐야 할 것 같다.)

     

    • 독립성(Isolation): 하나의 트랜잭션은 다른 트랜잭션에 끼어들 수 없고, 서로 독립적이다.

      - 두 개의 트랜잭션을 병행하더라도, 서로의 트랜잭션 연산에 끼어들 수 없다. 한 트랜잭션이 완료되어야 다른 트랜잭션이 그 연산의 결과를 참조할 수 있다.(프로젝트를 진행하면서 해당 부분을 경험했다. 아래 참조)

     

    • 지속성(Durability): 성공한 트랜잭션의 결과는 영구적으로 반영되어야 한다.

      - 트랜잭션 로그가 기록되어야 성공으로 간주한다.

     

    트랜잭션 Commit과 Rollback

     

    Commit은 트랜잭션의 성공을 보장한다. 모든 과정이 오류 없이 수행되면 그 내용을 데이터베이스에 반영하기 위해 변경된 내용을 영구 저장한다. 지속성을 보장한다.
    Rollback은 문제가 발생했을 경우 트랜잭션 도중의 변경 사항을 모두 취소한다. 즉 트랜잭션으로 묶음 처리된 모든 작업 내용을 이전 상태로 되돌린다. 이전 상태라 함은 이전 Commit 상태를 말한다.

     

    프로젝트에 적용하기

     

      결제 취소 기능을 구현하는 도중에 트랜잭션을 접하게 되었다. 트랜잭션을 적용하지 않을 경우 발생할 수 있는 문제가 있었다.

    public enum PaymentStatus {
    
    	BEFORE_CHECK, CONFIRMED, CONFIRMED_UNABLE_TO_CANCEL, CANCELED
    
    }
    @Transactional
    public void cancelPayment(long paymentId, String userId) {
    	PaymentDTO dto = getPaymentSummary(paymentId, userId);
        	validateUnableToCancelPayment(dto);
    	validateCorrectPaymentOwner(dto, userId);
    	paymentDao.updatePaymentStatusCanceled(paymentId, userId);
    }

      결제 취소 로직(cancelPayment)은 결제 번호와 유저 아이디를 확인해 결제 취소를 실행한다.

    1. getPaymentSummary로 데이터베이스에 접근해 결제 내역을 조회한다.
    2. 조회한 결과를 validateUnableToCancelPayment에 담아 현재 결제 상태가 취소가 가능한 상태인지 아닌지 확인한다.
    3. validateCorrectPaymentOwner를 호출해 해당 결제 내역의 유저가 맞는지 확인한다.
    4. 위 과정을 통과하면 결제 상태를 CANCELED로 업데이트한다.

      2에서는 1에서 조회한 PaymentStatus가 CONFIRMED_UNABLE_TO_CANCEL(결제 취소 불가능)인지 확인하고, 불가능하면 결제 취소가 실행될 수 없도록 예외를 던지고, 아니면 다음 단계로 넘어간다.

     

      그런데 만약 사용자가 결제 취소 로직을 실행하는 도중에 관리자가 데이터베이스에서 해당 결제 상태를 취소 불가능으로 변경했다면?

    1. 사용자가 결제 취소를 요청한다.
    2. 데이터베이스에 접근해 결제 내역을 조회한다.(getPaymentSummary)
    3. validateUnableToCancelPayment를 호출해서 결제 취소가 가능한 상태(CONFIRMED) 임을 확인하고, 다음 단계로 넘어간다.
    4. 관리자가 데이터베이스에서 해당 결제 상태를 취소 불가능(CONFIRMED_UNABLE_TO_CANCEL)으로 변경한다.

      트랜잭션이 없는 상황에서 4를 본다면, 사용자는 결제 상태로 CONFIRMED 값을 가지고 있지만 데이터베이스에는 CONFIRMED_UNABLE_TO_CANCEL 값이 저장되어 있다. 즉, 데이터베이스에 저장된 값과 불일치하기 때문에 다음 로직이 꼬일 수 있다.

     

      하지만 트랜잭션이 있는 경우라면, 사용자의 결제 취소가 진행되는 과정에서 4는 실행 불가능하다. 사용자가 결제를 취소하는 트랜잭션의 작업이 모두 완료될 때까지 관리자가 결제 상태를 업데이트하는 트랜잭션은 끼어들 수 없기 때문이다. 즉, 독립성이 보장된다.

     


      트랜잭션에 관한 내용은 아직 완벽하게 파악하지는 못했다. 우선 이 정도로 정리를 해두고, 프로젝트를 진행하면서 추가적으로 더 공부를 해야 하는 상황을 마주했을 때 심화 학습을 해봐야겠다. 전에는 오늘 다룬 기초적인 부분도 와닿지가 않았는데, 확실히 직접 작성한 코드로 트랜잭션을 공부하니까 이해가 더 잘 되는 것 같다.

     

    출처

    https://hanamon.kr/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%98-acid-%EC%84%B1%EC%A7%88/

     

    [데이터베이스] 트랜잭션의 ACID 성질 - 하나몬

    트랜잭션이란 여러 개의 작업을 하나로 묶은 실행 유닛을 말한다. 데이터베이스 트랜잭션은 ACID라는 특성을 가지고 있다. ACID는 데이터베이스 내에서 일어나는 하나의 트랜잭션(transaction)의 안

    hanamon.kr

    https://techvu.dev/115

     

    트랜잭션이란?

    트랜잭션(Transacation) 정의 트랜잭션이란 데이터베이스의 상태를 변화시키는 하나의 논리적인 작업 단위라고 할 수 있으며, 트랜잭션에는 여러개의 연산이 수행될 수 있다. 특징 하나의 트랜잭션

    techvu.dev

     

Designed by Tistory.