πŸ’»
Albert's Til
GitHub
  • 맀일맀일 μ‘°κΈˆμ”© μ„±μž₯ν•˜κΈ°
    • README
    • CS
      • Network
      • HTTP
        • NO-CACHE
      • 였λ₯˜ μ½”λ“œ
      • ORM 도ꡬ
      • Design Pattern
        • CQRS Pattern
          • Event Sourcing and CQRS pattern
        • Builder Pattern
    • DB
      • MySQL
        • Timeline
        • Pagination
        • Index
        • Database Performance Optimization Strategies
        • B+ tree
        • MySQL Connectors VS MySQL Shell(Scripting) VS MySQL Workbench
        • MySQL Storage Engine Architecture
      • Normalization & Denormalization
      • JPA
        • @Transactional
        • Why JPA?
        • About JPA
        • N+1 Issue
        • Index
        • ElementCollection&CollectionTable
        • orphanRemoval
        • CascadeType
        • Use Subselect
        • Dynamic Instance Creation
        • Paging
        • Order
        • Spefication
        • mappedBy
      • MongoDB
        • ObjectId
      • Why MySQL?
      • ACID properties of transactions
      • Between JPA and JDBC
      • Identifiers in Hibernate/JPA
    • Java
      • Jackson de/serialize
      • Collections.singletonList() vs List.of()
      • Manage dependencies in Gradle
      • Logging Level
      • Bean Validation
      • JVM Internals
        • Threads
          • Frame
        • Shared Between Threads
          • Classloader
            • Class Loader Hierarchy
            • Loading Linking Initialization
      • Java Collection Framework
      • Annotation
      • Generic
      • λ””λ―Έν„° 법칙
    • Spring
      • Caching
      • Spring Integration Overview
        • ThreadPollTaskExecutor
        • Messaging Bridge
        • Channel Adapter
        • Poller
        • Configuration and @EnableIntegration
        • Message Endpoints
        • Message Channels
      • HATEOAS
      • @Autowired vs Constructor Dependency Injection
      • Spring Security
        • JWT 토큰 μ‚¬μš©ν•œ 인가
        • OAuth 2 Login
        • OAuth 2 인증
        • 인가
        • 인증
        • PasswordEncoder
      • IoC Container
      • Filter,Interceptor,AOP,Argument Resolver
      • Spring Annotation
      • About Spring
    • Kafka
      • Error Channel
    • Infra
      • Scale Up || Scale Out
      • Docker
        • Dockerfile
        • Docker Hub Deploy
        • Command
      • Cloud μœ ν˜•
        • Infrastructure as a Service
        • Platform as a Service
        • Software as a Service
      • 무쀑단 배포
        • μ—”μ§„μ—‘μŠ€(Nginx)
      • μ½”λ“œ μžλ™ 배포
        • Technical
      • AWS EC2
        • PEM(Privacy Enhanced Mail) ν‚€
      • AWS RDS
      • AWS S3
    • CodeSquad
      • Spring Boot Project 1μ£Όμ°¨ 회고
      • Spring Boot Project 2μ£Όμ°¨ 회고
      • Spirng Boot Project 3μ£Όμ°¨ 회고
      • Spring Boot Project 4μ£Όμ°¨ 회고
    • Foody Moody ν”„λ‘œμ νŠΈ
      • Query Performance Comparison
      • HeartCount Asynchronous Issue
      • DeferredResult
      • ResponseBodyEmitter
      • SseEmitter (Spring)
      • Server-Sent Events (SSE)
      • 기술 μŠ€νƒ 적용 이유
      • NO-CACHE(HTTP)
      • Transactional
    • DDD
      • AggregateId
    • Test
      • RestAssured
    • Coding and Algorithmic Problems
      • 819. Most Common Word
      • 344. Reverse String
      • 125. Valid Palindrome
      • 937. Reorder Data in Log Files
    • Node
      • Async... Await...
      • Custom Transactional Decorator Challenger
    • Python
      • Python Basic Grammar
        • Comments and Input/Output
        • Variable
        • Data type
        • Operations and syntax
        • List,Tuple,Dictionary,Set
        • Function
        • Conditional statement
        • Loop
    • HTML
      • HTML Basic
      • HTML Basic Tags
      • HTML Form Tags
      • HTML Table Tags
    • CSS
      • CSS Basic
      • CSS Practice
