@Transactional AOP ๋ก์ง๊ณผ ๋ถ์ฐ๋ฝ AOP ์ ์ค์ฒฉํด์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ @Transactional ์ ๋์ค์ ์คํ์ํค๊ณ ์ถ์๋ค. ์ด๋ฅผ ์ ์ฉํ๊ธฐ ์ํด ๊ฒํ ํ๋ ์ฝ๋ ๊ธฐ๋ก์ด๋ค. ํด๋น ๋ด์ฉ์ kurly techblog ์์ ๋ถ์ฐ๋ฝ ๋ด์ฉ์ ๋ณด๊ณ ์ ์ฉํ๋ ๊ณผ์ ์์ ๋ ๊ณ ๋ฏผ์ด๋ค.
์ฐธ๊ณ ์๋ฃ : ํํ๋จผํธ ์ ๊ณ ์๋น์คํ์์ ๋ถ์ฐ๋ฝ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ - Spring Redisson
[1] ๋ถ์ฐ๋ฝ์ ๋ฝ ์ ์ /ํด์ ๋ธ๋ก ์์์ Transaction ๋ฅผ ๋ฌถ์ด์ผ ํ๋ค.
๋ถ์ฐ๋ฝ์ ์ฌ์ฉํด์ผ ํ๋ ์ด์ ๋ ๋ฌด์์ผ๊น? ๊ทธ ์ด์ ๋ ๋ถ์ฐ ํ๊ฒฝ์ ๋์์ฑ ์ ์ด๋ฅผ ์ํจ์ด๋ค. ๋ถ์ฐ๋ฝ์ ์๊ณ ์์ญ์ ๋ค๋ฅธ ์์ฒญ์ด ์ ๊ทผ์ ๋ง์ ์ปดํฌ๋ํธ๊ฐ ๋ฐ์ดํฐ ์ ํฉ์ฑ์ ๋ณด์ฅํ๋ ๋ฐฉ์์ด๋ค. ๊ฐ ์ ์ฅ์๋ ๋ ๋ฆฝ์ ์ธ ๋ก์ปฌ ํธ๋์ญ์ ์ ์ง์ํ์ง๋ง, ์ด์ข ๋ฐ์ดํฐ๋ฒ ์ด์ค(hetero database) ์ ํธ๋์ญ์ ์ ์ง์ํ์ง ์๋๋ค. ์ด๋ฅผ ๋ถ์ฐ๋ฝ์ ์ฌ์ฉํด ๋จ์ผ ์์ฒญ๋ง ์ ๊ทผ์ ํ์ฉํด ๋์์ฑ ์ ์ด๋ฅผ ๋ณด์ฅํ๋ค.
๋ง์ฝ ๋ถ์ฐ๋ฝ๊ณผ ํจ๊ป ํธ๋์ญ์ ์ ์ ์ธํด ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ์ ์งํ๊ณ ์ถ๋ค๋ฉด ๋ถ์ฐ๋ฝ์ ๋ฝ ์ ์ /ํด์ ๋ธ๋ก ์์ ํธ๋์ญ์ ์ ์คํ์์ผ์ผ ํ๋ค. ๋ง์ฝ lock block ๋ด๋ถ์ ํธ๋์ญ์ ์ ์ ์ธํ์ง ์์ ๊ฒฝ์ฐ ํํ ํธ๋์ญ์ ์ด ์๊ณ ์์ญ์ ์ ๊ทผ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ ์ฝ๊ธฐ ์์ ์์ ์ผ๊ด์ฑ์ด ๊บ ์ง๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ ์ ์์ด ๋์์ฑ ์ ์ด๋ฅผ ํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ ์ ์๋ค.

