Home > Backend > Spring > πŸƒ[Spring] `@Transactional` μ• λ…Έν…Œμ΄μ…˜

πŸƒ[Spring] `@Transactional` μ• λ…Έν…Œμ΄μ…˜
Spring Framework

πŸƒ[Spring] @Transactional μ• λ…Έν…Œμ΄μ…˜.

  • @Transactional μ• λ…Έν…Œμ΄μ…˜μ€ Spring Frameworkμ—μ„œ μ œκ³΅ν•˜λŠ” μ• λ…Έν…Œμ΄μ…˜μœΌλ‘œ, λ©”μ„œλ“œλ‚˜ ν΄λž˜μŠ€μ— μ μš©ν•˜μ—¬ ν•΄λ‹Ή λ²”μœ„ λ‚΄μ˜ λ°μ΄ν„°λ² μ΄μŠ€ μž‘μ—…μ„ ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μœΌλ‘œ 관리할 수 μžˆλ„λ‘ ν•΄μ€λ‹ˆλ‹€.
    • 즉, @Transactional을 μ‚¬μš©ν•˜λ©΄ μ§€μ •λœ λ©”μ„œλ“œ λ˜λŠ” 클래슀 λ‚΄μ˜ λ°μ΄ν„°λ² μ΄μŠ€ μž‘μ—…μ΄ λͺ¨λ‘ μ„±κ³΅ν•΄μ•Όλ§Œ 컀밋(commit)되고, 그렇지 μ•ŠμœΌλ©΄ λ‘€λ°±(rollback)λ©λ‹ˆλ‹€.

1️⃣ μ£Όμš” κΈ°λŠ₯.

  • 1. νŠΈλžœμž­μ…˜ 관리.
    • @Transactional μ• λ…Έν…Œμ΄μ…˜μ΄ 적용된 λ©”μ„œλ“œ λ‚΄μ—μ„œ μˆ˜ν–‰λ˜λŠ” λͺ¨λ“  λ°μ΄ν„°λ² μ΄μŠ€ μž‘μ—…(예: INSERT, UPDATE, DELETE)은 ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μœΌλ‘œ κ΄€λ¦¬λ©λ‹ˆλ‹€.
      • λ§Œμ•½ λ©”μ„œλ“œ μ‹€ν–‰ 쀑 μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ©΄, ν•΄λ‹Ή νŠΈλžœμž­μ…˜ λ‚΄μ˜ λͺ¨λ“  λ³€κ²½ 사항이 λ‘€λ°±λ©λ‹ˆλ‹€.
  • 2. 적용 λ²”μœ„.
    • @Transactional은 ν΄λž˜μŠ€λ‚˜ λ©”μ„œλ“œμ— μ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • ν΄λž˜μŠ€μ— μ μš©ν•˜λ©΄ ν•΄λ‹Ή 클래슀의 λͺ¨λ“  λ©”μ„œλ“œκ°€ νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ μ‹€ν–‰λ©λ‹ˆλ‹€.
    • λ©”μŠ€νŠΈμ— 적용되면 ν•΄λ‹Ή λ©”μ„œλ“œλ§Œ νŠΈλžœμž­μ…˜μœΌλ‘œ κ΄€λ¦¬λ©λ‹ˆλ‹€.
  • 3. νŠΈλžœμž­μ…˜ μ „νŒŒ(Propagation)
    • @Transactional은 μ—¬λŸ¬ μ „νŒŒ(Propagation) μ˜΅μ…˜μ„ μ œκ³΅ν•˜μ—¬ νŠΈλžœμž­μ…˜μ΄ λ‹€λ₯Έ νŠΈλžœμž­μ…˜κ³Ό μ–΄λ–»κ²Œ μƒν˜Έμž‘μš©ν• μ§€λ₯Ό μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
      • REQUIRED : κΈ°λ³Έκ°’μœΌλ‘œ, ν˜„μž¬ νŠΈλžœμž­μ…˜μ΄ μ‘΄μž¬ν•˜λ©΄ 이λ₯Ό μ‚¬μš©ν•˜κ³ , μ—†μœΌλ©΄ μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜μ„ μƒμ„±ν•©λ‹ˆλ‹€.
      • REQUIRES_NEW : 항상 μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜μ„ μƒμ„±ν•˜κ³ , κΈ°μ‘΄ νŠΈλžœμž­μ…˜μ„ μΌμ‹œ μ •μ§€ν•©λ‹ˆλ‹€.
      • MANDATORY : ν˜„μž¬ νŠΈλžœμž­μ…˜μ΄ λ°˜λ“œμ‹œ μ‘΄μž¬ν•΄μ•Ό ν•˜λ©°, μ—†μœΌλ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•©λ‹ˆλ‹€.
      • SUPPORT : ν˜„μž¬ νŠΈλžœμž­μ…˜μ΄ 있으면 이λ₯Ό μ‚¬μš©ν•˜κ³ , μ—†μœΌλ©΄ νŠΈλžœμž­μ…˜ 없이 μ‹€ν–‰ν•©λ‹ˆλ‹€.
      • 기타 : NOT_SUPPORT, NEVER, NESTED λ“±.
  • 4. νŠΈλžœμž­μ…˜ 격리 μˆ˜μ€€(Isolation Level)
    • λ°μ΄ν„°λ² μ΄μŠ€ νŠΈλžœμž­μ…˜μ˜ 격리 μˆ˜μ€€μ„ μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
      • μ΄λŠ” λ™μ‹œμ— μ‹€ν–‰λ˜λŠ” μ—¬λŸ¬ νŠΈλžœμž­μ…˜ κ°„μ˜ μƒν˜Έμž‘μš© 방식을 μ •μ˜ν•©λ‹ˆλ‹€.
        • READ_UNCOMMITTED : λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ˜ λ―Έμ™„λ£Œ λ³€κ²½ 사항을 읽을 수 μžˆμŠ΅λ‹ˆλ‹€.
        • READ_COMMITED : λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ˜ μ»€λ°‹λœ λ³€κ²½ μ‚¬ν•­λ§Œ 읽을 수 μžˆμŠ΅λ‹ˆλ‹€.
        • REPEATABLE_READ : νŠΈλžœμž­μ…˜ λ™μ•ˆ λ™μΌν•œ 데이터λ₯Ό 반볡적으둜 읽어도 λ™μΌν•œ κ²°κ³Όλ₯Ό 보μž₯ν•©λ‹ˆλ‹€.
        • SERIALIZABLE : κ°€μž₯ μ—„κ²©ν•œ 격리 μˆ˜μ€€μœΌλ‘œ, νŠΈλžœμž­μ…˜μ΄ μ™„μ „νžˆ 순차적으둜 μ‹€ν–‰λ˜λ„λ‘ 보μž₯ν•©λ‹ˆλ‹€.
  • 5. λ‘€λ°± κ·œμΉ™(Rollback Rules)
    • 기본적으둜 @Transactional 은 RuntimeException λ˜λŠ” Error κ°€ λ°œμƒν•˜λ©΄ νŠΈλžœμž­μ…˜μ„ λ‘€λ°±ν•©λ‹ˆλ‹€.
      • νŠΉμ • μ˜ˆμ™Έμ— λŒ€ν•΄ 둀백을 κ°•μ œν•˜κ±°λ‚˜, 둀백을 λ°©μ§€ν•˜λ„λ‘ μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • rollbackFor λ˜λŠ” noRollbackFor 속성을 μ‚¬μš©ν•˜μ—¬ 이 λ™μž‘μ„ μ»€μŠ€ν„°λ§ˆμ΄μ§•ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 6. 읽기 μ „μš©(Read-Only)
    • @Transactional(readOnly = true)둜 μ„€μ •ν•˜λ©΄ νŠΈλžœμž­μ…˜μ΄ 데이터 읽기 μ „μš©μœΌλ‘œ λ™μž‘ν•˜λ©°, 이 경우 데이터 μˆ˜μ • μž‘μ—…μ΄ μ΅œμ ν™”λ  수 μžˆμŠ΅λ‹ˆλ‹€.
      • 주둜 SELECT μΏΌλ¦¬μ—μ„œ μ‚¬μš©λ©λ‹ˆλ‹€.

        2️⃣ μ˜ˆμ‹œ μ½”λ“œ

