🚧 트랜잭션 (스탠다드)

2025. 5. 2. 16:25·[내일배움캠프-Sparta]/Spring 6기
반응형

1️⃣ 현실에서의 트랜잭션

💲 송금(계좌이체) 

이것은 트랜잭션입니다.

돈을 주는 사람 계좌는 금액이 차감되어야 하고, 돈을 받는 사람은 금액이 증가되어야 합니다.

이 두 작업 중 어느 하나라도 실패하면 이것은 전체 실패

✈ 해외여행

해외 여행을 가면 숙소, 비행기 티켓을 먼저 예약을 해야 합니다. 하나를 성공하더라도 다른 하나가 실패하면 우리는 여행을 갈 수 없습니다. 이런 경우 다른 하나를 같이 취소하거나 또는 둘 다 예약이 될 때가지 계속 시도를 합니다.

또한 여권이나 비자가 없어도 우리는 여행을 갈 수 없습니다. 모든 조건을 만족해야만 여행을 갈 수 있습니다.

이렇게 해외여행이라는 개념하나에 우리가 만족해야하는 조건이 4개가 있습니다.

이 중에 하나라도 만족하지 못 한다면 다른 3개도 같이 취소

2️⃣ ACID

하나의 트랜잭션이 발생할때 안정성을 보장하기 위한 중요한 4가지 속성

Atomicity ( 원자성 ) ⭐ 모든 작업이 성공하거나 아무 작업도 일어나지 않음
Consistency ( 일관성 )  하나의 트랜잭션 끝난 뒤에도 모든 상태는 이전과 같이 유효
Isolation ( 격리성 ) 모든 트랜잭션은 다른 트랜잭션으로부터 독립적
Durablilty ( 지속성 ) 하나의 트랜잭션이 완료되면 영구적으로  저장

3️⃣ 트랜잭션 상태

  • 활동 상태 ( active ) : 초기 상태로, 트랜잭션이 실행 중일때 가지는 상태
  • 부분 완료 상태 ( partially commited ) : 트랜잭션의 모든 명령문의 성공적으로 실행된 후 , 커밋만 남은 상태
  • 완료 상태 ( commited ) : 트랜잭션이 성공적으로 커밋되어 DB에 영구적으로 반영된 상태
  • 실패 상태 ( failed ) : 실행 중 오류가 발생해 트랜잭션을 더 이상 진행할 수 없는 상태
  • 철회 상태 ( aborted ) : 실패로 인해 트랜잭션이 롤백되고, DB가 트랜잭션 이전 상태로 돌아가는 상태

4️⃣ 스프링의 롤백

앞서 트랜잭션 ACID 중 원자성 속성을 배웠다. 

더보기

모든 작업이 성공하거나 아무 작업도 일어나지 않음.

이 속성에 의하면 트랜잭션 중에 실패하면 반드시 아무 작업도 일어나지 않아야하며, 이는 즉 기존 완료된 작업이 Rollback 되어야 한다는 의미가 됨.

여기서 실패는 Exception 상황을 의미

더보기

내부에서 Exception 발생 ➡  원자성 보장 ➡ Rollback

✅ 스프링 롤백의 기본동작

⭐ 결론

Checked Exception ➡ 롤백 ❌

Unchecked Exception ➡ 롤백  ⭕

5️⃣ 트랜잭션 내부 호출 💥

@Service
@RequiredArgsConstructor
public class MemberService {

    private final MemberRepository memberRepository;

    public void saveWithTx() {
        memberRepository.save(new Member("Outer method", 20L));
        saveInnerMember(); // <--- ✅ 내부에서 호출해서 어딘지 모름. 
    }

    @Transactional
    public void saveInnerMember() {
        memberRepository.save(new Member ("Inner method - no transaction", 10L));
        throw new RuntimeException("Exception in saveInnerPost");
    }
 
}


@SpringBootTest
class MemberServiceTest {

    @Autowired
    private MemberService memberService;