Powered by GitBook
On this page
  • μ£Όμš” νŠΉμ§• 및 주의 사항
  • Propaging(μ „νŒŒ μ˜΅μ…˜):
  • 1. REQUIRED (ν•„μš”ν•œ 경우):
  • 2.SUPPORTS (μ§€μ›ν•˜λŠ” 경우):
  • 3. MANDATORY (ν•„μˆ˜):
  • 4. REQUIRES_NEW (항상 μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜):
  • 5. NOT_SUPPORTED (νŠΈλžœμž­μ…˜ 지원 μ•ˆ 함):
  • 6. NEVER (νŠΈλžœμž­μ…˜ μ‚¬μš© κΈˆμ§€):
  • 7. NESTED (μ€‘μ²©λœ νŠΈλžœμž­μ…˜):
  • Isolation(격리 μˆ˜μ€€):
  • λ™μ‹œμ„± 문제
  • Timeout (μ‹œκ°„ 초과):
  • Read-only (읽기 μ „μš©):
  • μ„±λŠ₯ ν–₯상 이유:
  • Rollback rules (λ‘€λ°± κ·œμΉ™):
  • AOP (관점 μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°):

Was this helpful?

  1. 맀일맀일 μ‘°κΈˆμ”© μ„±μž₯ν•˜κΈ°
  2. Foody Moody ν”„λ‘œμ νŠΈ

Transactional

이 μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λ©΄ λ©”μ„œλ“œκ°€ νŠΈλžœμž­μ…˜ 경계에 ν¬ν•¨λ˜μ–΄μ•Ό 함을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€. Spring은 이 μ–΄λ…Έν…Œμ΄μ…˜μ„ κ°μ§€ν•˜κ³  ν•΄λ‹Ή λ©”μ„œλ“œκ°€ 호좜될 λ•Œ νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν•˜λ©°, λ©”μ„œλ“œκ°€ μ’…λ£Œλ  λ•Œ νŠΈλžœμž­μ…˜μ„ μ»€λ°‹ν•˜κ±°λ‚˜ λ‘€λ°±ν•©λ‹ˆλ‹€.

μ£Όμš” νŠΉμ§• 및 주의 사항

Propaging(μ „νŒŒ μ˜΅μ…˜):

  • νŠΈλžœμž­μ…˜μ˜ μ „νŒŒ λ™μž‘μ„ μ§€μ •ν•œλ‹€

μ’…λ₯˜

1. REQUIRED (ν•„μš”ν•œ 경우):

  • νŠΈλžœμž­μ…˜μ΄ 이미 μ‘΄μž¬ν•˜λ©΄ 그것을 μ‚¬μš©ν•˜κ³ , κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν•©λ‹ˆλ‹€.

    @Transactional(propagation = Propagation.REQUIRED)
    public void requiredMethod() {
        // 이미 νŠΈλžœμž­μ…˜μ΄ μ‘΄μž¬ν•˜λ©΄ μ‚¬μš©ν•˜κ³ , μ—†μœΌλ©΄ μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜ μ‹œμž‘
    }

2.SUPPORTS (μ§€μ›ν•˜λŠ” 경우):

  • νŠΈλžœμž­μ…˜μ΄ 이미 μ‘΄μž¬ν•˜λ©΄ 그것을 μ‚¬μš©ν•˜κ³ , κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ νŠΈλžœμž­μ…˜ 없이 μ‹€ν–‰λ©λ‹ˆλ‹€.

    @Transactional(propagation = Propagation.SUPPORTS)
    public void supportsMethod() {
        // 이미 νŠΈλžœμž­μ…˜μ΄ μ‘΄μž¬ν•˜λ©΄ μ‚¬μš©ν•˜κ³ , μ—†μœΌλ©΄ νŠΈλžœμž­μ…˜ 없이 μ‹€ν–‰
    }