@Service
public class MyService {
    
    @Autowired
    private MyRepository myRepository;
    
    @Transactional
    public void performTransaction() {
        // λ°μ΄ν„°λ² μ΄μŠ€μ— μƒˆλ‘œμš΄ μ—”ν‹°ν‹° μΆ”κ°€
        myRepository.save(new MyEntity("Data1"));
        
        // λ‹€λ₯Έ λ°μ΄ν„°λ² μ΄μŠ€ μž‘μ—… μˆ˜ν–‰
        myRepository.updateEntity(1L, "UpdatedData");
        
        // μ˜ˆμ™Έ λ°œμƒ μ‹œ, μœ„μ˜ λͺ¨λ“  μž‘μ—…μ΄ 둀백됨
        if (someConditionFails()) {
            throw new RuntimeException("Transaction failed, rolling back...");
        }
    }
    
    @Transactional(readOnly = true)
    public List<MyEntity> getEntities() {
        return myRepository.findAll();
    }
}

3️⃣ μš”μ•½.

  • @Transactional 은 λ°μ΄ν„°λ² μ΄μŠ€ νŠΈλžœμž­μ…˜μ„ μ‰½κ²Œ 관리할 수 μžˆλ„λ‘ ν•΄μ£ΌλŠ” Spring의 핡심 μ• λ…Έν…Œμ΄μ…˜μž…λ‹ˆλ‹€.
    • 이 μ• λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λ©΄ λ©”μ„œλ“œλ‚˜ 클래슀의 λ°μ΄ν„°λ² μ΄μŠ€ μž‘μ—…μ„ ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μœΌλ‘œ μ²˜λ¦¬ν•˜λ©°, μ‹€νŒ¨ μ‹œ μžλ™μœΌλ‘œ λ‘€λ°±λ©λ‹ˆλ‹€.
      • λ˜ν•œ, νŠΈλžœμž­μ…˜ μ „νŒŒ, 격리 μˆ˜μ€€, λ‘€λ°± κ·œμΉ™ 등을 톡해 μ„ΈλΆ€μ μœΌλ‘œ νŠΈλžœμž­μ…˜μ˜ λ™μž‘μ„ μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ΄λŸ¬ν•œ κΈ°λŠ₯ 덕뢄에 @Transactional은 Spring μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ 데이터 일관성과 무결성을 μœ μ§€ν•˜λŠ” 데 μ€‘μš”ν•œ 역할을 ν•©λ‹ˆλ‹€.