❓
물음표살인마 블로그
  • README
  • ALGORITHM
    • Sieve of Eratosthenes
    • Round Up
    • Binary Search
    • Union Find
    • Sorting Array
    • Lcm, Gcd
  • TechTalk Review
    • Template
  • Books
    • CS Note for Interview
      • Ch1. Design Pattern & Programming paradigm
        • 1.1.1 Singleton Pattern
        • 1.1.2 Factory Pattern
        • 1.1.4 Observer Pattern
        • 1.1.5 Proxty Pattern & Proxy Server
        • 1.1.8 Model-View-Controller Pattern
        • 1.2.1 Declarative and Functional Programming
        • 1.2.2 Object Oriented Programming
      • Ch2. Network
        • 2.2.1 TCP/IP Four-Layer Model
        • 2.2.1-1 TCP 3, 4 way handshake
        • 2.3 Network Devices L4, L7
        • 2.4.1 ARP, RARP
        • 2.4.2 Hop By Hop Communication
        • 2.4.3 IP Addressing Scheme
      • Ch3. Operating System
        • 3.1.1 Roles and Structure of Operating Systems
        • 3.2.1 Memory Hierarchy
        • 3.2.2 Memory Management
        • 3.3.1 Processes and Compilation Process
        • 3.3.3 Memory Structure of a Process
        • 3.3.4 Process Control Block (PCB)
        • 3.3.5 Multiprocessing
        • 3.3.6 Threads and Multithreading
        • 3.3.7 Shared Resources and Critical Sections
        • 3.3.8 Deadlock
        • 3.4 CPU Scheduling Algorithm
      • Ch4. Database
        • 4.1 Database Basic
        • 4.2 Normalization
        • 4.3 Transaction and Integrity
        • 4.4 Types of Databases
        • 4.5 Indexes
        • 4.6 Types of Joins
        • 4.7 Principles of Joins
      • Ch5. Data Structure
    • Learning the Basics of Large-Scale System Design through Virtual Interview Cases
      • 1. Scalability based on user counts(1/2)
      • 1. Scalability based on user counts(2/2)
      • 2.Back-of-the-envelope estimation
      • 3. Strategies for System Design Interviews
      • 4. Rate Limiter
      • 5. Consistent Hashing
      • 6. Key-Value System Design
      • 7. Designing a Unique ID Generator for Distributed Systems
      • 8. Designing a URL Shortener
      • 9. Designing a Web Crawler
      • 10. Notification System Design
      • 11. Designing a News Feed System
      • 12. Chat System Design
      • 13. AutoComplete
      • 14. Design YouTube
      • 15. Design Google Drive
      • Loadbalancer Algorithms
      • Cache tier
      • CDN, Content Delivery Network
      • Stateless Web tier
    • Computer System A programmer's perspective
    • Effective Java
      • Item 1. Consider Static Factory Methods Instead of Constructors
      • Item 2. Consider a Builder When Faced with Many Constructor Parameters
      • Item 3. Ensure Singleton with Private Constructor or Enum Type
      • Item 4. Enforce Noninstantiability with a Private Constructor
      • Item 5. Prefer Dependency Injection to Hardwiring Resources
      • Item 6. Avoid Creating Unnecessary Objects
      • Item 7. Eliminate Obsolete Object References
      • Item 8. Avoid Finalizers and Cleaners
      • Item 9.Prefer try-with-resources to try-finally
      • Item10. Adhering to General Rules When Overriding equals
        • Handling Transitivity Issues
        • Ensuring Consistency
      • Item11. Override hashCode When You Override equals
      • Item12. Always Override toString
        • Always Override toString
      • Item13. Override Clone Judiciously
      • Item14. Consider Implementing Comparable
      • Item15. Minimize the Accessibility of Classes and Members
      • Item16. Accessor Methods Over Public Fields
      • Item17. Minimize Mutability
      • Item18. Composition over inherentance
      • Item19. Design and Document for Inheritance, or Else Prohibit It
      • Item20. Prefer Interfaces to Abstract Classes
      • Item21. Design Interfaces with Implementations in Mind
      • Item22. Use Interfaces Only to define Types
      • Item23. Prefer Class Hierarchies to Tagged Classes
      • Item24. Favor Static Member Classes Over Non-Static
      • Item28. Use Lists Instead of Arrays
      • Item29. Prefer Generic Types
      • Item30. Favor Generic Methods
    • Head First Design Patterns
      • Ch1. Strategy Pattern
      • Ch2. Observer Pattern
        • Ver1. Ch2. Observer Pattern
      • Ch3. Decorator Pattern
        • Ch3. Decorator Pattern
      • Ch4. Factory Pattern
      • Ch5. Singleton Pattern
      • Ch6. Command Pattern
      • Ch7. Adapter and Facade Pattern
      • Ch8. Template Method Pattern
    • Digging Deep into JVM
      • Chapter 2. Java Memory Area & Memory Overflow
      • Chapter 3. Garbage Collector & Memory Allocation Strategy (1/2)
      • Chapter 3. Garbage Collector & Memory Allocation Strategy (2/2)
      • Chapter 5. Optimization Practice
      • Chapter 6. Class file structure
      • Chapter 8. Bytecode Executor Engine (1/2)
  • Interview Practices
    • Restful API Practices
      • Url Shortener API
      • Event Ticket Reservation API
      • Course Management API
      • Search posts by tags API
      • Online Code platform API
      • Simple Task Management API
      • Event Participation API
      • Review System API
      • Car management API
      • Online Library
    • Tech Review
      • if(kakao)
        • Kakao Account Cache Migration / if(kakao)2022
        • Improving the Anomaly Detection System for KakaoTalk Messaging Metrics / if(kakao) 2022
        • Standardizing API Case Handling Without Redeployment / if(kakaoAI)2024
        • JVM warm up / if(kakao)2022
    • Naver Computer Science
      • Process & Thread
      • TCP & UDP
      • Spring & Servlet
      • Filter & Interceptor & AOP
      • Equals() & ==
      • Dependency Injection
      • Object Oriented Programming
  • F-Lab
    • Week1
      • Client & Server
      • HTTP
      • TCP/UDP
      • REST API
      • Questions
        • Object Oriented Programming
        • HTTP
        • Process & Thread
        • Data Structure
    • Week2
      • OSI 7 layer
      • Web vs WAS
    • Week3
      • RDB vs NoSQL
      • RDB Index
      • Cache
      • Redis
      • Messaging Queue
    • Week4
      • Project - Ecommerce
    • Week5
      • ERD - 1
    • Week6
      • Ecommerce - 2
      • Role
      • pw hashing && Salt
      • CreatedAt, ModifiedAt
      • JWT
      • Copy of ERD - 1
    • Week7
      • Vault (HashiCorp Vault)
    • Week 8
      • Api Endpoints
    • Week10
      • Product Create Workflow
  • TOY Project
    • CodeMentor
      • Implementation of Kafka
      • Project Improvement (Architectural Enhancements)
      • Communication between servers in msa
  • JAVA
    • MESI protocol in CAS
    • CAS (Compare and Set)
    • BlockingQueue
    • Producer & Consumer
    • Synchronized && ReentrantLock
    • Memory Visibility
    • Checked vs Unchecked Exception
    • Thread
    • Batch delete instead of Cascade
    • Java Questions
      • Week 1(1/2) - Basic Java
      • Week 1(2/2) - OOP
      • Week 2(1/2) - String, Exception, Generic
      • Week2(2/2) Lambda, Stream, Annotation, Reflection
      • Week3(1/2) Collections
      • Week3(2/2) Threads
      • Week4 Java Concurrency Programming
      • Week5 JVM & GC
    • Java 101
      • JVM Structure
      • Java Compiles and Execution Method
      • Override, Overload
      • Interface vs Abstract Class
      • Primitive vs Object Type
      • Identity and equality
      • String, StringBuilder, StringBuffer
      • Checked Exceptions and Unchecked Exceptions
      • Java 8 methods
      • Try-with-reources
      • Strong Coupling and Loose Coupling
      • Serialization and Deserialization
      • Concurrency Programming in Java
      • Mutable vs Immutable
      • JDK vs JRE
  • SPRING
    • DIP. Dependency Inversion Principal
    • Ioc container, di practice
    • @Transactional
    • Proxy Pattern
    • Strategy Pattern
    • Template Method Pattern
    • using profile name as variable
    • Spring Questions
      • Spring Framework
      • Spring MVC & Web Request
      • AOP (Aspect-Oriented Programming)
      • Spring Boot
      • ORM & Data Access
      • Security
      • ETC
  • DATABASE
    • Enhancing Query Performance & Stability - User list
    • Ensuring Data Consistency, Atomicity and UX Optimization (feat.Firebase)
    • Redis: Remote Dictionary Server
    • Database Questions
      • Week1 DBMS, RDBMS basics
      • Week2 SQL
      • Week3 Index
      • Week4 Anomaly, Functional Dependency, Normalization
      • Week5 DB Transaction, Recovery
    • Normalization
      • 1st Normal Form
      • 2nd Normal Form
      • 3rd Normal Form
  • NETWORK
    • HTTP & TCP head of line blocking
    • HTTP 0.9-3.0
    • Blocking, NonBlocking and Sync, Async
    • Network Questions
      • Week1 Computer Network Basic
      • Week2(1/3) Application Layer Protocol - HTTP
      • Week2(2/3) Application Layer Protocol - HTTPS
      • Week2(3/3) Application Layer Protocol - DNS
      • Week3 Application Layer
      • Week4 Transport Layer - UDP, TCP
      • Week5 Network Layer - IP Protocol
    • Network 101
      • https://www.google.com
      • TCP vs UDP
      • Http vs Https
      • TLS Handshake 1.2
      • HTTP Method
      • CORS & SOP
      • Web Server Software
  • OS
    • Operating System Questions
      • Week1 OS & How Computer Systems Work
      • Week2(1/2) Process
      • Week2(2/2) Thread
      • Week3 CPU Scheduling
      • Week4 Process Synchronize
      • Week5 Virtual Memory
    • Operating System 101
      • Operating system
        • The role of the operating system
        • The composition of the operating system.
      • Process
        • In Linux, are all processes except the initial process child processes?
        • Zombie process, orphan process
        • (Linux) Daemon process
        • Process address space
        • Where are uninitialized variables stored?
        • Determination of the size of the Stack and Heap
        • Access speed of Stack vs Heap
        • Reason for memory space partitioning
        • Process of compiling a process
        • sudo kill -9 $CURRENT_PID
      • Thread
        • Composition of a thread's address space
      • Process vs Thread
        • Creation of processes and threads in Linux
      • Multiprocessing
        • Web Browser
        • Implementation of multiprocessing
        • Application areas of multiprocessing
      • Multithreading
        • Application areas of multithreading
      • Interrupt
        • HW / SW Interrupt
        • Method of handling interrupts
        • Occurrence of two or more interrupts simultaneously
      • Polling
      • Dual Mode
        • Reason for distinguishing between user mode and kernel mode
      • System call
        • Differentiation between system calls
        • Types of system calls
        • Execution process of a system call
      • Process Control Block (PCB)
        • PCB의 구조
        • 쓰레드는 PCB를 갖고 있을까?
        • 프로세스 메모리 구조
      • Context switching
        • Timing of context switching
        • Registers saved during context switching
        • Context switching in processes
        • Context switching in threads
        • Difference between context switching in processes and threads
        • Information of the current process during context switching
      • Interprocess Communication (IPC)
        • Cases where IPC is used
        • Process address space in IPC Shared Memory technique
        • Types of IPC
  • COMPUTER SCIENCE
    • Computer Architecture 101
      • 3 components of a computer
      • RAM vs ROM
      • CPU vs GPU
      • SIMD
      • Two's complement
      • Harvard Architecture vs. von Neumann Architecture
      • The structure of a CPU.
      • Instruction cycle (CPU operation method)
      • Instruction pipelining
      • Bus
      • Memory area
      • Memory hierarchy structure
        • Reason for using memory hierarchy structure
      • Cache memory
      • L1, L2, L3 Cache
      • Locality of reference (cache)
      • Fixed-point vs Floating-point
        • epresentation of infinity and NaN (Not a Number) in floating-point
      • RISC vs CISC
      • Hamming code
      • Compiler
      • Linking
      • Compiler vs Interpreter
      • Mutex vs Semaphore
      • 32bit CPU and 64bit CPU
      • Local vs Static Variable
      • Page
  • Programming Paradigm
    • Declarative vs Imperative
  • JPA, QueryDsl
    • why fetchResults() is deprecated
  • PYTHON
    • Icecream
  • FASTAPI
    • Template Page
  • LINUX
    • Template Page
  • DATA STRUCTURE
    • Counting Sort
    • Array vs Linked List
  • GIT, Github
    • git clone, invalid path error
  • INFRA
    • Template Page
  • AWS
    • Server Log Archive Pipeline
    • Image Processing using Lambda
  • DOCKER
    • Docker and VM
    • Python Executable Environment
    • Docker commands
  • docker-compose
    • Kafka, Multi Broker
  • KUBERNATES
    • !Encountered Errors
      • my-sql restarts
      • kafka producer: disconnected
    • Kubernetes Components
    • Helm
      • Helm commands
    • Pod network
    • Service network
      • deployment.yaml
      • services.yaml
    • Service type
      • Cluster IP
      • NodePort
    • service-name-headless?
    • kube-proxy
  • GraphQL
    • Template Page
  • WEB
    • Template Page
  • Reviews
    • Graphic Intern Review
    • Kakao Brain Pathfinder Review
    • JSCODE 자바 1기 Review
  • 😁Dev Jokes
    • Image
      • Plot twist
      • Priorities
      • SQL join guide
      • Google is generous
      • Genie dislikes cloud
      • buggy bugs
      • last day of unpaid internship
      • what if clients know how to inspect
      • its just game
      • how i wrote my achievement on resume
      • self explanatory
      • chr(sum(range(ord(min(str(not))))))