[2] custom Aspect ๊ฐ @Transactional ๋ณด๋ค ์คํ์ด ๋ฆ์ ์ด์ ๋?
์ด์ ๋ถ์ฐ๋ฝ์ ์ ์ฉํ๊ธฐ ์ํด @Transactional ์ ๋ถ์ฐ๋ฝ AOP ์ ์ฉ์ ์ํด ์ปค์คํ ์ด๋ ธํ ์ด์ @DistributedLock ์ ์ ์ธํ๋ค.
ํ์ง๋ง ์์๊ณผ๋ ๋ค๋ฅด๊ฒ ๋ถ์ฐ๋ฝ Aspect ์ ์ ์ฉํ๋ฉฐ @Transactional ๋ณด๋ค ๋ฆ๊ฒ ์คํ๋๋ ๋ฌธ์ ๊ฐ ์์๋ค. ์ด ์ํฉ์ ๊ณง ์ ํฉ์ฑ ๋ณด์ฅ ๋ฐ ๋์์ฑ ์ ์ด๋ฅผ ํ ์ ์์์ ์๋ฏธํ๋ฏ๋ก AopForTransaction ์ด๋ผ๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํด @Transactional ์ ๋ถ๋ฆฌํ๊ณ ์ ํ๋ค. ์ฒ์์๋ ํด๋น ๋ฐฉ์์ ๋์ํ๋ฉฐ ๊ธฐ์กด์ ์ ์ธํ @Transactional ์ ์ ์ฉํ๊ณ AopForTranaction ์ ๋์ ํด ์ ์ฉํ๋ค.
๐จ ๊ทธ๋ฐ๋ฐ ๋ง์ฝ ๋ถ์ฐ๋ฝ์์ ํธ๋์ญ์ ์ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด??
๋ถํ์ํ DB connection ๊ณผ ๊ฐ์ ๋ถํ์ํ ๋ฆฌ์์ค๋ฅผ ์๋ชจํ๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ ๋ฐฉ์์ ์ ์ ํ์ง ์๋ ๋ฐฉ์์ด๋ผ๋ ํผ๋๋ฐฑ์ด ์์๋ค.
๊ทธ๋์ @Transactional ์ ์์๋ฅผ ์ ์ดํ๊ธฐ ์ํด ๊ณต์ ์ฝ๋๋ฅผ ํ์ธํด๋ณด์๋ค.

[3] @Transactional ์ ์ฐ์ ์์๋ ๊ฐ์ฅ ๋ฎ๋ค. (Ordered.LOWEST_PRECEDENCE)
@Transactional ์ฐ์ ์์๋ฅผ ํ์ธํด๋ณด์. spring docs ์ ๋ณด๋ฉด @Transactional ์ ์ฐ์ ์์๋ ๊ฐ์ฅ ๋ฎ๋ค. ํ์ง๋ง ์ฃผ์์ฌํญ์ด ์๋ค.
๋ง์ฝ ๋ค๋ฅธ ๋ก์ง์์ @Order ์ด๋ ธํ ์ด์ ์ ์ธ ๋๋ Ordered ์ธํฐํ์ด์ค ๊ตฌํ์ด ๋์ด ์์ง ์๋ค๋ฉด ์๋ฌด๋ฆฌ @Transactional ์ด ์ฐ์ ์์๊ฐ ๋ฎ๋๋ผ๋ ๋จผ์ ์คํ๋๋ค.
spring docs :Using @Transactional

[4] @Transactional ์ ์ฐ์ ์์ ์ฝ๋๋ก ํ์ธํด๋ณด๊ธฐ
(1) SpringBoot autoconfiguartion ์ฐ๋จนํ๊ธฐ
SpringBoot 3.x ๋ถํฐ๋ spring.factories ๋์ AutoConfiguration.imports๋ฅผ ์ฌ์ฉํ์ฌ ์๋ ์ค์ ์ ๋์ฑ ๋ช ํํ๊ฒ ๊ด๋ฆฌํ๋ค. SpringBoot 3.x ์๋ ์ค์ ์ ์๋๋ฅผ ์ฐธ๊ณ ํ์.
- @SpringBootApplication ๋ด๋ถ์ @EnableAutoConfiguration์ด ์๋ ์ค์ ์ ํ์ฑํํจ.
- AutoConfiguration.imports์์ ์๋ ์ค์ ํด๋์ค ๋ชฉ๋ก์ ๊ฐ์ ธ์ด.
- AutoConfigurationImportSelector๊ฐ ์๋ ์ค์ ํด๋์ค๋ฅผ ๋ก๋ํจ.
- @ConditionalOnClass์ @ConditionalOnMissingBean ๋ฑ์ ์กฐ๊ฑด์ ํ์ธํ์ฌ ์๋ ์ค์ ์ ์ ์ฉํจ.
- ํ์ํ ๊ฒฝ์ฐ ํน์ ์๋ ์ค์ ์ excludeํ์ฌ ๋นํ์ฑํ ๊ฐ๋ฅ.


[๐ ์ถ๊ฐ์ ์ผ๋ก AutoConfiguration ์คํ ์์๋ฅผ ์๋๋ฅผ ํตํด์ ํ์ธํด๋ณด์.]
- spring-boot-autoconfigure-3.4.1.jar!/META-INF/spring-autoconfigure-metadata.properties