3. MANDATORY (ν•„μˆ˜):

  • νŠΈλžœμž­μ…˜μ΄ 이미 μ‘΄μž¬ν•΄μ•Όλ§Œ ν•©λ‹ˆλ‹€. κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•©λ‹ˆλ‹€.

    @Transactional(propagation = Propagation.MANDATORY)
    public void mandatoryMethod() {
        // νŠΈλžœμž­μ…˜μ΄ λ°˜λ“œμ‹œ μ‘΄μž¬ν•΄μ•Ό 함. μ—†μœΌλ©΄ μ˜ˆμ™Έ λ°œμƒ
    }

4. REQUIRES_NEW (항상 μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜):

  • 항상 μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν•©λ‹ˆλ‹€. 이미 μ‘΄μž¬ν•˜λŠ” νŠΈλžœμž­μ…˜μ€ μΌμ‹œ μ€‘λ‹¨λ©λ‹ˆλ‹€.

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void requiresNewMethod() {
        // 항상 μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜ μ‹œμž‘. κΈ°μ‘΄ νŠΈλžœμž­μ…˜μ€ μΌμ‹œ 쀑단
    }

5. NOT_SUPPORTED (νŠΈλžœμž­μ…˜ 지원 μ•ˆ 함):

  • νŠΈλžœμž­μ…˜μ„ μ§€μ›ν•˜μ§€ μ•Šμ•„μ„œ νŠΈλžœμž­μ…˜ μ™ΈλΆ€μ—μ„œ μ‹€ν–‰λ©λ‹ˆλ‹€. 이미 μ‘΄μž¬ν•˜λŠ” νŠΈλžœμž­μ…˜μ€ μΌμ‹œ μ€‘λ‹¨λ©λ‹ˆλ‹€.

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void notSupportedMethod() {
        // νŠΈλžœμž­μ…˜ 없이 μ‹€ν–‰. κΈ°μ‘΄ νŠΈλžœμž­μ…˜μ€ μΌμ‹œ 쀑단
    }

6. NEVER (νŠΈλžœμž­μ…˜ μ‚¬μš© κΈˆμ§€):

  • νŠΈλžœμž­μ…˜μ„ μ‚¬μš©ν•΄μ„œλŠ” μ•ˆ 되며, νŠΈλžœμž­μ…˜μ΄ 이미 μ‘΄μž¬ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•©λ‹ˆλ‹€.

    @Transactional(propagation = Propagation.NEVER)
    public void neverMethod() {
        // νŠΈλžœμž­μ…˜μ„ μ‚¬μš©ν•΄μ„œλŠ” μ•ˆ 됨. 이미 μ‘΄μž¬ν•˜λ©΄ μ˜ˆμ™Έ λ°œμƒ
    }

7. NESTED (μ€‘μ²©λœ νŠΈλžœμž­μ…˜):

  • ν˜„μž¬ νŠΈλžœμž­μ…˜μ΄ μ‘΄μž¬ν•˜λ©΄ 쀑첩 νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν•˜κ³ , κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ 일반 νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν•©λ‹ˆλ‹€.

    @Transactional(propagation = Propagation.NESTED)
    public void nestedMethod() {
        // ν˜„μž¬ νŠΈλžœμž­μ…˜μ΄ μ‘΄μž¬ν•˜λ©΄ 쀑첩 νŠΈλžœμž­μ…˜ μ‹œμž‘, κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ 일반 νŠΈλžœμž­μ…˜ μ‹œμž‘
    }

Isolation(격리 μˆ˜μ€€):

  • νŠΈλžœμž­μ…˜μ˜ 격리 μˆ˜μ€€μ„ μ§€μ •ν•œλ‹€