Powered by GitBook
On this page
  • 1. @Transactional 이란?
  • 1.1. @Transactional의 기본 속성
  • 2. 작동 원리
  • 3. 트랜잭션 전파(Propagation.~~)
  • 4. 트랜잭션 격리 수준(isolation = Isolation.~~)
  • 5. 예외 처리와 롤백(rollbackFor / noRollbackFor = ~~)
  • 6. 읽기 전용 트랜잭션 설정(readOnly = true/false)
  • 7. 트랜잭션의 타임아웃 설정(timeout = ~)
  • 7.1. 동작 원리
  • 8. 트랜잭션 이벤트와 리스너(phase = TransactionPhase.~~)
  • 9. 테스트에서의 @Transactional 사용
  1. SPRING

@Transactional

@Transactional

1. @Transactional 이란?

Transactional은 스프링에서 제공하는 어노테이션입니다. 메서드나 클래스에 적용하여 해당 범위 내에서 트랜잭션을 관리합니다. 이를 통해 일관성을 유지하고, 예외 발생시 롤백할 수 있습니다.

클래스에 @Transactional을 적용하게 되면, 해당 클래스의 모든 public 메서드에 트랜잭션이 적용됩니다. 각 메서드 호출 시마다 트랜잭션이 시작되고, 메서드 실행 후 커밋 또는 롤백이 이루어집니다.