    @Test
    void saveWithTx() {
        try {
            memberService.saveWithTx();
        } catch (RuntimeException ex) {
            System.out.println("Caught exception: " + ex.getMessage());
        }
    }
}

saveWithTx() 안에서 saveInnerMember()를 호출하고 있습니다. saveInnerMember는 @Tx가 적용되어 있기 때문에 예외 발생시 롤백이 일어난다고 생각할 수 있음

하지만 아님 ^^

saveInnerMember()는 @Tx가 적용되지 않습니다.

스프링은 트랜잭션을 적용하기 위해서는 반드시 프록시 객체를 통해야 합니다.

프록시 객체는 우리가 @Contoller, @Service, @Repository와 같은 어노테이션을 적용하면 사용할 수 있는 것입니다.

이미 익숙하게 쓰고 있는 어노테이션이고 이 어노테이션을 적용하면 우리는 프록시 객체를 쓰는 것입니다.

프록시 객체를 통해 메소드 호출이 일어나면 메소드가 호출 되는 시점, 종료되는 시점에 각각 트랜잭션 처리가 되는 원리

하지만 Service 내부에서 메소드를 호출하는 경우는 프록시 객체가 아닌 실체 객체의 메소드를 호출

스프링 입장에서는 메소드가 호출되고 종료되는 시점을 알 수 없음. ➡  트랜잭션이 적용되지 않는 것 ( 롤백 ❌ )

6️⃣ 전파 속성 ( Propagation )

트랜잭션에서 전파 속성은 하나의 트랜잭션이 시작된 상태에서,  또 다른 트래잭션이 시작되었을 때 어떻게 처리할지 정의

 

종류 기존 트랙잭션  ❌ 기존 트랜잭션 ⭕ 적용 사례
REQUIRED ⭐  새 트랜잭션 생성 기존 트랜잭션에 참여 기본값, 대부분의 비즈니스 로직
REQUIRES_NEW ⭐ 새 트랜잭션 생성 기존 트랜잭션 일시중단,
새로운 트랜잭션 생성
독립적인 작업 처리
SUPPORTS 트랜잭션 없이 진행 기존 트랜잭션에 참여 트랜잭션이 필수가 아닌 작업
NOT_SUPPROTED 트랜잭션 없이 진행 기존 트랜잭션 일시중단,
새로운 트랜잭션 생성
로그 저장 등 트랜잭션과 독립적인 작업
MANDATORY IllegalTransactionStateException 발생 기존 트랜잭션에 참여 트랜잭션 내부에서만 호출가능한 메소드
NEVER 트랜잭션 없이 진행 IllegalTransactionStateException 발생 외부 시스템 호출시
NESTED 새 트랜잭션 생성 중첩 트랜잭션 생성 부분적으로 롤백 가능한 작업

7️⃣ 격리 수준 ( Isolation Level )

트랜잭션 격리레벨은 DB마다 다르다. ( MySQL 기준 )

동일한 트랜잭션의 레벨의 이름을 갖고 있더라도 DB마다 세부적인 내용은 다를수 있음.

✅ READ UNCOMMITTED

  • 아직 커밋되지 않은 데이터도 다른 트랜잭션에서 접근할 수 있는 격리 수준
  • Dirty Read : 커밋-트랜잭션이 끝나지 않았는데도 데이터를 읽을 수 있기 때문에 정합성에 문제가 많음.

✅ READ COMMITTED

  • 커밋된 데이터만 다른 트랜잭션에서 읽기 가능한 격리 수준
  • Non-Repeatable Read: 한 트랜잭션에서 첫 번째 조회를 한 이후 두 번째 조회를 하기 전에 사이에 다른 트랜잭션에서 데이터 삽입/수정 커밋이 이뤄지면 한 트랜잭션 내에서 같은 조회 쿼리를 날려도 결과가 달라질 수 있음.