μ’…λ₯˜

  1. READ_UNCOMMITTED (미확인 읽기):

    • 문제점: Dirty Read (λ”λŸ¬μš΄ 읽기)

    • λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ 아직 μ»€λ°‹λ˜μ§€ μ•Šμ€ λ³€κ²½ λ‚΄μš©μ„ 읽을 수 μžˆμŠ΅λ‹ˆλ‹€.

    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void readUncommittedMethod() {
        // λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ˜ μ»€λ°‹λ˜μ§€ μ•Šμ€ λ³€κ²½ λ‚΄μš©μ„ 읽을 수 있음
    }
    • μ˜ˆμ‹œ:

      • A μ‚¬μš©μžκ°€ 10000원을 은행 κ³„μ’Œμ— μž…κΈˆν•˜λŠ” νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν–ˆμ§€λ§Œ 아직 μ»€λ°‹ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. 이 λ•Œ, B μ‚¬μš©μžκ°€ κ³„μ’Œ μž”μ•‘μ„ μ‘°νšŒν•˜λ©΄ 10000원이 더해진 μž”μ•‘μ„ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. λ§Œμ•½ A μ‚¬μš©μžκ°€ νŠΈλžœμž­μ…˜μ„ λ‘€λ°±ν•˜λ©΄ B μ‚¬μš©μžλŠ” 잘λͺ»λœ 정보λ₯Ό λ³Έ 것이 λ©λ‹ˆλ‹€.

  2. READ_COMMITTED (확인 읽기):

    • 문제점: Non-Repeatable Read (λΉ„λ°˜λ³΅ 읽기)

    • λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ μ»€λ°‹λœ λ³€κ²½ λ‚΄μš©λ§Œ 읽을 수 μžˆμŠ΅λ‹ˆλ‹€.

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void readCommittedMethod() {
        // λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ˜ μ»€λ°‹λœ λ³€κ²½ λ‚΄μš©λ§Œ 읽을 수 있음
    }
    • μ˜ˆμ‹œ:

      • A μ‚¬μš©μžκ°€ μžμ‹ μ˜ κ³„μ’Œ μž”μ•‘μ„ μ‘°νšŒν–ˆμ„ λ•Œ 50000원이 λ‚˜μ˜΅λ‹ˆλ‹€. κ·Έ 사이 B μ‚¬μš©μžκ°€ A μ‚¬μš©μžμ˜ κ³„μ’Œμ—μ„œ 20000원을 μΆœκΈˆν–ˆμŠ΅λ‹ˆλ‹€. A μ‚¬μš©μžκ°€ λ‹€μ‹œ μž”μ•‘μ„ μ‘°νšŒν•˜λ©΄ 30000원이 λ‚˜μ˜΅λ‹ˆλ‹€. 같은 νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ 두 번의 쑰회 κ²°κ³Όκ°€ λ‹€λ¦…λ‹ˆλ‹€.

  3. REPEATABLE_READ (반볡 κ°€λŠ₯ν•œ 읽기):

    • 문제점: Phantom Read (유령 읽기)

    • νŠΈλžœμž­μ…˜μ΄ μ‹œμž‘ν•  λ•Œ 읽은 λ°μ΄ν„°λŠ” ν•΄λ‹Ή νŠΈλžœμž­μ…˜ λ™μ•ˆ λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ— μ˜ν•΄ λ³€κ²½λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void repeatableReadMethod() {
        // νŠΈλžœμž­μ…˜ λ™μ•ˆ 읽은 λ°μ΄ν„°λŠ” λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ— μ˜ν•΄ λ³€κ²½λ˜μ§€ μ•ŠμŒ
    }
    • μ˜ˆμ‹œ:

      • A μ‚¬μš©μžκ°€ 30μ„Έ μ΄ν•˜μ˜ 고객을 μ‘°νšŒν–ˆμ„ λ•Œ 5λͺ…이 λ‚˜μ˜΅λ‹ˆλ‹€. κ·Έ 사이 B μ‚¬μš©μžκ°€ μƒˆλ‘œμš΄ 30μ„Έ μ΄ν•˜μ˜ 고객을 μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€. A μ‚¬μš©μžκ°€ λ‹€μ‹œ 30μ„Έ μ΄ν•˜μ˜ 고객을 μ‘°νšŒν•˜λ©΄ 6λͺ…이 λ‚˜μ˜΅λ‹ˆλ‹€.

  4. SERIALIZABLE (직렬화 κ°€λŠ₯):

    • νŠΈλžœμž­μ…˜λ“€μ΄ 순차적으둜 μ‹€ν–‰λ˜μ–΄ λ™μ‹œμ„± λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•Šλ„λ‘ ν•©λ‹ˆλ‹€.

    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void serializableMethod() {
        // μ½”λ“œ
    }
    • μ˜ˆμ‹œ:

      • A μ‚¬μš©μžκ°€ μžμ‹ μ˜ κ³„μ’Œ μž”μ•‘μ„ λ³€κ²½ν•˜λŠ” νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν•˜λ©΄, κ·Έ λ™μ•ˆ B μ‚¬μš©μžλŠ” A μ‚¬μš©μžμ˜ κ³„μ’Œμ— μ–΄λ– ν•œ μž‘μ—…λ„ μˆ˜ν–‰ν•  수 μ—†μŠ΅λ‹ˆλ‹€. A μ‚¬μš©μžμ˜ νŠΈλžœμž­μ…˜μ΄ μ™„λ£Œλ  λ•ŒκΉŒμ§€ κΈ°λ‹€λ €μ•Ό ν•©λ‹ˆλ‹€