1.1. @Transactional의 기본 속성

  • propagation: 전파 방식. 기본: REQUIRED

  • isolation: 격리 수준. 기본: Repeatable Read(MySQL)

  • timeout: 트랜잭션 타임아웃. 기본: 제한없음

  • readonly: 읽기 전용 여부. 기본: false

  • rollbackFor/noRollbackFor: 롤백/커밋 대상 예외 지정

2. 작동 원리

트랜잭션은 AOP를 기반으로 동작합니다. 스프링은 프록시 객체를 생성하여 실제 메서드 호출 전에 트랜잭션을 시작하고, 실행 후에는 트랜잭션을 커밋하거나 롤백합니다. 개발자 대신 트랜잭션을 관리하게 됩니다.

AOP가 프록시 객체를 생성하여 동작하기 때문에, private이나 protected 메서드 처럼 외부에서 접근할 수 없는 접근 제어자를 사용하게되면 @Transactional이 적용되지 않습니다.

프록시 기반 AOP는 동일 클래스 내에서 자기 자신의 메서드를 호출할 경우 프록시가 적용되지 않는다는 제한이 있습니다. 따라서 같은 클래스 내의 메서드 호출 시에는 @Transactional이 제대로 적용되지 않을 수 있습니다. (이 경우, 구조를 재설계 / 트랜잭션 관리를 명시적으로 처리)

