Recent Posts
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Spring Batch
- 코루틴 컨텍스트
- tolerated
- 코루틴 빌더
- mp4fpsmod
- preemption #
- k8s #kubernetes #쿠버네티스
- PytestPluginManager
- JanusWebRTCGateway
- 자원부족
- JanusWebRTCServer
- PersistenceContext
- 깡돼후
- pytest
- JanusGateway
- 헥사고날아키텍처 #육각형아키텍처 #유스케이스
- Value too long for column
- 개성국밥
- terminal
- 겨울 부산
- 달인막창
- taint
- python
- 티스토리챌린지
- kotlin
- VARCHAR (1)
- 오블완
- vfr video
- JanusWebRTC
- table not found
Archives
너와 나의 스토리
[Spring] @Transaction과 AOP를 이용해서 트랜잭션 처리하기 & 차이점 본문
반응형
Transaction의 속성: ACID
- ACID
- Atomicity(원자성): 트랜잭션은 하나 이상의 관련된 동작을 하나의 작업 단위로 처리하고, 그 결과가 성공 또는 실패할 경우 관련된 동작은 모두 동일한 결과가 나온다. 즉, 작업 중 하나라도 실패한다면 관련된 트랜잭션 내에서 먼저 처리한 동작들도 모두 처음 상태로 돌아간다.
- Consistency(일관성): 트랜잭션이 성공적으로 처리되면 데이터베이스의 관련된 모든 데이터는 일관성을 유지해야 한다.
- Isolation(고립성): 트랜잭션은 독립적으로 처리된다. 서로 다른 트랜잭션이 동일한 데이터에 동시에 접근할 경우 적절한 동시 접근 제어를 해야 한다.
- Durability(지속성): 트랜잭션이 성공적으로 처리되면 그 결과는 지속적으로 유지되어야 한다.
- 이 속성 중 트랜잭션을 가장 잘 표현한 것은 원자성이다.
- "작업 중 하나라도 실패한다면 관련된 트랜잭션 내에서 먼저 처리한 동작들도 모두 처음 상태로 되돌린다"
- -> 이를 Rollback이라고 한다.
테스트할 상황:
- 다음과 같이 게시판이 있고, 게시글은 조회하게 되면 조회수를 가진다.
- 이때, 해당 게시글을 조회하는 과정에서 에러가 나는 경우를 테스트하려고 한다.
public BoardDto selectBoardDetail(int boardIdx) throws Exception{
boardMapper.updateHitCount(boardIdx); // 조회수 올리기
int a = 10/0;
BoardDto board = boardMapper.selectBoardDetail(boardIdx); // 게시글 보여주기
return board;
}
- 위 코드에서 알 수 있듯, 조회수를 올린 후 게시글을 display하기 전에 의도적으로 에러를 발생시킨다.
- 아무런 조취를 취하지 않고 위 코드로 작업을 수행한 경우, 다음과 같은 결과를 얻게 된다.
- 이처럼 게시글 조회하는 과정에서 에러가 발생했음에도 불구하고, 다시 게시글 목록을 보면 조회수가 증가했음을 확인할 수 있다.
방법 1: @Transaction 이용
- 해당 서비스 위에 @Transaction 어노테이션을 붙여주자!
@Service
@Transactional
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardMapper boardMapper;
@Override
public BoardDto selectBoardDetail(int boardIdx) throws Exception{
boardMapper.updateHitCount(boardIdx); // 조회수 올리기
int a = 10/0;
BoardDto board = boardMapper.selectBoardDetail(boardIdx); // 게시글 보여주기
return board;
}
}
- 그 결과 다음과 같이, 조회수가 증가하지 않았음을 확인할 수 있다.
방법 2: AOP 이용
- 앞에서 선언한 @Transaction을 삭제하고 아래의 코드(파일)를 추가해준다.
package com.example.board.board.aop;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import java.util.Collections;
@Configuration
public class TransactionAspect {
private static final String AOP_TRANSACTION_METHOD_NAME="*";
private static final String AOP_TRANSACTION_EXPRESSION="execution(* board.service.*Impl.*(..))";
@Autowired
private PlatformTransactionManager transactionManager;
@Bean
public TransactionInterceptor transactionAdvice(){
MatchAlwaysTransactionAttributeSource source = new MatchAlwaysTransactionAttributeSource();
RuleBasedTransactionAttribute transactionAttribute = new RuleBasedTransactionAttribute();
transactionAttribute.setName(AOP_TRANSACTION_METHOD_NAME);
transactionAttribute.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
source.setTransactionAttribute(transactionAttribute);
return new TransactionInterceptor(transactionManager, source);
}
@Bean
public Advisor transactionAdviceAdvisor(){
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(AOP_TRANSACTION_EXPRESSION);
return new DefaultPointcutAdvisor(pointcut, transactionAdvice());
}
}
- 결과는 @Transactional 어노테이션을 사용한 것과 같이 정상적인 결과를 얻을 수 있다.
@Transaction을 이용한 트랜잭션 vs AOP이용한 트랜잭션
@Transaction을 이용한 트랜잭션 | AOP이용한 트랜잭션 | |
장점 | - 특별한 설정 없이 쉽게 사용 가능 - 원하는 곳에서만 트랜잭션 설정함으로써 성능에 대한 영향을 최소화 할 수 있음 |
- 공통으로 트랜잭션이 적용되기 때문에 트랜잭션이 누락될 일이 없다 - 외부 라이브러리에도 적용 가능 |
단점 | - 어노테이션이 누락되거나 여러 메서드에 걸쳐서 사용될 경우 트랜잭션이 적용되지 않을 수 있다. - 외부 라이브러리에는 적용 불가 |
- 원하는 곳에만 트랜잭션 적용 힘듦 -> 성능에 영향 미침 - 특정 비지니스 로직에서는 에러 발생한 시점까지 데이터가 저장되야 하는데, 이런 것까지 모두 rollback 됨 |
참고:
- [스프링 부트 시작하기: 차근차근 따라 하는 단계별 실습]
반응형
'개발 > Spring Boot' 카테고리의 다른 글
Comments