λ™μ‹œμ„± 문제

  1. Dirty Reads (μ˜€μ—Όλœ 읽기):

    • ν•œ νŠΈλžœμž­μ…˜μ—μ„œ λ³€κ²½λœ (κ·ΈλŸ¬λ‚˜ 아직 μ»€λ°‹λ˜μ§€ μ•Šμ€) 데이터λ₯Ό λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ μ½λŠ” 경우 λ°œμƒν•©λ‹ˆλ‹€. 이둜 인해 아직 ν™•μ •λ˜μ§€ μ•Šμ€ 데이터λ₯Ό 기반으둜 μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    • 해결방법:

      • READ_COMMITTED μ΄μƒμ˜ 격리 μˆ˜μ€€μ„ μ‚¬μš©ν•˜μ—¬ Dirty Readsλ₯Ό λ°©μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ μ»€λ°‹λœ λ°μ΄ν„°λ§Œ 읽게 λ©λ‹ˆλ‹€.

  2. Non-Repeatable Reads (λΉ„λ°˜λ³΅ κ°€λŠ₯ν•œ 읽기):

    • ν•œ νŠΈλžœμž­μ…˜ 도쀑에 같은 데이터λ₯Ό 두 번 이상 읽을 λ•Œ, 두 번째 μ½κΈ°μ—μ„œ 첫 번째 읽기와 λ‹€λ₯Έ 값을 μ–»λŠ” 경우 λ°œμƒν•©λ‹ˆλ‹€. μ΄λŠ” λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ— μ˜ν•΄ ν•΄λ‹Ή 데이터가 λ³€κ²½λ˜μ—ˆκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

    • 해결방법:

      • REPEATABLE_READ μ΄μƒμ˜ 격리 μˆ˜μ€€μ„ μ‚¬μš©ν•˜μ—¬ Non-Repeatable Readsλ₯Ό λ°©μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. νŠΈλžœμž­μ…˜μ΄ μ‹œμž‘λ  λ•Œ 읽은 λ°μ΄ν„°λŠ” ν•΄λ‹Ή νŠΈλžœμž­μ…˜ λ™μ•ˆ λ³€κ²½λ˜μ§€ μ•Šλ„λ‘ 보μž₯λ©λ‹ˆλ‹€.

  3. Phantom Reads (ν™˜μ˜ 읽기):

    • ν•œ νŠΈλžœμž­μ…˜ 도쀑에 νŠΉμ • 쑰건을 기반으둜 데이터λ₯Ό 두 번 이상 읽을 λ•Œ, 두 번째 μ½κΈ°μ—μ„œ 첫 번째 μ½κΈ°μ—μ„œ λ³΄μ•˜λ˜ λ°μ΄ν„°μ˜ μˆ˜μ™€ λ‹€λ₯΄κ²Œ λ‚˜νƒ€λ‚˜λŠ” 경우 λ°œμƒν•©λ‹ˆλ‹€. μ΄λŠ” λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ— μ˜ν•΄ μƒˆλ‘œμš΄ 데이터가 μΆ”κ°€λ˜κ±°λ‚˜ μ‚­μ œλ˜μ—ˆκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

    • 해결방법:

      • SERIALIZABLE 격리 μˆ˜μ€€μ„ μ‚¬μš©ν•˜μ—¬ Phantom Readsλ₯Ό λ°©μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. νŠΈλžœμž­μ…˜λ“€μ΄ 순차적으둜 μ‹€ν–‰λ˜μ–΄, ν•œ νŠΈλžœμž­μ…˜μ΄ μ‹€ν–‰λ˜λŠ” λ™μ•ˆ λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ λ°μ΄ν„°μ˜ μΆ”κ°€λ‚˜ μ‚­μ œκ°€ λ°œμƒν•˜μ§€ μ•Šλ„λ‘ ν•©λ‹ˆλ‹€.

