<트랜잭션이란?>
DB 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위
또는 한꺼번에 모두 수행되어야 할 일련의 연산들
<트랜잭션 예시>
- 상황: 온라인 쇼핑몰에서 결제할 때
- ① 판매자에게 돈 보내기
- ② 판매자에게 상품 받기
- 중요한 원칙:
두 작업은 모두 성공하거나,
둘 다 실패해서 원상복구 되어야 한다. - 핵심 개념:
- commit: 모든 작업이 성공했을 때 결과를 확정
- rollback: 하나라도 실패하면 처음 상태로 되돌리기
-> 트랜잭션은 작업 전체가 완전히 성공하거나, 아예 안 한 것처럼 만드는 기술~!
<트랜잭션 ACID>
- Atomicity (원자성)
→ 모든 작업이 다 성공하거나, 하나라도 실패하면 전부 실패한 걸로 처리 - Consistency (일관성)
→ 트랜잭션 전후에 DB의 규칙이 항상 지켜져야 함 - Isolation (격리성)
→ 동시에 여러 트랜잭션이 실행돼도 서로 간섭하지 않아야 함 - Durability (지속성)
→ 성공한 트랜잭션은 영구적으로 기록되어야 함
<비즈니스 로직과 트랜잭션 코드 분리>
비즈니스 로직과 트랜잭션 처리 로직이 동시에 존재한다면?
->코드가 복잡해지고
->핵심 로직에 집중하기 어려움
<Spring의 트랜잭션 처리 방식>
1. TransactionTemplate
- 다양한 DB 기술(JdbcTemplate, JPA 등)에 따라 트랜잭션 처리 방법이 다르기 때문에,
Spring에서는 공통된 방식으로 트랜잭션을 처리할 수 있도록 추상화를 제공함. - PlatformTransactionManager 인터페이스를 통해 다음 3가지 기능 제공:
- getTransaction(): 트랜잭션 상태 조회
- commit(): 성공 시 변경 사항 저장
- rollback(): 실패 시 변경 사항 되돌림
- 개발자가 직접 트랜잭션 시작/종료 시점을 명확히 지정할 수 있음.
2. @Transactional 어노테이션
- 트랜잭션이 필요한 클래스나 메서드에 붙이기만 하면 자동으로 트랜잭션 적용
- 클래스에 붙이면: 해당 클래스와 하위 메서드에 모두 적용
- 메서드에 붙이면: 해당 메서드에만 적용됨
<프로그래밍적 트랜잭션 관리 vs 선언적 트랜잭션 관리>
- 프로그래밍 트랜잭션 관리 Programmactic Transaction Management
- ex: TransactionManager, TransactionTemplate
- 트랜잭션 관련 코드를 직접 작성하는 방법
- 선언적 트랜잭션 관리 Declarative Transaction Management
- ex: @Transactional
- 과거엔 xml을 이용해 설정하기도 함
- 프로그래밍 트랜잭션 관리에 비해 간편
@Transactional은 트랜잭션 AOP를 위해 Spring에서 지원해주는 어노테이션!!
@Transactional
public void buy(Long money) {
userDao.loseMoney(money);
sellerDao.gainMoney(money);
}
loseMoney 또는 gainMoney 둘 중 하나라도 실패하면 전체 작업을 취소한다.
모든 작업이 성공할 경우 DB에 해당 변경 내역이 반영된다.
<@Transactional의 동작 구조>
- Spring은 AOP를 활용해서 @Transactional이 붙은 메서드나 클래스에 자동으로 트랜잭션을 적용한다.
- 즉, 우리가 트랜잭션을 일일이 작성하지 않아도, Spring이 프록시(proxy)를 만들어서 중간에서 트랜잭션을 관리해준다.
1. Client가 API 호출 → 사용자가 요청을 보냄 (예: 주문하기)
2. 프록시 실행 → Spring이 만든 트랜잭션 프록시가 중간에 끼어듦
3. 트랜잭션 시작 코드 실행 → 트랜잭션 매니저가 트랜잭션을 시작함
4. 비즈니스 로직 실행 → 실제로 주문 처리, 결제 처리 등 핵심 로직 수행
5. 트랜잭션 종료 코드 실행 (commit 또는 rollback) → 성공하면 저장(commit), 실패하면 되돌리기(rollback)
프록시(Proxy)란?
-대리인 또는 중간 관리자
-진짜 객체(서비스 클래스 등)를 호출하기 전에 가로채서 어떤 작업을 먼저 하거나 뒤에 덧붙일 수 있는 객체
<OrderController>
- 역할: HTTP 요청 처리
- fail=true일 경우 예외 발생시켜 트랜잭션 롤백 테스트 가능
<OrderService>
@Transactional: 이 메서드에서 예외가 나면 모든 DB 작업 롤백
<Order.java (엔티티)>
<LoggingAspect (AOP 로깅)>
- @Around: 서비스 메서드 실행 전후로 감싸서 로직 삽입
- joinPoint.proceed(): 원래 메서드 (placeOrder) 실행
- AOP의 핵심 장점: 모든 서비스에 공통 로그 작성 가능
로그예시
메서드 [placeOrder] 실행 시간: 68ms
@Transactional을 안붙이면??
@Transactional을 Service에 안 붙였기 때문에 트랜잭션이 적용되지 않았고,
예외가 발생했지만 롤백되지 않고 DB에 커밋이 되어버림..
'서버 심화 스터디' 카테고리의 다른 글
추가기능(보안 필터 추가 및 서버 구조 개선) (0) | 2025.05.23 |
---|---|
AOP(Aspect-Oriented Programming) (0) | 2025.05.16 |
의존성 주입(Dependency Injection) 을 구현한 예제<알림 서비스> (0) | 2025.05.09 |
의존성 주입(Dependency Injection) (0) | 2025.05.09 |
서블릿 필터와 리스너 (0) | 2025.05.02 |