이번에는 DB 트랜잭션을 사용해서 앞서 발생한 문제점을 해결해보겠습니다.

애플리케이션에서 트랜잭션을 어떤 계층에 걸어야 할까요?

쉽게 이야기해서 트랜잭션을 어디에서 시작하고, 어디에서 커밋해야할까요?

비즈니스 로직과 트랜잭션

트랜잭션은 비즈니스 로직이 있는 서비스 계층에서 시작해야 합니다.

비즈니스 로직이 잘못되면 해당 비즈니스 로직으로 인해 문제가 되는 부분을 함께 롤백해야 하기 때문입니다.

예시로 앞서 작성했던 accountTransfer() 코드를 다시 보겠습니다.

public void accountTransfer(String fromId, String toId, int money) throws SQLException {
    // 트랜잭션 시작
    Member fromMember = memberRepository.findById(fromId);
    Member toMember = memberRepository.findById(toId);

    memberRepository.update(fromId, fromMember.getMoney() - money);
    validation(toMember);
    memberRepository.update(toId, toMember.getMoney() + money);
    // 커밋 혹은 롤백
}

비즈니스 로직 시작과 동시에 트랜잭션이 시작되고 비즈니스 로직이 끝날 때 커밋 또는 롤백이 되어야 합니다.

그림으로 나타내면 아래와 같죠.

image.png

그런데 트랜잭션을 시작하려면 커넥션이 필요합니다.

트랜잭션을 시작하는 건 수동 커밋 모드로 설정하는 것이라고 했습니다. 즉, set autocommit false; 를 하는게 트랜잭션을 시작하는 건데 커넥션이 있어야 명령을 날릴 수 있겠죠.

결국 서비스 계층에서 커넥션을 만들고, 트랜잭션 커밋 이후에 커넥션을 종료해야 합니다.