Timeout (μ‹œκ°„ 초과):

  • timeout μ˜΅μ…˜μ€ ν•΄λ‹Ή νŠΈλžœμž­μ…˜μ΄ μ§€μ •λœ μ‹œκ°„ 내에 μ™„λ£Œλ˜μ§€ μ•ŠμœΌλ©΄ κ°•μ œλ‘œ λ‘€λ°±λ©λ‹ˆλ‹€.

    @Transactional(timeout = 5)  // 5초
    public void timeoutMethod() {
        // 이 νŠΈλžœμž­μ…˜μ€ 5초 내에 μ™„λ£Œλ˜μ§€ μ•ŠμœΌλ©΄ λ‘€λ°±λ©λ‹ˆλ‹€.
    }

Read-only (읽기 μ „μš©):

  • readOnly μ˜΅μ…˜μ€ ν•΄λ‹Ή νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ 데이터 λ³€κ²½ μž‘μ—…μ΄ λ°œμƒν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•©λ‹ˆλ‹€. 읽기 μ „μš© μž‘μ—…μ—μ„œλŠ” μ„±λŠ₯ ν–₯상이 μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

    @Transactional(readOnly = true)
    public Account getAccount(Long id) {
        // 이 λ©”μ„œλ“œλŠ” 데이터λ₯Ό 읽기만 ν•΄μ•Ό ν•©λ‹ˆλ‹€. 데이터 μˆ˜μ •μ€ ν•˜λ©΄ μ•ˆ λ©λ‹ˆλ‹€.
        return accountRepository.findById(id).orElse(null);
    }