3. 트랜잭션 전파(Propagation.~~)

트랜잭션 전파는 현재 실행중인 트랜잭션이 있을 때, 새로운 메서드가 호출되었을 때의 트랜잭션 동작 방식을 정의하는 것입니다. (여러 트랜잭션이 어떻게 상호작용할지 정의하는 것입니다.)

@Transactional
public void parent(User user) {
    userRepository.save(user);
    child(user.getStats);
}

@Transactional(Propagation.MANDATORY)
public void child(UserStats userStats) {
    userStatsRepository.save(userStats);
}

위 코드 처럼, parent내의 child가 실행될시 어떻게 처리를 해야할지 정의를 하는 것입니다. 위 예시는 parent 트랜잭션이 항상 존재해야한다는 것입니다.

  • Propagation.REQUIRED 부모 트랜잭션이 존재하면 자식 트랜잭션은 부모에게 포함된다. (자식 트랜잭션이 실패하면 부모도 롤백) 부모 트랜잭션이 존재하지 않으면, 새로운 트랜잭션을 생성한다. (자식이 부모가 된다.)

  • Propagation.REQUIRES_NEW 부모 트랜잭션의 존재 유무와 관계 없이, 새로운 트랜잭션을 생성한다. 자식은 쓰기 작업 가능. 부모가 읽기 전용이고 자식이 쓰기 전용일때 사용.

  • Propagation.NESTED 부모 트랜잭션이 존재할 경우, 부모 트랜잭션안에 새로운 트랜잭션을 생성한다. 자식 트랜잭션은 부모 트랜잭션의 영향(커밋, 롤백)을 받지만, 부모는 자식의 영향을 받지 않는다.

  • Propagation.MANDATORY 부모에 무조건 포함시키고, 부모가 없다면 예외 발생(IllegalTransactionStateException)

  • Propagation.SUPPORTS 부모가 존재하면 부모에 포함 부모가 존재하지 않는다면 자식은 @Transaction 적용 없이 동작(위험하지만 성능 이점)

  • Propagation.NOT_SUPPORTED 부모가 존재하면 부모 트랜잭션을 일시 중지하고, 트랜잭션 없이 동작 (부모 트랜잭션이 롤백되더라도 자식은 영향을 받지 않습니다.) 부모가 존재하지 않는다면 트랜잭션 없이 동작

  • Propagation.NEVER 부모 트랜잭션이 존재하면 안됩니다. 트랜잭션이 아예 적용이 안됩니다.

