728x90
반응형
📚 참고자료
- [10분 테코톡] 샐리의 트랜잭션 => 링크
0️⃣ 트랜잭션 개념 공부를 하게 된 계기
스프링을 사용하면서 @Transactional 이라는 어노테이션을 적용해본 적이 있습니다.
메서드 위에 해당 어노테이션을 적용하면 메서드 안에 있는 쿼리들이 하나의 단위로 묶인다는 대략적인 용도만 고 있습니다. 그래서 @Transactional 어노테이션의 정확한 개념을 모르고 사용했기 때문에 의문점이 많이 들었습니다.
- 트랜잭션이란?
- 트랜잭션을 사용해야 하는 상황은?
- 스프링에서는 트랜잭션을 어떻게 지원하는지?
1️⃣ 트랜잭션이란?
- 더이상 나눌 수 없는 가장 작은 하나의 단위를 의미
- 데이터베이스에서는 트랜잭션을 조작함으로써 사용자가 데이터베이스에 대한 완전성을 신뢰할 수 있도록 함
- 모든 데이터베이스는 자체적으로 트랜잭션을 지원
- 하나의 명령을 실행했을 때 데이터베이스가 온전히 그 명령을 실행해주는 것
=> 성공하면 커밋(Commit)
=> 실패하면 롤백(Rollback) - 데이터베이스는 기본적으로 트랜잭션을 관리하기 위한 설정을 갖고 있습니다.
- 명령을 끝마칠 때까지 수행 내역을 로그에 저장해둡니다.
- 데이터베이스에 반영된 내용을 재반영하기 위한 redo log
- 수행을 실패해 이전의 상태로 되돌리는 undo log
* 두 개의 log를 이용해 트랜잭션을 지원합니다.
- 명령을 끝마칠 때까지 수행 내역을 로그에 저장해둡니다.
2️⃣ 트랜잭션을 사용하는 상황(예시)과 성질
트랜잭션에서 가장 흔히 볼 수 있는 입출금을 예시로 들어보겠습니다.
- A가 B에게 만원을 송금하려고 합니다.
- A의 계좌에 만원보다 많은 금액이 있는지 확인합니다.
- A의 계좌에 만원보다 많은 금액이 있다면 만원을 차감합니다.
- 차감한 만원의 금액을 B의 계좌에 더해줍니다.
위 업무는 순서를 나눠놨지만 절대로 분리되거나 일부만 실행되면 안 되는 하나의 작업입니다.
이렇게 절대로 깨져서는 안되는 하나의 작업을 트랜잭션이라고 합니다.
트랜잭션의 네가지 성질
- 원자성(Atomicity)
- A가 B에게 송금을 하는데 A의 계좌에서 만원이 차감만 되고 작업이 종료되면 문제가 발생합니다.
- 이렇듯 일부만 실행되는 경우는 없다는 원자성을 지닙니다.
- [롤백]1번부터 4번까지 연결된 하나의 작업에서 어느 하나의 명령이라도 실패하면 롤백을 하게 됩니다.
- [트랜잭션 커밋]반대로 1번부터 4번까지 작업이 성공적으로 수행하면 수정된 내용 데이터베이스에 반영
- 롤백이나 커밋이 실행되어야 트랜잭션이 종료됩니다. - 일관성(Consistency)
- 데이터베이스 내의 상태 혹은 계층 관계
- 컬럼의 속성이 항상 일관되게 유지되어야 함
- 컬럼의 속성이 수정되었다면 trigger를 통해 일괄적으로 모든 데이터베이스에 적용해야 합니다. - 지속성(Durability)
- 트랜잭션이 성공적으로 수행되어 커밋되었다면 어떠한 문제가 발생하더라도 데이터베이스에 그 내용이
영원히 지속되어야한다는 지속성이 있습니다.
- 이를 위해 모든 트랜잭션은 로그로 남겨져 어떠한 장애에도 대비할 수 있도록 합니다. - 독립성(Isolation)
- 트랜잭션 수행 시 다른 트랜잭션이 끼어들 수 없고 각각 독립적으로 실행된다는 성질
DB 독립성의 문제점(더보기 클릭)
더보기하지만 데이터베이스에 작업이 들어왔을 때 모든 작업의 독립성을 보장해 하나씩 순차적으로 진행하게 된다면, CPU는 DBMS보다 인풋, 아웃풋이 빈번히 수행되기 때문에 트랜잭션을 순차적으로 시행하면 CPU는 점점
응답을 기다리는 시간이 길어지게 됩니다. 그 결과 프로그램이 비효율적으로 동작하는 문제가 발생합니다.
이처럼 데이터베이스에 저장된 데이터의 무결성과 동시성의 성능을 지키기 위해 트랜잭션의 설정이 중요한 것입니다.
여러 명령을 하나의 트랜잭션으로 묶고 싶은 경우 개발자가 직접 트랜잭션의 경계설정을 통해 트랜잭션 명시
3️⃣ 스프링에서 지원하는 트랜잭션
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition);
void commit(TransactionStatus status);
void rollback(TransactionStatus status);
}
- 트랜잭션 추상화 인터페이스인 PlatformTransactionManager를 제공
- getTransaction 메서드
- 파라미터로 전달되는 TransactionDefinition에 따라 트랜잭션을 시작
- 트랜잭션을 문제없이 마치면 commit을, 문제가 발생하면 Rollback을 호출 - getTransaction부터 commit이나 rollback을 하는 부분까지가 트랜잭션의 경계설정입니다.
- getTransaction 메서드
- 다양한 DataSource에 맞게 트랜잭션을 관리
스프링이 제공하는 다양한 트랜잭션 매니저 구현체
- DataSourceTransactionManager
- JDBC에 사용되는 매니저
- 하나의 데이터베이스를 사용하거나 각각의 데이터를 독립적으로 사용하는 로컬 트랜잭션에 사용 - JpaTransactionManager
- JPA에 사용되는 매니저
- 하나의 데이터베이스를 사용하거나 각각의 데이터를 독립적으로 사용하는 로컬 트랜잭션에 사용 - JtaTransactionManager
- 하나 이상의 데이터베이스가 참여하는 경우 글로벌 트랜잭션에 사용되는 JtaTransactionManager 사용
- 여러 개의 데이터베이스에 대한 작업을 하나의 트랜잭션에 묶을 수 있고, 다른 서버에 분산된 것도 묶을 수 있음
🍃 어노테이션을 기반으로 트랜잭션을 설정하는 방법
@Transactional
public void addRestaurantFoods(
Long restaurantId,
List<FoodRequestDto> requestDtoList
) {
Optional<Restaurant> foundRestaurant = restaurantRepository.findById(restaurantId);
checkRestaurant(foundRestaurant);
Restaurant restaurant = foundRestaurant.get();
for (FoodRequestDto requestDto : requestDtoList) {
String foodName = requestDto.getName();
int foodPrice = requestDto.getPrice();
checkDuplicateRestaurantFood(restaurant, foodName);
checkFoodPrice(foodPrice);
Food food = Food.builder()
.name(foodName)
.price(foodPrice)
.restaurant(restaurant)
.build();
foodRepository.save(food);
}
}
- 어노테이션이 적용된 메서드는 메서드 시작부터 트랜잭션이 시작
=> 메서드를 성공적으로 끝마치면 트랜잭션 커밋
=> 도중에 문제가 발생하면 롤백 - 어노테이션은 데이터베이스에 여러번 접근하면서 하나의 작업을 수행하는 서비스 계층 메서드에 붙인다.
반응형
'프로그래밍언어 & 프레임워크 > 스프링(Spring)' 카테고리의 다른 글
[JPA] Update 시 InvalidDataAccessApiUsageException 에러 (0) | 2022.05.08 |
---|---|
쿼리DSL을 사용하는 이유는?(QueryDSL) (0) | 2022.05.01 |
[테코톡] ORM, SQL Mapper, JDBC의 개념과 비교 (0) | 2022.03.19 |
[테코톡] TDD와 단위테스트 (0) | 2022.03.17 |
[팀프로젝트] 스프링 Cors 처리(WebMvcConfigurer) (0) | 2022.02.27 |