μ„±λŠ₯ ν–₯상 이유:

  1. μ΅œμ ν™”λœ λ°μ΄ν„°λ² μ΄μŠ€ μ—”μ§„ λ™μž‘:

    • λŒ€λΆ€λΆ„μ˜ RDBMSλŠ” μ—¬λŸ¬ μœ ν˜•μ˜ 락킹 λ©”μ»€λ‹ˆμ¦˜μ„ μ œκ³΅ν•©λ‹ˆλ‹€. 읽기 μ „μš© νŠΈλžœμž­μ…˜μ˜ 경우, λ°μ΄ν„°λ² μ΄μŠ€λŠ” 데이터 변경에 κ΄€λ ¨λœ 락(예: μ“°κΈ° 락)을 νšλ“ν•˜λŠ” 것을 λ°©μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이둜 인해 읽기 μ „μš© νŠΈλžœμž­μ…˜μ€ λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ— μ˜ν•΄ λΈ”λ‘œν‚Ήλ˜λŠ” λΉˆλ„κ°€ 쀄어듀 수 μžˆμŠ΅λ‹ˆλ‹€.

    • 예: μƒμ μ˜ 재고 확인 μ‹œμŠ€ν…œμ—μ„œ, μ—¬λŸ¬ μ‚¬μš©μžκ°€ λ™μ‹œμ— 재고λ₯Ό ν™•μΈν•˜λŠ” κ²½μš°μ—, 읽기 μ „μš© νŠΈλžœμž­μ…˜μ„ μ‚¬μš©ν•˜λ©΄ λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ 재고 정보λ₯Ό λΉ λ₯΄κ²Œ κ°€μ Έμ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€. 데이터 변경이 μ—†κΈ° λ•Œλ¬Έμ—, μ“°κΈ° 락 없이 정보λ₯Ό μ‘°νšŒν•  수 μžˆμ–΄, λΈ”λ‘œν‚Ή 없이 λ™μ‹œμ— μ—¬λŸ¬ μ‚¬μš©μžμ˜ μš”μ²­μ„ μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  2. 버전 관리와 락킹 μ΅œμ†Œν™”:

    • ORM 도ꡬ(예: Hibernate)λŠ” 데이터 변경을 μΆ”μ ν•˜κΈ° μœ„ν•΄ λ‚΄λΆ€μ μœΌλ‘œ 버전 관리λ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” λ°μ΄ν„°λ² μ΄μŠ€ 행에 λŒ€ν•œ 버전 번호λ₯Ό μ‚¬μš©ν•˜μ—¬, 두 μ‚¬μš©μžκ°€ λ™μ‹œμ— 같은 데이터λ₯Ό μˆ˜μ •ν•˜λŠ” 상황(λ™μ‹œμ„± 문제)을 ν•΄κ²°ν•˜λŠ”λ° 도움을 μ€λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 읽기 μ „μš© νŠΈλžœμž­μ…˜μ—μ„œλŠ” 데이터 변경이 μ—†μœΌλ―€λ‘œ, μ΄λŸ¬ν•œ 버전 관리가 ν•„μš” μ—†μ–΄μ§‘λ‹ˆλ‹€.

    • 예: μ€ν–‰μ˜ κ³„μ’Œ μž”μ•‘ 확인 μ‹œμŠ€ν…œμ—μ„œ, μ‚¬μš©μžκ°€ μž”μ•‘λ§Œ ν™•μΈν•˜λ €λŠ” 경우, 읽기 μ „μš© νŠΈλžœμž­μ…˜μ„ μ‚¬μš©ν•˜λ©΄ ORM이 버전 κ΄€λ¦¬λ‚˜ 락킹 λ©”μ»€λ‹ˆμ¦˜μ„ μ μš©ν•˜μ§€ μ•Šμ•„λ„ λ˜λ―€λ‘œ, 응닡 속도가 ν–₯상될 수 μžˆμŠ΅λ‹ˆλ‹€.

  3. 캐싱 νš¨μœ¨μ„±:

    • ORM ν”„λ ˆμž„μ›Œν¬λŠ” μ’…μ’… 쿼리 κ²°κ³Όλ₯Ό μΊμ‹œν•˜μ—¬, λ™μΌν•œ 쿼리에 λŒ€ν•΄ λΉ λ₯Έ 응닡 μ‹œκ°„μ„ μ œκ³΅ν•©λ‹ˆλ‹€. 읽기 μ „μš© νŠΈλžœμž­μ…˜μ—μ„œλŠ” 데이터 변경이 μ—†κΈ° λ•Œλ¬Έμ—, μΊμ‹œλœ λ°μ΄ν„°μ˜ μœ νš¨μ„±μ— λŒ€ν•œ μš°λ €κ°€ μ€„μ–΄λ“­λ‹ˆλ‹€.

    • 예: λ‰΄μŠ€ μ›Ήμ‚¬μ΄νŠΈμ—μ„œ, μ‚¬μš©μžκ°€ νŠΉμ • μΉ΄ν…Œκ³ λ¦¬μ˜ λ‰΄μŠ€ λͺ©λ‘μ„ μ‘°νšŒν•˜λŠ” 경우, 읽기 μ „μš© νŠΈλžœμž­μ…˜μ„ μ‚¬μš©ν•˜λ©΄ ORM ν”„λ ˆμž„μ›Œν¬λŠ” 이전에 쑰회된 κ²°κ³Όλ₯Ό μΊμ‹œμ—μ„œ λΉ λ₯΄κ²Œ κ°€μ Έμ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

  4. 일관성 μœ μ§€:

    • 읽기 μ „μš© νŠΈλžœμž­μ…˜μ€ μ‹€μˆ˜λ‘œ 데이터 변경을 λ°©μ§€ν•©λ‹ˆλ‹€. μ˜λ„μΉ˜ μ•Šκ²Œ 데이터λ₯Ό λ³€κ²½ν•˜λŠ” 것은 μ„±λŠ₯ 문제뿐만 μ•„λ‹ˆλΌ 데이터 무결성 문제λ₯Ό μ•ΌκΈ°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    • 예: 병원 μ‹œμŠ€ν…œμ—μ„œ, ν™˜μžμ˜ 병λ ₯을 ν™•μΈν•˜λŠ” 경우, 읽기 μ „μš© νŠΈλžœμž­μ…˜μ„ μ‚¬μš©ν•˜λ©΄, μ‹€μˆ˜λ‘œ ν™˜μž 정보λ₯Ό λ³€κ²½ν•˜λŠ” 것을 λ°©μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Rollback rules (λ‘€λ°± κ·œμΉ™):

  • 기본적으둜 λŸ°νƒ€μž„ μ˜ˆμ™Έ(RuntimeException 및 κ·Έ ν•˜μœ„ μ˜ˆμ™Έ)κ°€ λ°œμƒν•˜λ©΄ 둀백을 μˆ˜ν–‰ν•©λ‹ˆλ‹€

  • rollbackFor

    • 이 속성을 μ‚¬μš©ν•˜λ©΄ νŠΉμ • μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμ„ λ•Œ νŠΈλžœμž­μ…˜μ„ λ‘€λ°±ν•˜λŠ” κ·œμΉ™μ„ μ§€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    @Transactional(rollbackFor = InsufficientBalanceException.class)
    public void transferMoney() {
        // InsufficientBalanceException이 λ°œμƒν•˜λ©΄ νŠΈλžœμž­μ…˜μ€ λ‘€λ°±λ©λ‹ˆλ‹€.
    }
  • noRollbackFor

    • 이 속성은 μ§€μ •λœ μ˜ˆμ™Έ μœ ν˜•μ— λŒ€ν•œ 둀백을 λ°©μ§€ν•©λ‹ˆλ‹€. 즉, ν•΄λ‹Ή μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ”λΌλ„ νŠΈλžœμž­μ…˜μ€ λ‘€λ°±λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

    @Transactional(noRollbackFor = BusinessException.class)
    public void businessOperation() {
        // ...
        // BusinessException이 λ°œμƒν•΄λ„ νŠΈλžœμž­μ…˜μ€ λ‘€λ°±λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
    }