4. 트랜잭션 격리 수준(isolation = Isolation.~~)

트랜잭션 격리 수준은 동시에 실행되는 트랜잭션 간의 데이터 일관성을 유지하기 위한 설정입니다.

  • READ_UNCOMMITTED: Dirty Read, Non-Repeatable Read, Phantom Read

  • READ_COMMITTED: Non-Repeatable Read, Phantom Read

  • REPEATABLE_READ: Phantom Read

  • SERIALIZABLE

트랜잭션 격리 수준별 현상 정의

  • Dirty Read: 다른 트랜잭션에서 아직 커밋하지 않은 변경 내용을 읽는 것

  • Non-Repeatable Read: 동일한 쿼리를 두 번 실행할 때 결과가 다른 것 (다른 트랜잭션이 데이터를 수정하고 커밋한 경우)

  • Phantom Read: 동일한 조건의 조회에서 레코드 수가 달라지는 것 (다른 트랜잭션이 데이터를 삽입하거나 삭제하고 커밋한 경우)

5. 예외 처리와 롤백(rollbackFor / noRollbackFor = ~~)

기본적으로 Unchecked 예외가 발생하면 롤백되고, Checked 예외는 롤백되지 않습니다. 필요시 지정할 수 있습니다.

만약 체크 예외 발생시 트랜잭션을 롤백하기 위해서는, @Transactional(rollbackFro = SQLException.class) 같이 설정. SQLException 발생시 롤백됩니다.

