๐ก ํธ๋์ญ์
๐ค ํธ๋์ญ์ ์ด๋?
ํธ๋์ญ์ ์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํน์ ์ ์ฌ ์์คํ ์์ ํ๋์ ์ํธ์์ฉ ๋จ์์ด๋ค.
์ด๋ ๋ฐ์ดํฐ์ ์ ํฉ์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด ๊ณ ์๋ ๋ฐฉ๋ฒ์ด๋ค.
์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ผ๊ด์ฑ ์๊ฒ ์ ์งํ๊ณ , ๋์ ์ ๊ทผํ๋ ์ฌ๋ฌ ํ๋ก๊ทธ๋จ ๊ฐ์ ๊ฒฉ๋ฆฌ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ์กด์ฌํ๋ค.
ํธ๋์ญ์ ๋ด SQL๋ฌธ๋ค์ ๋ชจ๋ ์ฑ๊ณตํ์ฌ commit ๋๊ฑฐ๋, ํ๋๋ผ๋ ์คํจํ๋ ๊ฒฝ์ฐ ์ ์ฒด๊ฐ rollback ๋๋ค.
๐ซจ ACID
ํธ๋์ญ์ ์ด ์ด๋ค ์์ฑ์ ์ง๋ ์ผ ํ๋์ง ๋ํ๋ด๋ ํต์ฌ์ด๋ค.
4๊ฐ์ง ๊ท์น์ ๋ชจ๋ ๋ณด์ฅํด ์์ ํ๊ฒ ์ํ๋์ด์ผ ํ๋ค.
์์์ฑ(Atomicity)
- All or Noting
- ๋ชจ๋ ์ฑ๊ณต or ๋ชจ๋ ์คํจ
ํ๋์ ํธ๋์ญ์ ์ ๋ ผ๋ฆฌ์ ์ผ๋ก ๋๋์ด์ง ์ ์๋ ๋จ์์ด๊ธฐ ๋๋ฌธ์ ๋์ผํ ๊ฒฝ๊ณผ๋ฅผ ๋ณด์ฅํด์ผ ํ๋ค.
์ฆ, ์ผ๋ถ๋ง ์ฑ๊ณตํ๊ฑฐ๋ ์คํจํ๋ ์ํ๋ ์กด์ฌํด์ ์ ๋๋ค.
์ผ๊ด์ฑ(Consistency)
- ํธ๋์ญ์
์ด์ ๊ณผ ์ดํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ํญ์ ์ผ๊ด์ ์ธ ์ํ์ฌ์ผ ํ๋ค.
- ํธ๋์ญ์ ์ DB๋ฅผ Consistency -> Consistency๋ก ๋ณ๊ฒฝํ๋ค.
๋ง์ฝ DB์ ์ ์๋ ๊ท์น์ ์๋ฐํ๋ค๋ฉด ํธ๋์ญ์ ์ ๋กค๋ฐฑ๋์ด์ผ ํ๋ค.
์๋ฅผ ๋ค์ด, ๊ณ์ข ์๊ณ ๊ฐ -๊ฐ ๋ ์ ์๋๋ก ์ค์ ํด ๋์๋ค๋ฉด ์ด๋ฅผ ์ผ๊ด์ฑ ์๊ฒ ์ง์ผ์ผ ํ๋ค.
๋ ๋ฆฝ์ฑ(Isolation)
- ์ฌ๋ฌ ํธ๋์ญ์ ์ด ๋์ ์คํ๋์ด๋, ํ๋์ ํธ๋์ญ์ ์ ๋ ๋ฆฝ์ ์ผ๋ก ๋์ํ๋ ๊ฒ์ด์ด์ผ ํ๋ค.
- ํธ๋์ญ์ ๋ฐ์ ์๋ ์ด๋ ํ ์ฐ์ฐ๋ ํธ๋์ญ์ ์ ์ค๊ฐ ์ฐ์ฐ์ ๋ณผ ์ ์์ด์ผ ํ๋ค.
- DBMS๋ ์ฌ๋ฌ ์ข ๋ฅ์ isolation level์ ์ ๊ณตํ๋ค.
์ง์์ฑ(Durability)
- ์ฑ๊ณต์ ์ผ๋ก ์ํ๋ ํธ๋์ญ์ ์ ์๊ตฌ์ ์ผ๋ก ๋ฐ์๋์ด์ผ ํ๋ค.
- ์ ์์ด ๊บผ์ง ๋ค์๋ ์ ์ฅ๋๋ ๋นํ๋ฐ์ฑ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋์ด์ผ ํ๋ค.
JDBC Template
catch (SQLException e) {
try {
connection.rollback();
} catch (SQLException ex) {
ex.addSuppressed(e);
throw ex;
}
throw e;
}
๐ ๋จ๊ณ๋ณ ์๋ฏธ
1๏ธโฃ dataSource.getConnection()
→ DB ์ปค๋ฅ์
ํ๋
2๏ธโฃ setAutoCommit(false)
→ ์๋ ์ปค๋ฐ ๋๊ธฐ (ํธ๋์ญ์
์์)
3๏ธโฃ ๋น์ฆ๋์ค ๋ก์ง ์ํ
→ ์ฌ๋ฌ SQL ์คํ
4๏ธโฃ commit()
→ ์ ์ ์ข
๋ฃ ์ DB ๋ฐ์
5๏ธโฃ rollback()
→ ์์ธ ๋ฐ์ ์ ๋๋๋ฆฌ๊ธฐ
6๏ธโฃ close()
→ ์ปค๋ฅ์
๋ฐํ (๋ณดํต ํ๋ก ๋ฐํ๋จ)
์ฆ, ํธ๋์ญ์ ๊ฒฝ๊ณ๋ฅผ ๊ฐ๋ฐ์๊ฐ ์ง์ ์ ์ดํ๋ ๋ฐฉ์์ด๋ค.
ํธ๋์ญ์ ๋ฒ์๊ฐ ๋ฉ์๋ ๋ด๋ถ์ ๊ณ ์ ๋๊ฑฐ๋, AOP ๊ธฐ๋ฐ ํธ๋์ญ์ ์ด ๋ถ๊ฐ๋ฅํ์ฌ ์์ฃผ ์ฌ์ฉ๋์ง๋ ์๋๋ค.
โผ๏ธ Spring Transaction
์ ์
์คํ๋ง์ด ์ ๊ณตํ๋ ์ถ์ํ๋ ํธ๋์ญ์ ๊ด๋ฆฌ ๊ธฐ๋ฅ์ผ๋ก ๊ฐ๋ฐ์๊ฐ ๋น์ฆ๋์ค ๋ก์ง์๋ง ์ง์คํ ์ ์๋๋ก
ํธ๋์ญ์ ์์/์ปค๋ฐ/๋กค๋ฐฑ์ ์๋์ผ๋ก ์ฒ๋ฆฌํด ์ฃผ๋ ๊ธฐ๋ฅ์ด๋ค.
PlatformTransactionManager
Spring ํธ๋์ญ์ ์ถ์ํ์ ์ค์ฌ ์ธํฐํ์ด์ค์ด๋ค.
commit์ rollback ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
JDBC, JPA ๋ฑ ๋ชจ๋ ์ด๋ฅผ ๊ตฌํํ์ฌ Spring Transaction์ ์ง์ํ๋ค.
์ด๋ฅผ ํตํด ๊ธฐ์ ์ ๋ ๋ฆฝ์ ์ด๊ณ , ํธ๋์ญ์ ๊ฒฝ๊ณ์ค์ ์ด ๊ฐ๋ฅํด์ก๋ค.
org.springframework.transaction.PlatformTransactionManager ๊ฒฝ๋ก์ ์กด์ฌํ๋ฉฐ
ํ์ฌ ํ์ฑํ๋ ํธ๋์ญ์ ์ ๋ฐํํ๊ฑฐ๋, ์ง์ ๋ ์ ํ(propagation) ๋์์ ๋ฐ๋ผ ์๋ก์ด ํธ๋์ญ์ ์ ์์ฑํฉ๋๋ค.
๊ฒฉ๋ฆฌ ์์ค(isolation level)์ด๋ ํ์์์(timeout)๊ณผ ๊ฐ์ ๋งค๊ฐ๋ณ์๋ ์๋ก์ด ํธ๋์ญ์ ์๋ง ์ ์ฉ๋๋ฉฐ, ์ด๋ฏธ ํ์ฑํ๋ ํธ๋์ญ์ ์ ์ฐธ์ฌํ๋ ๊ฒฝ์ฐ์๋ ๋ฌด์๋ฉ๋๋ค.
๋ํ, ๋ชจ๋ ํธ๋์ญ์ ์ ์ ์ค์ ์ด ๋ชจ๋ ํธ๋์ญ์ ๋งค๋์ ์์ ์ง์๋๋ ๊ฒ์ ์๋๋๋ค. ์ ์ ํ ํธ๋์ญ์ ๋งค๋์ ๊ตฌํ์ฒด๋ ์ง์๋์ง ์๋ ์ค์ ์ด ์ฌ์ฉ๋ ๊ฒฝ์ฐ ์์ธ๋ฅผ ๋ฐ์์์ผ์ผ ํฉ๋๋ค.
์ ๊ท์น์ ์์ธ๋ read-only ํ๋๊ทธ์ ๋๋ค. ๋ช ์์ ์ธ read-only ๋ชจ๋๋ฅผ ์ง์ํ์ง ์๋ ๊ฒฝ์ฐ, ์ด ํ๋๊ทธ๋ ๋ฌด์๋์ด์ผ ํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก read-only ํ๋๊ทธ๋ ์ ์ฌ์ ์ธ ์ต์ ํ๋ฅผ ์ํ ํํธ์ผ ๋ฟ์ ๋๋ค.
์์ ๊ฐ์ ์ค๋ช ์ ํ๊ณ ์๋ค.
ํ์ง๋ง ์ฌ์ ํ ๋น์ฆ๋์ค ๋ก์ง์๋ง ์ง์คํ๋ ๊ฒ์ด ์๋ DB์ ๊ทผ๊ณผ ๊ฐ์ ๋ค๋ฅธ ๊ด์ฌ์ฌ์ ์ ๋ฌด๋ฅผ ์ํํด์ผ ํ๋ค.
โค๏ธ ์ ์ธ์ ํธ๋์ญ์ (@Transactional)
๊ฐ๋
Transaction ๊ด๋ฆฌ๋ฅผ ๋ณ๋์ ์ด๋ ธํ ์ด์ ์ผ๋ก ๋ถ๋ฆฌํ์ฌ AOP๋ก ํก๋จ ๊ด์ฌ์ฌ ์ฒ๋ฆฌ๋ฅผ ์งํํ๋ ๊ฒ์ด๋ค.
์ด๋ฅผ ํตํด ํ๋ก๊ทธ๋๋ฐ ๊ณผ์ ์์ ํธ๋์ญ์ ์ผ๋ก ์ธํ ์ฝ๋ ์ค๋ณต ๋ฌธ์ , ์์ค์ฝ๋ ์ ์ง ๋ณด์ ์ด๋ ค์์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
์ฌ์ฉ