✅ REPEATABLE READ (MySQL의 디폴트 트랜잭션 레벨)

  • 데이터 변경 전의 레코드를 트랜잭션 번호와 함께 언두 공간에 백업해놓기 때문에, READ COMMITTED 처럼 그 사이에 다른 트랜잭션이 커밋되었더라도 언두 공간에 백업해놓은 데이터를 참조하기 때문에 항상 같은 조회 결과를 보장하는 격리 수준
  • Phantom Read : 다른 트랜잭션에서 데이터 변경이 아닌 추가를 할 경우, 언두 공간에 백업할 게 없기 때문에 한 트랜잭션 내에서 데이터가 안 보였다 → 보였다하는 현상.

✅ SERIALIZABLE

  • 데이터 접근 시 락을 걸어서 같은 데이터에 다른 트랜잭션이 동시에 접근할 수 없는 격리 수준

⚡ 스프링 트랜잭션 어노테이션

두 가지는 트랜잭션의 기본 기능은 모두 동일하게 지원합니다.

하지만 스프링의 어노테이션이 더 많은 기능을 지원하고 있기 때문에 jakara 보다는 스프링의 @Tx 어노테이션을 사용하는 것이 더 좋음.

반응형

'[내일배움캠프-Sparta] > Spring 6기' 카테고리의 다른 글

🔍 영속성과 Transactional  (0) 2025.05.04
TIL 50 [ JPA 심화 - ( 테이블 객체 다루는법, JpaRepository 쿼리,페이징처리, JPQL ,QueryDSL, Auditing, 필요한부분 갱신 ) , 트랜잭션 복습 ]  (0) 2025.05.02
🔒 JWT 인증/인가  (0) 2025.05.01
TIL 49 [ JPA 심화 - ( MyBatis, ORM, 테이블 객체, Raw JPA 연관관계) ]  (0) 2025.05.01
TIL 48 [ JPA 심화 ( 의존성, DB, SQL, Driver, JDBC ) ]  (0) 2025.04.30
'[내일배움캠프-Sparta]/Spring 6기' 카테고리의 다른 글
  • 🔍 영속성과 Transactional
  • TIL 50 [ JPA 심화 - ( 테이블 객체 다루는법, JpaRepository 쿼리,페이징처리, JPQL ,QueryDSL, Auditing, 필요한부분 갱신 ) , 트랜잭션 복습 ]
  • 🔒 JWT 인증/인가
  • TIL 49 [ JPA 심화 - ( MyBatis, ORM, 테이블 객체, Raw JPA 연관관계) ]
dimenshun
dimenshun
한 소년의 개발 일기
    반응형
  • dimenshun
    Dev Life Notes
    dimenshun
  • 전체
    오늘
    어제
    • 분류 전체보기 (268)
      • CS (23)
        • 자료구조 (0)
        • 알고리즘 (0)
        • 컴퓨터 구조 (8)
        • 네트워크 (6)
        • 운영체제 (3)
        • DB ( + SQLD ) (5)
        • SW공학 (1)
      • 프로그래밍 (3)
        • Java (0)
        • Spring (0)
        • HTML,CSS (3)
        • JavaScript (0)
      • 개발 툴 (7)
        • Git(버전관리) (1)
        • Docker (3)
        • AWS (2)
        • JSP (1)
      • 코딩테스트(Algorithm) (125)
        • 백준 (6)
        • 프로그래머스 (119)
      • [내일배움캠프-Sparta] (110)
        • Spring 6기 (106)
        • KPT 회고 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    네트워크
    OS
    컴퓨터구조
    웹
    Python
    web
    세션
    백엔드
    트랜잭션
    network
    docker
    배포
    운영체제
    SQL
    메모리
    알고리즘
    db
    AWS
    개발자
    Testcode
    내일배움캠프
    SQLD
    spring
    CPU
    KPT
    코딩테스트
    It
    Til
    Java
    cs
  • hELLO· Designed By정상우.v4.10.3
dimenshun
🚧 트랜잭션 (스탠다드)
상단으로

티스토리툴바