반대로, 특정 Unchecked 예외시 롤백하지 않게 하려면, @Transactional(noRollbackFor = IllegalArgumentException.class). IllegalArgumentException이 발생해도 트랜잭션이 롤백되지 않고 커밋됩니다.

여러 예외를 지정할 수도 있습니다. @Transactional(rollbackFor = {SQLException.class, IOException.class})

6. 읽기 전용 트랜잭션 설정(readOnly = true/false)

트랜잭션에서 readOnly=true 옵션을 통해서 읽기 전용 모드로 동작하게 할 수 있습니다. 성능, 메모리 최적화를 위해 사용되며 데이터를 조회하는 작업에 사용됩니다.

@Service
@RequiredArgsConstructor
public class ParentService {

    private final UserRepository userRepository;
    private final ChildService childService;

    @Transactional(readOnly = true)  // 부모 트랜잭션: 읽기 전용
    public void readAndModifyUser(Long userId) {
        User user = userRepository.findById(userId)
                                  .orElseThrow(() -> new RuntimeException("User not found"));

        // 자식 트랜잭션에서 쓰기 작업을 수행
        childService.updateUserStats(user);
    }
}

@Service
@RequiredArgsConstructor
public class ChildService {

    private final UserStatsRepository userStatsRepository;

    @Transactional(propagation = Propagation.REQUIRES_NEW)  // 새로운 쓰기 트랜잭션 생성
    public void updateUserStats(User user) {
        UserStats stats = user.getStats();
        stats.incrementLoginCount();
        userStatsRepository.save(stats);
    }
}
  • 메모리 이점: JPA 영속성 컨텍스트가 스냅샷 저장소를 유지하지 않게 됩니다.

  • 불필요한 플러시 방지: 자동으로 Hibermate에서 FlushMode.MANUAL로 변경하여, 트랜잭션이 끝날때 자동으로 DB에 반영되는 flush를 하지 않습니다.

  • 데이터베이스 잠금 최적화: 동시성 성능을 높입니다.

  • 가독성: 읽기 전용인것을 단번에 알 수 있습니다.

따라서, 읽기 작업의 트랜잭션의 경우 예외없이 무조건사용하는 것이 좋습니다.

7. 트랜잭션의 타임아웃 설정(timeout = ~)