# jdbc autoconfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration.AutoConfigureBefore=org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
# hibernate autoconfiguration
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration.AutoConfigureBefore=org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
# transaction autoconfiguration
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration=
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$AspectJTransactionManagementConfiguration=
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$AspectJTransactionManagementConfiguration.ConditionalOnBean=org.springframework.transaction.aspectj.AbstractTransactionAspect
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration=
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration.ConditionalOnBean=org.springframework.transaction.TransactionManager
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$TransactionTemplateConfiguration=
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$TransactionTemplateConfiguration.ConditionalOnSingleCandidate=org.springframework.transaction.PlatformTransactionManager
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration.ConditionalOnClass=org.springframework.transaction.PlatformTransactionManager
(2) @EnableTransactionManager ๊ฐ ์์ผ๋ฉด TransactionAutoConfiguration ์ค์ ์์ @EnableTransactionManager ๋ฅผ ์ค์ ํ๋ค.
TransactionAutoConfiguration ์ ์ดํด๋ณด์.
์๋ spring-autoconfigure-metadata.properties ๋ฅผ ํ์ธํ๋ฉด ์๋์ ๊ฐ์ด ํ์๋์ด ์๋ค. ํด๋น ์๋ฏธ๋ EnableTransactionManagementConfiguration ๋ฅผ ํด๋น ํด๋์ค ๋น์ผ๋ก ๋ฑ๋ก๋์ด์ผ ํ๋ค๋ ์๋ฏธ์ด๋ฉฐ, ๊ฑฐ์ ๋๋ถ๋ถ @Configuration ์ด ์ถ๊ฐ๋์ด ๋น์ผ๋ก ๋ฑ๋ก๋๋ค.

์ด๋ฅผ TransactionAutoConfiguration ์์ ํ์ธํด๋ณด๋ฉด
๊ธฐ๋ณธ ์ค์ ์ผ๋ก EnableTransactionManagementConfiguration ์ @Configuration ์ ํตํด ๋ฑ๋กํ๊ณ @EnableTransactionManager ์ค์ ์ ์ถ๊ฐํ๋ค.

(3) @EnableTransactionManager ๋ TransactionManagementConfigurationSelector ์ ํตํด ์ค์ ํ๋ค.
@EnableTransactionManager ๋TransactionManagementConfigurationSelector ์ ๊ดํ ์ค์ ํ์ผ์ ํธ์ถํด ๊ด๋ จ ์ค์ ์ ํ์ฑํ ํ๋ค.

์ด ๋, TransactionManagementConfigurationSelector ๋ด๋ถ ์ฝ๋๋ฅผ ํ์ธํด๋ณด๋ฉด AdviceMode.PROXY ์ ๋ถ๊ธฐ ์ฒ๋ฆฌ๋์ด ProxyTransactionManagerConfiguration ์ ์ค์ ์ ๊ฐ์ ธ์ ์ฌ์ฉํ๊ฒ ๋๋ค.
- AdviceMode.PROXY ๋ JDK-Dynamic-Proxy ๋๋ CGLIB Proxy ๋ฅผ ํ์ฑํ ํ๋ ๊ฒฝ์ฐ์ ์ ์ธํ๋ ์์์ด๋ค. ํด๋น ๋ด์ฉ์์๋ ํด๋น ์ฃผ์ ๋ฅผ ๋ค๋ฃจ์ง ์๋๋ค.

(4) ProxyTransactionManagementConfiguration ์์ TransactionInteceptor ์ ์ธ ๋ฐ ์์ ์ค์
- BeanFactoryTransactionAttributeSourceAdvisor
- Spring AOP ๊ธฐ๋ฐ ํธ๋์ญ์ ์ ์ฉ์ ์ํ ํต์ฌ ์ปดํฌ๋ํธ
- AOP์์ ํธ๋์ญ์ ์ ์ด๋๋ฐ์ด์ค(Advice)๋ก ์ ์ฉํ ๋์์ ์ค์ ํ๋ ์ญํ
- TransactionInterceptor
- ํธ๋์ญ์ ์ ์์, ์ปค๋ฐ, ๋กค๋ฐฑํ๋ ์ค์ ์์ ์ ์ฒ๋ฆฌํ๋ ์ปดํฌ๋ํธ
์๋ ๋นจ๊ฐ ๋ค๋ชจ๋ฅผ ํ์ธํด๋ณด๋ฉด advisor ์ ์์๋ฅผ ์ค์ ํ๊ธฐ ์ํด @EnableTransactionManager ์ order option ์ ๊ฐ์ ธ์ ์คํ ์์๋ฅผ ์กฐํํด ์ฃผ์ ํ๊ณ ์ด๋ฅผ @Transactional ์ด๋ ธํ ์ด์ ์ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์ ์คํ ์์๋ก ์ฌ์ฉ๋๋ค. ๊ฒฐ๊ตญ ์ด ๋ถ๋ถ์ด @Transactional ์ด ์ ์ธ๋์ด BeanFactoryTransactionAttributeSourceAdvisor ์คํ ์์๋ฅผ ์ ์ดํ๋ ์ญํ ์ด๋ค.

