DB의 트랜잭션 개념에 대해 학습하고 Spring에서 트랜잭션이 어떻게 동작하고 활용되는지 살펴보고자.
Transaction(트랜잭션)이란?
Transaction의 탄생 배경
보다 복잡한 프로그램을 개발하다 보면 쿼리 한 줄로 해결할 수 없는 로직을 처리해야하는 경우가 많다. 그리고 여러 개의 쿼리가 처리되는 상황에서 문제가 생겨버린다면 시스템에 큰 결함을 남기게 된다. 예를 들어 쇼핑물 서비스를 구현한다고 하면 아래와 같은 로직은 한 줄로 처리하는 것이 불가능할 것이다.
먼저 쇼핑몰에서 상품을 구매할 때 회원의 잔여 금액이 충분한지 확인하고 잔여 금액이 상품 가격보다 높을 때 구매 로직으로 넘어가야 한다. 그리고 상품의 재고가 있는지 확인 후에 회원의 잔여 금액을 상품 가격만큼 감소시키고 로직을 종료해야 한다.
그런데 선택상품구매 단계에서 Exception()이 발생하여 상품이 없음에도 불구하고 있다고 판단하였거나 잔여 금액이 감소하는 찰나에 서버의 전원이 나가서 상품을 구매했는데도 회원의 잔여 금액이 감소하지 않을 수 있다. 이러한 상황은 곧바로 엄청난 비용 손실을 유발하는데, 이러한 문제를 해결하기 위해 Transaction 기술이 탄생하게 되었다.
Transaction의 기본 방법
Transaction은 2개 이상의 쿼리를 하나의 커넥션으로 묶어 DB에 전송하고, 이 과정에서 에러가 발생할 경우 자동으로 모든 과정을 원래대로 되돌려 놓는다. 이러한 과정을 구현하기 위해 Transaction은 하나 이상의 쿼리를 처리할 때 동일한 Connection 객체를 공유하도록 한다.
Spring에서 Transaction의 사용법
Spring의 Transaction
Spring은 코드 기반의 트랜잭션(Programmatic Transaction) 처리 뿐만 아니라 선언적 트랜잭션(Declarative Transaction)을 지원하고 있다. 즉, Spring이 제공하는 트랜잭션 템플릿 클래스를 이용하거나 설정파일, 어노테이션을 이용해서 트랜잭션의 범위 및 규칙을 정의할 수 있다. Spring에서는 주로 선언적 트랜잭션을 이용하는데, <tx:advice>태그 또는 @Transactional 어노테이션을 이용하는데, 퀴리문을 처리하는 과정에서 에러가 났을 경우 자동으로 Rollback 처리를 해준다.
Spring @Transactional
일반적으로 Spring에서는 Service Layer에서 @Transactional 을 추가하여 Transaction 처리를 한다.
아래의 예시는 상점과 관련된 Service 부분이고, 데이터의 조회만 일어나는 select 메소드에서는 @Transactional 을 활용하고 있지 않지만, 값을 추가하거나 변경 또는 삭제하는 insert, update, delete 메소드에는 @Transactional을 추가하여 트랜잭션을 설정해두었다.
package com.mang.store.service;
import com.mang.store.vo.StoreVO;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
public interface StoreService {
List<StoreVO> selectStoreInfoList(StoreVO storeVO);
StoreVO selectStoreInfo(StoreVO storeVO);
@Transactional
int insertStoreInfo(StoreVO storeVO);
@Transactional
int updateStoreInfo(StoreVO storeVO);
@Transactional
int deleteStoreInfo(StoreVO storeVO);
}
위의 예시는 아주 기본적인 내용들만 다루었기 때문에 이해하기에는 부족할 것이다.
Spring이 제공하는 트랜잭션에 대해 보다 깊이있게 이해를 원한다면 다음 글을 참고하자.