타임아웃 설정은 트랜잭션이 시작된 후 지정된 시간 내에 완료되지 않으면 자동으로 롤백되는 기능입니다.

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional(timeout = 5) // 5초로 설정
    public void deleteUser(Long userId) {
        User user = userRepository.findById(userId)
                                  .orElseThrow(() -> new EntityNotFoundException("User not found"));
        userRepository.delete(user); //cascade가 걸려있다고 가정
    }
}
  • 과도한 락 점유 방지: 과도한 락 점유로 인한 다른 트랜잭션의 대기 상태 발생을 줄여 시스템 성능을 유지

  • 데드락 방지: 데드락 상황에서도 일정 시간 후 트랜잭션을 롤백하여 시스템이 오랫동안 교착 상태에 빠지지 않도록 할 수 있습니다.

7.1. 동작 원리

  1. 트랜잭션 시작: 트랜잭션 매니저는 해당 시간 동안 트랜잭션이 완료되기를 기다립니다.

  2. 정상 종료: 타임아웃 시간 내에 정상적으로 완료되면 트랜잭션은 커밋됩니다.

  3. 타임아웃 초과: 트랜잭션 매니저는 트랜잭션을 롤백하고, 변경 사항은 모두 취소

8. 트랜잭션 이벤트와 리스너(phase = TransactionPhase.~~)

트랜잭션의 상태 변화에 따라 이벤트를 발생시키는 것. 커밋이나 롤백 시점에 특정 작업을 수행할 수 있습니다.

@TransactionalEventListener의 단계

  • BEFORE_COMMIT: 트랜잭션 커밋 직전에 호출

  • AFTER_COMMIT: 트랜잭션 커밋 후에 호출 (가장 많이 사용됨)

  • AFTER_ROLLBACK: 트랜잭션 롤백 후에 호출

  • AFTER_COMPLETION: 트랜잭션 완료 후에 호출 (커밋 또는 롤백 상관없이)

@Transactional
public void performTransactionalOperation() {
    // 트랜잭션 내 작업
    someDatabaseOperation();

    // 트랜잭션 작업 후 바로 메서드 호출
    sendEmail();
}

위 상황의 경우, 트랜잭션이 커밋되기전에 항상 이메일을 보내게 됩니다.

public class TransactionalEvent {
    private String message;

    public TransactionalEvent(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

@Service
public class TransactionalService {

    private final ApplicationEventPublisher eventPublisher;

    public TransactionalService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    @Transactional
    public void performTransactionalOperation() {
        // 트랜잭션 내 작업
        someDatabaseOperation();

        // 트랜잭션 커밋 후 실행될 이벤트 발행
        eventPublisher.publishEvent(new TransactionalEvent("이메일 전송"));
    }
}

@Component
public class TransactionEventListener {

    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) //
    public void handleAfterCommit(TransactionalEvent event) {
        // 트랜잭션 커밋 후 실행할 로직
        sendEmail(event.getMessage());
    }

    private void sendEmail(String message) {
        System.out.println("트랜잭션 후 이메일 전송: " + message);
    }
}

EventListener를 사용하게되면, 커밋이 되기 전에 이메일 전송을 하게 되지만, @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)로 인해 커밋 후에 실제로 실행되게 됩니다.

  • 데이터 일관성 유지

  • 불필요한 작업 방지

  • 롤백 시점에 따른 보정 작업

9. 테스트에서의 @Transactional 사용

테스트 클래스나 메서드에 @Transactional을 적용하면, 각 테스트가 완료된 후에 자동으로 롤백됩니다. 이렇게 사용하게 되면, 테스트 간 데이터 간섭이 없으므로 안정적인 테스트가 가능합니다.

@SpringBootTest
@Transactional
public class UserServiceTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    //@Commit 을 사용하여 데이터베이스에 실제로 커밋되게 할 수 있습니다.
    public void testCreateUser() {
        // 트랜잭션 내에서 사용자 추가
        User user = new User("testUser");
        userRepository.save(user);

        // 사용자 추가 확인
        assertNotNull(userRepository.findByUsername("testUser"));

        // 테스트가 끝나면 트랜잭션이 롤백되어 데이터베이스에 반영되지 않음
    }
}
PreviousIoc container, di practiceNextProxy Pattern

Last updated 7 months ago