[Spring] @Transactional์ด ๋์ํ์ง ์๋ ๊ฒฝ์ฐ
ํ๊ทธ: Spring, TIL, ํธ๋์ญ์
์นดํ ๊ณ ๋ฆฌ: Spring
@Transactional์ ๋ถ์๋๋ฐ๋ ํธ๋์ญ์ ์ด ์ ์ฉ๋์ง ์๋ ๊ฒฝ์ฐ๋ค์ ์ ๋ฆฌํ ๊ธ์ด๋ค.
๋ค์ด๊ฐ๋ฉฐ
์์ฆ ํ๋ก์ ํธ๋ฅผ ํ๋ค๊ฐ @Transactional์ ๋ถ์๋๋ฐ๋ ๋กค๋ฐฑ์ด ๋์ง ์๋ ์ํฉ์ ๊ฒช์๋ค. ๋ถ๋ช ํ ํธ๋์ญ์ ์ด๋ ธํ ์ด์ ์ ๋ถ์๋๋ฐ ์ ์ ๋๋์ง ํ์ฐธ ํค๋งธ๋ค. ๊ทธ๋์ ํธ๋์ญ์ ์ด ์ ์ฉ๋์ง ์๋ ์ผ์ด์ค๋ฅผ ์ ๋ฆฌํด๋ดค๋ค.
๊ฐ์ ํด๋์ค ๋ด๋ถ ํธ์ถ(self-invocation)
๊ฐ์ฅ ํํ ๊ฑด ๊ฐ์ ํด๋์ค ์์์ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋๋ค. ์คํ๋ง์ ํ๋ก์๋ก ํธ๋์ญ์ ์ ์ฒ๋ฆฌํ๋๋ฐ, ๋ด๋ถ ํธ์ถ(self-invocation)์ ํ๋ก์๋ฅผ ๊ฑฐ์น์ง ์๊ธฐ ๋๋ฌธ์ ํธ๋์ญ์ ์ด ์ ์ฉ๋์ง ์๋๋ค.
์๋ฅผ ๋ค๋ฉด ์ด๋ฐ ์ฝ๋๋ค.
1
2
3
4
5
6
7
8
9
10
public class OrderService {
public void outer() {
this.inner(); // ์ด๋ ๊ฒ ๋ถ๋ฅด๋ฉด ํธ๋์ญ์
์๋จน์
}
@Transactional
public void inner() {
// ...
}
}
outer์์ inner๋ฅผ ํธ์ถํ๋ฉด this๋ก ํธ์ถํ๋ ๊ผด์ด๋ผ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๊ฑฐ์น์ง ์๋๋ค. ๊ฒฐ๊ตญ ํธ๋์ญ์ ์ด ์์๋์ง ์๋๋ค.
private ๋ฉ์๋์ @Transactional
๋ ํ๋๋ private ๋ฉ์๋์ @Transactional์ ๋ถ์ด๋ ๊ฒฝ์ฐ์ธ๋ฐ, ์ด๊ฒ๋ ๋์ํ์ง ์๋๋ค. ํ๋ก์ ๊ธฐ๋ฐ @Transactional์ ๊ธฐ๋ณธ์ ์ผ๋ก public ๋ฉ์๋์๋ง ์ ์ฉ๋๊ธฐ ๋๋ฌธ์ด๋ค. ์ฌ๊ธฐ์ ๋ํด CGLIB ์๋ธํด๋์ค ํ๋ก์๋ private(๊ทธ๋ฆฌ๊ณ final, static) ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ ์ ์์ด ๊ฐ๋ก์ฑ์ง๋ ๋ชปํ๋ค. private ๋ฉ์๋๊ฐ ์ ๋๋ ๊ฑด ์ด ๋ ์ ์ฝ์ด ํจ๊ป ์์ฉํ ๊ฒฐ๊ณผ๋ค.
์์ธ ๋ฐ์ ์ ๋กค๋ฐฑ ๋์
@Transactional์ด ๊ธฐ๋ณธ์ ์ผ๋ก ๋กค๋ฐฑํ๋ ๋์์ RuntimeException๊ณผ Error๋ฟ์ด๋ค. IOException, SQLException ๊ฐ์ checked ์์ธ๋ ๋ฉ์๋ ๋ฐ์ผ๋ก ๋์ ธ์ ธ๋ ๊ธฐ๋ณธ ์ค์ ์์๋ ๋กค๋ฐฑ๋์ง ์๊ณ ๊ทธ๋๋ก ์ปค๋ฐ๋๋ค. checked ์์ธ์์๋ ๋กค๋ฐฑํ๋ ค๋ฉด @Transactional(rollbackFor = Exception.class)์ฒ๋ผ ๋กค๋ฐฑ ๋์์ ๋ช
์ํด์ผ ํ๋ค.
๋ ํ ๊ฐ์ง, ํธ๋์ญ์ ๋ฉ์๋ ์์์ ์์ธ๋ฅผ try-catch๋ก ์ก๊ณ ๋ค์ ๋์ง์ง ์์ผ๋ฉด ๋กค๋ฐฑ ํธ๋ฆฌ๊ฑฐ ์์ฒด๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
- self injection์ ํ๋ค.
- ์์ ํด๋์ค๋ฅผ ๋ถ๋ฆฌํด์ ์ธ๋ถ ๋น์ ์ฃผ์ ๋ฐ์ ํธ์ถํ๋ค.
- AOP ํ๋ก์๋ฅผ ์ง์ ๊บผ๋ด ์ฐ๋ ๋ฐฉ๋ฒ๋ ์์ง๋ง ๊ถ์ฅ๋์ง๋ ์๋๋ค.
์ ๋ฆฌ
์ ๋ฆฌํ๋ฉด, ํธ๋์ญ์ ์ ํ๋ก์ ๊ธฐ๋ฐ์ด๋ผ ํ๋ก์๋ฅผ ๊ฑฐ์น์ง ์๋ ํธ์ถ์์๋ ๋์ํ์ง ์๋๋ค. ์ด ์ ๋ง ๊ธฐ์ตํ๋ฉด ๋๋ค.
๋๊ธ๋จ๊ธฐ๊ธฐ