์ฝ๋๋ฅผ ์์ฑํ๋ ๊ณผ์ ์์ @Transactional์ ์ ๋ ฅํ๋ ค๊ณ ํ๋ฉด ๋งค๋ฒ ๋ ๊ฐ์ import๋ฅผ ์ ํํ ์ ์์์ ๋๊ผ์ ๊ฒ์ด๋ค.
๋ ๊ฐ๋ ๋ฌด์์ด ๋ค๋ฅด๊ณ ์ด๋ค ๊ฒ์ ์ ํํด์ผ ํ ๊น?
๐ Spring Transaction vs Jakarta Transaction ๋น๊ต
| ๊ตฌ๋ถ | Spring Framework Transaction | Jakarta Transcation |
| ์ด๋ ธํ ์ด์ ํจํค์ง | org.springframework.transaction.annotation.Transactional | jakarta.transaction.Transactional |
| ์์ | Spring Framework | Jakarta EE (ํ์ค) |
| ๊ธฐ๋ฐ ๊ธฐ์ | Spring ์์ฒด ์ถ์ํ + AOP | JTA (Java Transaction API) |
| ํธ๋์ญ์ ๋งค๋์ | PlatformTransactionManager | JTA Transaction Manager |
| ๊ธฐ๋ณธ ๋กค๋ฐฑ ์ ์ฑ | RuntimeException, Error ๋กค๋ฐฑ | RuntimeException ๋กค๋ฐฑ (๊ตฌํ์ฒด ์์กด) |
| Checked Exception ๋กค๋ฐฑ | ๊ธฐ๋ณธ โ (์ต์ ์ผ๋ก ๊ฐ๋ฅ) | ๊ธฐ๋ณธ โ (rollbackOn์ผ๋ก ์ง์ ) |
| rollback ์ปค์คํฐ๋ง์ด์ง | rollbackFor, noRollbackFor | rollbackOn, dontRollbackOn |
| ์ ํ ์ต์ (Propagation) | REQUIRED, REQUIRES_NEW, NESTED ๋ฑ ๋งค์ฐ ๋ค์ | REQUIRED, REQUIRES_NEW ๋ฑ ์ผ๋ถ๋ง |
| ๊ฒฉ๋ฆฌ ์์ค(Isolation) | ์ง์ ์ค์ ๊ฐ๋ฅ | ์ง์ ์ค์ ๋ถ๊ฐ |
| timeout ์ค์ | ๊ฐ๋ฅ | ์ ํ์ |
| readOnly ์ต์ | ์์ (์ต์ ํ ํํธ) | ์์ |
| AOP ๊ธฐ๋ฐ ๋์ | O (ํ๋ก์ ๊ธฐ๋ฐ) | ์ปจํ ์ด๋ ๊ด๋ฆฌ |
| ThreadLocal ์ฌ์ฉ | ์ฌ์ฉ (๋๊ธฐ ํธ๋์ญ์ ) | ๊ตฌํ์ฒด ์์กด |
| Reactive ์ง์ | O (ReactiveTransactionManager) | X |
| ์ฃผ ์ฌ์ฉ ํ๊ฒฝ | Spring Boot / Spring ๊ธฐ๋ฐ ์ฑ | Jakarta EE ์๋ฒ (WildFly ๋ฑ) |
| ์ธ๋ฐํ ์ ์ด | ๋งค์ฐ ๊ฐํจ | ๋น๊ต์ ๋จ์ |
Spring or Spring boot๋ก ๊ฐ๋ฐ์ ์งํํ๋ ํ๊ฒฝ์ด๋ผ๋ฉด Spring Framework Transaction์ ์ ํํ์ฌ ์ฌ์ฉํ์.
org.springframework.transaction.annotation.Transactional
ํด๋์ค ์ฃผ์ ๋ฒ์ญ๋ฌธ
๊ฐ๋ณ ๋ฉ์๋ ๋๋ ํด๋์ค์ ํธ๋์ญ์
์์ฑ์ ์ค๋ช
ํฉ๋๋ค.
์ด ์ด๋
ธํ
์ด์
์ด ํด๋์ค ์์ค์ ์ ์ธ๋๋ฉด, ํด๋น ํด๋์ค์ ๊ทธ ํ์ ํด๋์ค์ ๋ชจ๋ ๋ฉ์๋์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ ์ฉ๋ฉ๋๋ค. ๋จ, ํด๋์ค ๊ณ์ธต ๊ตฌ์กฐ์์ ์์(์กฐ์) ํด๋์ค์๋ ์ ์ฉ๋์ง ์์ต๋๋ค. ์์๋ ๋ฉ์๋๊ฐ ํ์ ํด๋์ค ์์ค์ ์ด๋
ธํ
์ด์
์ ์ฐธ์ฌํ๋ ค๋ฉด ํด๋น ๋ฉ์๋๋ฅผ ํ์ ํด๋์ค์์ ๋ค์ ์ ์ธํด์ผ ํฉ๋๋ค. ๋ฉ์๋ ๊ฐ์์ฑ ์ ์ฝ์ ๋ํ ์์ธํ ๋ด์ฉ์ ๋ ํผ๋ฐ์ค ๋งค๋ด์ผ์ Transaction Management ์น์
์ ์ฐธ๊ณ ํ์ญ์์ค.
์ด ์ด๋
ธํ
์ด์
์ ์ผ๋ฐ์ ์ผ๋ก Spring์ org.springframework.transaction.interceptor.RuleBasedTransactionAttribute ํด๋์ค์ ์ง์ ์ ์ผ๋ก ๋น๊ตํ ์ ์์ต๋๋ค. ์ค์ ๋ก AnnotationTransactionAttributeSource๋ ์ด ์ด๋
ธํ
์ด์
์ ์์ฑ๋ค์ RuleBasedTransactionAttribute์ ์์ฑ์ผ๋ก ์ง์ ๋ณํํฉ๋๋ค. ๋ฐ๋ผ์ Spring์ ํธ๋์ญ์
์ง์ ์ฝ๋๋ ์ด๋
ธํ
์ด์
์์ฒด๋ฅผ ์ ํ์๊ฐ ์์ต๋๋ค.
์์ฑ ์๋ฏธ (Attribute Semantics)
์ด ์ด๋
ธํ
์ด์
์ ์ฌ์ฉ์ ์ ์ ๋กค๋ฐฑ ๊ท์น์ด ๊ตฌ์ฑ๋์ง ์์ ๊ฒฝ์ฐ, ํธ๋์ญ์
์ RuntimeException๊ณผ Error์ ๋ํด์๋ ๋กค๋ฐฑ๋์ง๋ง, ์ฒดํฌ ์์ธ(checked exception)์ ๋ํด์๋ ๋กค๋ฐฑ๋์ง ์์ต๋๋ค.
๋กค๋ฐฑ ๊ท์น์ ํน์ ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ํธ๋์ญ์
์ ๋กค๋ฐฑํ ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ฉฐ, ํ์
๋๋ ํจํด์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค. ์ฌ์ฉ์ ์ ์ ๊ท์น์ rollbackFor / noRollbackFor ๋ฐ rollbackForClassName / noRollbackForClassName์ ํตํด ์ค์ ํ ์ ์์ผ๋ฉฐ, ๊ฐ๊ฐ ํ์
๊ธฐ๋ฐ ๋๋ ํจํด ๊ธฐ๋ฐ์ผ๋ก ๊ท์น์ ์ง์ ํ ์ ์์ต๋๋ค.
์์ธ ํ์
์ ์ฌ์ฉํ์ฌ ๋กค๋ฐฑ ๊ท์น์ ์ ์ํ ๊ฒฝ์ฐ(์: rollbackFor), ํด๋น ํ์
์ ๋ฐ์ํ ์์ธ์ ํ์
๊ณผ ๋น๊ตํ์ฌ ๋งค์นญ๋ฉ๋๋ค. ๊ตฌ์ฒด์ ์ผ๋ก, ์ค์ ๋ ์์ธ ํ์
C๊ฐ ์์ ๋, ๋ฐ์ํ ์์ธ ํ์
T๊ฐ C์ ๋์ผํ๊ฑฐ๋ C์ ํ์ ํด๋์ค๋ผ๋ฉด ๋งค์นญ๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๋ค. ์ด๋ ํ์
์์ ์ฑ์ ์ ๊ณตํ๋ฉฐ, ํจํด ์ฌ์ฉ ์ ๋ฐ์ํ ์ ์๋ ์๋์น ์์ ๋งค์นญ์ ๋ฐฉ์งํฉ๋๋ค. ์๋ฅผ ๋ค์ด jakarta.servlet.ServletException.class๋ฅผ ์ง์ ํ๋ฉด, jakarta.servlet.ServletException ๋ฐ ๊ทธ ํ์ ํด๋์ค์ ๋ํด์๋ง ๋งค์นญ๋ฉ๋๋ค.
์์ธ ํจํด์ ์ฌ์ฉํ์ฌ ๋กค๋ฐฑ ๊ท์น์ ์ ์ํ ๊ฒฝ์ฐ, ํจํด์ ์์ธ ํ์
(๋ฐ๋์ Throwable์ ํ์ ํด๋์ค์ฌ์ผ ํจ)์ ์ ์ฒด ํด๋์ค ์ด๋ฆ(FQCN)์ด๊ฑฐ๋ ๊ทธ ์ผ๋ถ ๋ฌธ์์ด์ผ ์ ์์ต๋๋ค. ํ์ฌ๋ ์์ผ๋์นด๋ ์ง์์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด "jakarta.servlet.ServletException" ๋๋ "ServletException"์ด๋ผ๋ ๊ฐ์ jakarta.servlet.ServletException ๋ฐ ๊ทธ ํ์ ํด๋์ค์ ๋งค์นญ๋ฉ๋๋ค.
์ฃผ์: ํจํด์ ์ผ๋ง๋ ๊ตฌ์ฒด์ ์ผ๋ก ์ง์ ํ ์ง, ๊ทธ๋ฆฌ๊ณ ํจํค์ง ์ ๋ณด๋ฅผ ํฌํจํ ์ง(ํ์๋ ์๋)๋ฅผ ์ ์คํ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด "Exception"์ ๊ฑฐ์ ๋ชจ๋ ์์ธ์ ๋งค์นญ๋๋ฏ๋ก ๋ค๋ฅธ ๊ท์น์ ๊ฐ๋ฆด ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค. ๋ง์ฝ ๋ชจ๋ ์ฒดํฌ ์์ธ์ ๋ํ ๊ท์น์ ์ ์ํ๋ ค๋ ๋ชฉ์ ์ด๋ผ๋ฉด "java.lang.Exception"์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ์ ํฉ๋๋ค. "BaseBusinessException"์ฒ๋ผ ๊ณ ์ ํ ์ด๋ฆ์ ๊ฐ์ง ์์ธ๋ผ๋ฉด ์ ์ฒด ํด๋์ค ์ด๋ฆ์ ์ฌ์ฉํ ํ์๊ฐ ์์ ์ ์์ต๋๋ค.
๋ํ ํจํด ๊ธฐ๋ฐ์ผ๋ก ์ ์๋ ๋กค๋ฐฑ ๊ท์น์ ์ด๋ฆ์ด ์ ์ฌํ ์์ธ๋ ์ค์ฒฉ ํด๋์ค์ ๋ํด ์๋์น ์์ ๋งค์นญ์ ์ผ์ผํฌ ์ ์์ต๋๋ค. ์ด๋ ๋ฐ์ํ ์์ธ์ ์ด๋ฆ์ ์ค์ ๋ ์์ธ ํจํด ๋ฌธ์์ด์ด ํฌํจ๋์ด ์์ผ๋ฉด ๋งค์นญ๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋๊ธฐ ๋๋ฌธ์
๋๋ค. ์๋ฅผ ๋ค์ด "com.example.CustomException"์ด๋ผ๋ ๊ท์น์ด ์ค์ ๋ ๊ฒฝ์ฐ, ๋ค์๊ณผ ๊ฐ์ ์์ธ์๋ ๋งค์นญ๋ฉ๋๋ค:
com.example.CustomExceptionV2 (๊ฐ์ ํจํค์ง์ ์์ผ๋ ์ด๋ฆ์ ์ ๋ฏธ์ฌ๊ฐ ์ถ๊ฐ๋ ๊ฒฝ์ฐ) com.example.CustomException$AnotherException (CustomException ๋ด๋ถ์ ์ ์ธ๋ ์ค์ฒฉ ํด๋์ค)
์ด ์ด๋
ธํ
์ด์
์ ๋ค๋ฅธ ์์ฑ ์๋ฏธ์ ๋ํ ๊ตฌ์ฒด์ ์ธ ์ ๋ณด๋ TransactionDefinition ๋ฐ org.springframework.transaction.interceptor.TransactionAttribute์ Javadoc์ ์ฐธ๊ณ ํ์ญ์์ค.
ํธ๋์ญ์
๊ด๋ฆฌ (Transaction Management)
์ด ์ด๋
ธํ
์ด์
์ ์ผ๋ฐ์ ์ผ๋ก org.springframework.transaction.PlatformTransactionManager์ ์ํด ๊ด๋ฆฌ๋๋ ์ค๋ ๋ ๋ฐ์ธ๋ฉ(thread-bound) ํธ๋์ญ์
๊ณผ ํจ๊ป ๋์ํ๋ฉฐ, ํ์ฌ ์คํ ์ค๋ ๋ ๋ด์ ๋ชจ๋ ๋ฐ์ดํฐ ์ ๊ทผ ์์
์ ํธ๋์ญ์
์ ๋
ธ์ถํฉ๋๋ค. ๋จ, ์ด ํธ๋์ญ์
์ ํด๋น ๋ฉ์๋ ๋ด๋ถ์์ ์๋กญ๊ฒ ์์๋ ์ค๋ ๋๋ก๋ ์ ํ๋์ง ์์ต๋๋ค.
๋๋ ์ด ์ด๋
ธํ
์ด์
์ org.springframework.transaction.ReactiveTransactionManager์ ์ํด ๊ด๋ฆฌ๋๋ ๋ฆฌ์กํฐ๋ธ ํธ๋์ญ์
์ ๊ตฌ๋ถํ๋ ๋ฐ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ThreadLocal ๋ณ์๊ฐ ์๋๋ผ Reactor Context๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ฐ๋ผ์ ๋ชจ๋ ์ฐธ์ฌ ๋ฐ์ดํฐ ์ ๊ทผ ์์
์ ๋์ผํ ๋ฆฌ์กํฐ๋ธ ํ์ดํ๋ผ์ธ ๋ด์์, ๋์ผํ Reactor Context ์์์ ์คํ๋์ด์ผ ํฉ๋๋ค.
์ฐธ๊ณ : ReactiveTransactionManager์ ํจ๊ป ๊ตฌ์ฑ๋ ๊ฒฝ์ฐ, ๋ชจ๋ ํธ๋์ญ์
์ด ์ ์ธ๋ ๋ฉ์๋๋ ๋ฆฌ์กํฐ๋ธ ํ์ดํ๋ผ์ธ์ ๋ฐํํด์ผ ํฉ๋๋ค. void ๋ฉ์๋๋ ์ผ๋ฐ ๋ฐํ ํ์
์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ์ผ๋ฐ์ ์ธ PlatformTransactionManager์ ์ฐ๊ฒฐ๋์ด์ผ ํ๋ฉฐ, ์๋ฅผ ๋ค์ด transactionManager()๋ฅผ ํตํด ์ค์ ํด์ผ ํฉ๋๋ค.
๋ฉ์๋
public @interface Transactional {
// ํธ๋์ญ์
๋งค๋์ ์ด๋ฆ ์ง์ (transactionManager์ ๋ณ์นญ)
// ์ฌ๋ฌ TransactionManager๊ฐ ์์ ๋ ํน์ ๋งค๋์ ๋ฅผ ์ ํํ๊ธฐ ์ํด ์ฌ์ฉ
String value() default "";
// ์ฌ์ฉํ PlatformTransactionManager Bean ์ด๋ฆ ์ง์
// ๋ฉํฐ ๋ฐ์ดํฐ์์ค ํ๊ฒฝ์์ ์ฌ์ฉ
String transactionManager() default "";
// ํธ๋์ญ์
์ ๋ผ๋ฒจ(ํ๊ทธ)์ ๋ถ์ฌ
// ๋ชจ๋ํฐ๋ง/์ถ์ ์ฉ ๋ฉํ๋ฐ์ดํฐ์ด๋ฉฐ ํธ๋์ญ์
๋์์๋ ์ํฅ ์์
String[] label() default {};
// ํธ๋์ญ์
์ ํ ์ต์
์ค์
// ๊ธฐ์กด ํธ๋์ญ์
์ด ์์ ๋ ์ด๋ป๊ฒ ๋์ํ ์ง ๊ฒฐ์ (๊ธฐ๋ณธ: REQUIRED)
Propagation propagation() default Propagation.REQUIRED;
// ํธ๋์ญ์
๊ฒฉ๋ฆฌ ์์ค ์ค์
// ๋์์ฑ ์ ์ด๋ฅผ ์ํ ์ค์ ์ด๋ฉฐ ๊ธฐ๋ณธ๊ฐ์ DB ๊ธฐ๋ณธ๊ฐ ์ฌ์ฉ
Isolation isolation() default Isolation.DEFAULT;
// ํธ๋์ญ์
ํ์์์(์ด ๋จ์)
// ์ง์ ์๊ฐ ์ด๊ณผ ์ ๋กค๋ฐฑ (๊ธฐ๋ณธ๊ฐ์ ํธ๋์ญ์
๋งค๋์ ๊ธฐ๋ณธ๊ฐ ์ฌ์ฉ)
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
// ํ์์์์ ๋ฌธ์์ด๋ก ์ง์
// SpEL ๋๋ ํ๋กํผํฐ ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅ
String timeoutString() default "";
// ์ฝ๊ธฐ ์ ์ฉ ํธ๋์ญ์
์ฌ๋ถ
// ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํ ํํธ (๊ฐ์ ์ ํ์ ์๋)
boolean readOnly() default false;
// ์ง์ ํ ์์ธ ํ์
๋ฐ์ ์ ๋กค๋ฐฑ
// ํด๋น ํ์
๋ฐ ํ์ ํด๋์ค๊น์ง ์ ์ฉ
Class<? extends Throwable>[] rollbackFor() default {};
// ์์ธ ํด๋์ค ์ด๋ฆ(๋ฌธ์์ด ํจํด) ๊ธฐ๋ฐ ๋กค๋ฐฑ ์ง์
// ์ด๋ฆ์ ํด๋น ๋ฌธ์์ด์ด ํฌํจ๋๋ฉด ๋งค์นญ๋จ (์์ผ๋์นด๋ ์์)
String[] rollbackForClassName() default {};
// ์ง์ ํ ์์ธ ํ์
๋ฐ์ ์ ๋กค๋ฐฑํ์ง ์์
// RuntimeException์ด๋ผ๋ ์ปค๋ฐํ๋๋ก ์ค์ ๊ฐ๋ฅ
Class<? extends Throwable>[] noRollbackFor() default {};
// ์์ธ ํด๋์ค ์ด๋ฆ(๋ฌธ์์ด ํจํด) ๊ธฐ๋ฐ ๋กค๋ฐฑ ์ ์ธ ์ง์
String[] noRollbackForClassName() default {};
}
ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค (Isolation Level)
๋์์ ์คํ๋๋ ํธ๋์ญ์ ๊ฐ์ ๋ฐ์ดํฐ ์ ๊ทผ ํ์ฉ ๋ฒ์๋ฅผ ๊ฒฐ์ ํ๋ ์ค์
ํธ๋์ญ์ ์ด์ ํ์
| Dirty Read | ์ปค๋ฐ๋์ง ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ |
| Non-repeatable Read | ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ ๋ฒ ์กฐํํ๋๋ฐ ๊ฐ์ด ๋ฌ๋ผ์ง |
| Phantom Read | ๊ฐ์ ์กฐ๊ฑด์ผ๋ก ์กฐํํ๋๋ฐ ํ ๊ฐ์๊ฐ ๋ฌ๋ผ์ง |
1. DEFAULT
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ค์ ๋ ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ ์์ค์ ๋ฐ๋ฆ
- Spring์ ๊ด์ฌํ์ง ์์
- ๋ณดํต DB ๊ธฐ๋ณธ๊ฐ ์ฌ์ฉ
์ฐธ๊ณ :
- MySQL(InnoDB) ๊ธฐ๋ณธ: REPEATABLE READ
- Oracle ๊ธฐ๋ณธ: READ COMMITTED
2. READ_UNCOMMITTED
- ์ปค๋ฐ๋์ง ์์ ๋ฐ์ดํฐ ์กฐํ ๊ฐ๋ฅ
- Dirty Read ํ์ฉ
- ๊ฐ์ฅ ๋ฎ์ ๊ฒฉ๋ฆฌ ์์ค
- ์ ํฉ์ฑ ๋ฎ์, ๋์์ฑ ๋์
- ๋๋ถ๋ถ์ ์์ฉ DB์์๋ ์ฌ์ค์ READ_COMMITTED์ฒ๋ผ ๋์
3. READ_COMMITTED
- ์ปค๋ฐ๋ ๋ฐ์ดํฐ๋ง ์กฐํ ๊ฐ๋ฅ
- Dirty Read ๋ฐฉ์ง
- Non-repeatable Read, Phantom Read๋ ๋ฐ์ ๊ฐ๋ฅ
- ์ค๋ฌด์์ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ
4. REPEATABLE_READ
- ๋์ผ ํธ๋์ญ์ ๋ด์์ ๊ฐ์ ๋ฐ์ดํฐ ์กฐํ ์ ํญ์ ๋์ผ ๊ฐ ๋ณด์ฅ
- Dirty Read, Non-repeatable Read ๋ฐฉ์ง
- Phantom Read๋ DB ๊ตฌํ์ ๋ฐ๋ผ ๋ฐ์ ๊ฐ๋ฅ
- MySQL ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ ์์ค
5. SERIALIZABLE
- ๊ฐ์ฅ ๋์ ๊ฒฉ๋ฆฌ ์์ค
- ๋ชจ๋ ํธ๋์ญ์ ์ ์์ฐจ ์คํ์ฒ๋ผ ๋ณด์ฅ
- Dirty / Non-repeatable / Phantom Read ๋ชจ๋ ๋ฐฉ์ง
- ๋์์ฑ ๋งค์ฐ ๋ฎ์
- ์ฑ๋ฅ ์ ํ ๊ฐ๋ฅ์ฑ ํผ
- ๊ธ์ต/์ ์ฐ ๋ฑ ๊ฐํ ์ ํฉ์ฑ์ด ํ์ํ ๊ฒฝ์ฐ ์ฌ์ฉ
Spring์์์ ํน์ง
- isolation ์ต์ ์ "์๋ก์ด ํธ๋์ญ์ ์์ฑ ์์๋ง" ์ ์ฉ
- ๊ธฐ์กด ํธ๋์ญ์ ์ ์ฐธ์ฌํ๋ ๊ฒฝ์ฐ ๋ฌด์๋จ
- DB๊ฐ ์ง์ํ์ง ์๋ ๊ฒฉ๋ฆฌ ์์ค์ด๋ฉด ์์ธ ๋ฐ์ ๊ฐ๋ฅ
ํธ๋์ญ์ ์ ํ ์ต์ (Propagation)
๊ธฐ์กด ํธ๋์ญ์ ์กด์ฌ ์ฌ๋ถ์ ๋ฐ๋ผ ํ์ฌ ๋ฉ์๋๊ฐ ์ด๋ป๊ฒ ๋์ํ ์ง ๊ฒฐ์
1. REQUIRED (๊ธฐ๋ณธ๊ฐ)
- ๊ธฐ์กด ํธ๋์ญ์ ์ด ์์ผ๋ฉด ์ฐธ์ฌ
- ์์ผ๋ฉด ์๋ก ์์ฑ
- ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ์ต์
2. SUPPORTS
- ๊ธฐ์กด ํธ๋์ญ์ ์ด ์์ผ๋ฉด ์ฐธ์ฌ
- ์์ผ๋ฉด ํธ๋์ญ์ ์์ด ์คํ
- ์กฐํ์ฉ ๋ฉ์๋์ ์์ฃผ ์ฌ์ฉ
3. REQUIRES_NEW
- ํญ์ ์๋ก์ด ํธ๋์ญ์ ์์ฑ
- ๊ธฐ์กด ํธ๋์ญ์ ์ ์ ์ ์ค๋จ(Suspend)
- ๋ ๋ฆฝ์ ์ธ ์ปค๋ฐ/๋กค๋ฐฑ ํ์ํ ๋ ์ฌ์ฉ
- ์: ๋ก๊ทธ ์ ์ฅ, ๊ฐ์ฌ ๊ธฐ๋ก
4. MANDATORY
- ๊ธฐ์กด ํธ๋์ญ์ ์ด ๋ฐ๋์ ์์ด์ผ ํจ
- ์์ผ๋ฉด ์์ธ ๋ฐ์
- ๋จ๋ ์คํ์ด ํ์ฉ๋์ง ์๋ ๊ฒฝ์ฐ ์ฌ์ฉ
5. NOT_SUPPORTED
- ํธ๋์ญ์ ์์ด ์คํ
- ๊ธฐ์กด ํธ๋์ญ์ ์์ผ๋ฉด ์ค๋จ
- ๋ฝ์ ํผํ๊ณ ์ถ์ ๋๋ ์กฐํ ๋ฑ์ ์ฌ์ฉ
6. NEVER
- ํธ๋์ญ์ ์ด ์กด์ฌํ๋ฉด ์์ธ ๋ฐ์
- ์์ ๋นํธ๋์ญ์ ํ๊ฒฝ ๊ฐ์
7. NESTED
- ๊ธฐ์กด ํธ๋์ญ์ ๋ด๋ถ์ ์ค์ฒฉ ํธ๋์ญ์ ์์ฑ
- Savepoint ๊ธฐ๋ฐ ๋์
- ๋ถ๋ชจ ๋กค๋ฐฑ ์ ์์๋ ๋กค๋ฐฑ
- ์์ ๋กค๋ฐฑ์ ๋ถ๋ชจ์ ์ํฅ ์์
- DataSourceTransactionManager์์๋ง ์ง์
- JPA๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ์ง ์์
์ถ์ฒ
https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html
https://velog.io/@betterfuture4/Spring-Transactional-%EC%B4%9D%EC%A0%95%EB%A6%AC
https://adjh54.tistory.com/378
'Spring > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Spring] ํํฐ์ ์ธํฐ์ ํฐ๋ฅผ ํ์ฉํ ๋ก๊ทธ์ธ ๊ตฌํ (0) | 2024.09.02 |
|---|