AOP (관점 μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°):

  • λ‚΄λΆ€ λ©”μ„œλ“œ ν˜ΈμΆœμ—μ„œλŠ” **@Transactional**이 μ œλŒ€λ‘œ λ™μž‘ν•˜μ§€ μ•ŠλŠ” λ¬Έμ œλŠ” Spring의 ν”„λ‘μ‹œ 방식 λ•Œλ¬Έμž…λ‹ˆλ‹€. ν•΄λ‹Ή 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ©”μ„œλ“œ ν˜ΈμΆœμ„ μ™ΈλΆ€ λΉˆμ„ 톡해 κ°„μ ‘μ μœΌλ‘œ μˆ˜ν–‰ν•˜κ±°λ‚˜, ν”„λ‘œκ·Έλž¨ ꡬ쑰λ₯Ό λ³€κ²½ν•΄μ•Ό ν•©λ‹ˆλ‹€.

    @Service
    public class MyService {
        @Transactional
        public void methodA() {
            // ...
            this.methodB();  // 주의: methodB의 νŠΈλžœμž­μ…˜ 둜직이 μ œλŒ€λ‘œ μ μš©λ˜μ§€ μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€!
        }
        
        @Transactional
        public void methodB() {
            // ...
        }
    }

Last updated 1 year ago

Was this helpful?