๊ทธ๋์ ๊ฒฐ๋ก ์ @Transactional ์ @Order ์คํ ๋๋ Ordered interface ๊ตฌํํ์ ๋์ ์ฐ์ ์์๋ ๊ฐ์ฅ ํ์!

[5] @Transactional ๋ณด๋ค ๋จผ์ ์คํํ๊ธฐ = @Aspect ์ @Order ์ ์ธํด ์์ ์ค์ ํ๊ธฐ
@Transactional ๋ณด๋ค ๋จผ์ ์คํํ๊ธฐ ์ํด์๋ @Order ์ด๋ ธํ ์ด์ ์ฌ์ฉํ๋ฉด ๊ฐ๋จํ ํด๊ฒฐ๋๋ค. ์์ ์ด์ผ๊ธฐํ๋ฏ์ด @Order ์ ์ฐ์ ์์๋ ๊ฐ์ด ๋ฎ์์๋ก ์ฐ์ ์์๊ฐ ๋๋ค.
Ordered.LOWEST_PRECEDENCE ๋ฅผ ํ์ธํด๋ณด๋ฉด Integer.MAX_VALUE ๋ก ์ ์ธ๋์ด ์๋ค. ๊ทธ๋ฌ๋ฏ๋ก @Transactional ๋ณด๋ค ๋จผ์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ Integer.MAX_VALUE ๋ณด๋ค ์์ ๊ฐ์ ์ ์ธํ๋ฉด ํด๊ฒฐ๋ ๊ฒ์ด๋ค.


[6] ๊ฒฐ๋ก
์คํ๋ง ๋ถํธ๋ ์๋ ์ค์ ์ ๊ดํด ์ ์ง์ํด์ค ์ด์ ์ ์ค์ ์ ํ์ธ์์ด ๊ฒฐ๋ ธ๋ ์คํ๋ง์ ์ฌ์ฉํ ๋๋ณด๋ค ํธํ๋ค.
์ธ๋ถ ๊ตฌํ์ ๋ํด ์์ง ๋ชปํด๋ ์ถ์ํ๊ฐ ์ ๋์ด ์์ด ํ๋กํผํฐ ๊ฐ๋ง ๋ณ๊ฒฝํ๋ฉด ๊ด๋ จ ์ค์ ์ ์๋์ผ๋ก ํด์ค๋ค.
ํ์ง๋ง, ์๋ ์ค์ ์ ํธ์ํจ์ ์ทจํด ์ฌ์ฉํ๋๋ฐ๋ง ์ต์ํด์ง๋ฉด ์กฐ๊ธ๋ง ๋ค๋ฅธ ์ผ์ด์ค๊ฐ ๋ฐ์ํด๋ ํด๊ฒฐํ์ง ๋ชปํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค.
๋น๋ก ๋ชจ๋ ์คํ๋ง ์ฝ๋๋ฅผ ๊ณต๋ถํ๊ณ ์ดํดํ ์๋ ์์ง๋ง ์คํ๋ง์์ ํต์ฌ์ด ๋๋ ์ฝ๋๋ค์ ํ์ํ ๋๋ง๋ค ์ฝ์ด๋ณด๋ ์ฐ์ต์ด ํ์ํ ๊ฒ ๊ฐ๋ค.
๊ฐ๋ง์ ๋ด๋ถ ์ฝ๋๋ฅผ ๋ณด๋ฉด์ ๋ง์น ๋ฏธ๋ก ์ฐพ๋ฏ์ด ์ด๋ ค์์ ์์์ง๋ง ๋ค์์ ๋ค๋ฅธ ์คํ๋ง ์ฝ๋๋ฅผ ๋ณผ ๋๋ ์์ํ๊ฒ ๋ณผ ์ ์๊ธฐ๋ฅผ ๊ธฐ๋ํด๋ณธ๋ค. ๐จ๐ป
'๐ backend > spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| Presigned URL ๋ก ํ์ผ ์ ๋ก๋ ๊ธฐ๋ฅ์ ์ ์ ์ฉํ๋๋ฉด์. (1) | 2025.06.01 |
|---|---|
| Spring6.1 ๋ถํฐ ๋ณ๊ฒฝ๋ Parameter Name Retention (0) | 2025.03.11 |
| ์ค๋ณต๋๋ ์ค์ผ์ค๋ง ๋ถ์ฐ๋ฝ์ผ๋ก ํ๋๋ง ์คํํ๊ธฐ(w.ShedLock) (0) | 2025.01.16 |
| Spring REST Docs + Swagger UI ๋ฅผ ํตํ API ๋ฌธ์ํ (0) | 2024.12.07 |
| ๋น๊ด์ ๋ฝ vs ๋๊ด์ ๋ฝ(In JPA) (0) | 2024.11.28 |