ํธ๋์ญ์ ?
: DBMS ๋๋ ์ ์ฌํ ์์คํ ์์ ์ํธ์์ฉ์ ๋จ์ (ํ๋์ ๋ ผ๋ฆฌ์ ์ธ ์์ ๋จ์)
ํน์ง
- Atomic
- Consistent
- Isolation
- Durability
์ฐ์ฐ
- ๋กค๋ฐฑ
- ์ปค๋ฐ
⇒ ๊ทธ๋ผ Spring์์๋ ์ด ํธ๋์ญ์ ์ฒ๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ํ๋๊ฐ?
@Transactional
์คํ๋ง์์๋ ํธ๋์ญ์ ์ฒ๋ฆฌ๋ฅผ ์ํด ์ ์ธ์ ํธ๋์ญ์ ์ ์ฌ์ฉํ๋ค.
@Transactional ๊ณผ ๊ฐ์ด ์ด๋ ธํ ์ด์ ๋ฐฉ์์ผ๋ก ์ด๋ฅผ ์ง์ํ๋ค.
Spring์์ ๋ฐ์ดํฐ ์์ ์ ์คํ๋จ์๋ฅผ ๋ช ์ํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค๊ณ ๋ณผ ์ ์๋ค.
ํด๋์ค / ๋ฉ์๋ ์์ @Transactional ์ ๋ถ์ด๋ฉด AOP(๊ด์ ์งํฅํ๋ก๊ทธ๋๋ฐ)๋ฅผ ํตํด ํ๊ฒ์ด ์์ํ๊ณ ์๋ ์ธํฐํ์ด์ค ๋๋ ํ๊ฒ์ ์์ํ ํ๋ก์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ค. ์ด๋ ํ๋ก์ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ํ๊ฒ ๋ฉ์๋ ์ ํ๋ก ํธ๋์ญ์ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ค.
ํ์ํ ์ด์
// ๊ฐ๋ ์ฑ ๋๊ณ
- ๊ฐ๋
์ฑ์ด ๋์ ์ด์
๊ทผ๋ฐ ์ด๋ฅผ @Transactional ์ ์ด์ฉํ๋ฉด ๋์ด์ ๊ฐ๋ ์ฑ์ด ๋๋ค. ๋ผ๊ณ ๋ณผ ์ ์์?public static void main(String[] args) { //์ํฐํฐ ๋งค๋์ ํฉํ ๋ฆฌ ์์ฑ EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook"); EntityManager em = emf.createEntityManager(); //์ํฐํฐ ๋งค๋์ ์์ฑ EntityTransaction tx = em.getTransaction(); //ํธ๋์ญ์ ๊ธฐ๋ฅ ํ๋ try { tx.begin(); //ํธ๋์ญ์ ์์ logic(em); //๋น์ฆ๋์ค ๋ก์ง tx.commit();//ํธ๋์ญ์ ์ปค๋ฐ } catch (Exception e) { tx.rollback(); //ํธ๋์ญ์ ๋กค๋ฐฑ } finally { em.close(); //์ํฐํฐ ๋งค๋์ ์ข ๋ฃ } emf.close(); //์ํฐํฐ ๋งค๋์ ํฉํ ๋ฆฌ ์ข ๋ฃ }
- ๊ณผ๊ฑฐ์๋ ๋กค๋ฐฑ์ ํ๊ธฐ ์ํด try-catch์ ๊ฐ์ ๋กค๋ฐฑ์ ์ด์ฉํด์ผ ํ์
์ ์ง๋ณด์ ์ข๋ค
์๋
ํธ๋์ญ์ ์ ๊ฒฝ์ฐ, ํธ๋์ญ์ ์ ์์๊ณผ ์ฐ์ฐ ์ข ๋ฃ ์์ ์ปค๋ฐ ๊ณผ์ ์ด ํ์ํ๋ฏ๋ก, ํ๋ก์(ํธ๋์ญ์ AOP)๋ฅผ ์์ฑํด ํด๋น ๋ฉ์๋์ ์๋ค์ ํธ๋์ญ์ ์ ์์๊ณผ ๋์ ์ถ๊ฐํ๋ ๊ฒ์ด๋ค.
๋ํ, ์คํ๋ง ์ปจํ ์ด๋๋ ํธ๋์ญ์ ๋ฒ์์ ์์์ฑ ์ปจํ ์คํธ ์ ๋ต์ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๋ค.
์๋น์ค ํด๋์ค์์ @Transactional์ ์ฌ์ฉํ ๊ฒฝ์ฐ, ํด๋น ์ฝ๋ ๋ด์ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ ์์์ฑ ์ปจํ ์คํธ๊ฐ ์๊ธด๋ค๋ ๋ป์ด๋ค. ์์์ฑ ์ปจํ ์คํธ๋ ํธ๋์ญ์ AOP๊ฐ ํธ๋์ญ์ ์ ์์ํ ๋ ์๊ฒจ๋๊ณ , ๋ฉ์๋๊ฐ ์ข ๋ฃ๋์ด ํธ๋์ญ์ AOP๊ฐ ํธ๋์ญ์ ์ ์ปค๋ฐํ ๊ฒฝ์ฐ ์์์ฑ ์ปจํ ์คํธ๊ฐ flush๋๋ฉด์ ํด๋น ๋ด์ฉ์ด ๋ฐ์๋๋ค.
์ดํ ์์์ฑ ์ปจํ ์คํธ ์ญ์ ์ข ๋ฃ๋๋ ๊ฒ์ด๋ค.
// ์ด ๋ง์ด 1์ฐจ ์บ์๊ฐ ์ฌ๋ผ์ง๋ค๋ ๊ฑฐ๋
๋์ ์๋ฆฌ
AOP (๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ)
spring์ @Transactional์ ๋ณด๊ณ AOP ๊ธฐ๋ฐ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
์คํ๋ง AOP๋ ํ๋ก์ ํจํด์ ๊ธฐ๋ฐ์ผ๋ก ๋์. ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ๋, ์คํ๋ง ์ปจํ ์ด๋๋ ๋์ ๊ฐ์ฒด ๋์ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ ๊ณต.
⇒ ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ๋ชจ๋์ฑ์ด ํ์ฅ
- AOP ์ฃผ์ ๊ฐ๋
- Aspect: Advice + PointCut๋ก AOP์ ๊ธฐ๋ณธ ๋ชจ๋
- Advice: Target์ ์ ๊ณตํ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ๋ด๊ณ ์๋ ๋ชจ๋
- Target: Advice์ด ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ ๊ณตํ ๋์ (Advice๊ฐ ์ ์ฉ๋ ๋น์ฆ๋์ค ๋ก์ง)
- JointPoint: Advice๊ฐ ์ ์ฉ๋ ์์น
- ๋ฉ์๋ ์ง์ ์ง์ , ์์ฑ์ ํธ์ถ ์์ , ํ๋์์ ๊ฐ์ ๊บผ๋ด์ฌ ๋ ๋ฑ ๋ค์ํ ์์ ์ ์ ์ฉ ๊ฐ๋ฅ
- PointCut: Target์ ์ง์ ํ๋ ์ ๊ท ํํ์advice: ๋ถ๊ฐ๊ธฐ๋ฅ ๋ก์ง๋ง ๋ด๋น
- pointcut: ๋์์ธ์ง ํ์ธํ๋ ํํฐ ์ญํ ๋ง ๋ด๋น
- ⇒ ์ญํ ๊ณผ ์ฑ ์์ ๋ช ํํ๊ฒ ๋ถ๋ฆฌํจ
Proxy
AOP๋ฅผ ๊ตฌํํ๋ ๊ธฐ์ ์ค ํ๋, ๋์ ๊ฐ์ฒด์ ๋ํ ์ ๊ทผ์ ์ ์ดํ๊ณ ์ถ๊ฐ ๊ธฐ๋ฅ์ ์ํํ๊ธฐ ์ํด ์ฌ์ฉ
ํ๋ก์๋ฅผ ํตํด ์ค์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ธ๊ณ ํด๋ผ์ด์ธํธ๊ฐ ์ด๊ฒ ์ง์ง์ธ์ง ๊ฐ์ง์ธ์ง ๋ชจ๋ฅด๊ฒํ๋ฉด์ ์ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ ์ ๊ณตํ ์ ์์
- [Proxy ๊ฐ์ฒด๊ฐ ๋ง๋ค์ด์ง๋ ๋ฐฉ๋ฒ]
- JDK Dynamic Proxy
public interface MyService { void doSomething(); }
⇒ @Tranactional์ด ์ ์ฉ๋๋ฉด spring์ MyServiceImpl์ผใ ข ํ๋ก์ ๊ฐ์ฒด ์์ฑ. doSomething์ ํธ์ถํ๋ฉด ํ๋ก์๊ฐ ๋จผ์ ์คํ๋๋ฉด์ ํธ๋์ญ์ ๊ด๋ฆฌ๋ฅผ ํจ@Service public class MyServiceImpl implements MyService { @Transactional public void doSomething() { System.out.println("์ค์ ๋ก์ง ์คํ"); } }
- ์ธํฐํ์ด์ค๋ฅผ ์์๋ฐ์ ํ๋ก์ ๊ฐ์ฒด ์์ฑ
- CGLIBํด๋์ค ์์ฒด๋ฅผ ์์ํ์ฌ ํ๋ก์ ์์ฑ
- : ์์ ํด๋์ค๋ฅผ ๋ง๋ค์ด ์๋ ํด๋์ค์ ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉ
- ํด๋์ค ๊ธฐ๋ฐ ํ๋ก์
- JDK Dynamic Proxy
- @Transactional ์ ์ฉ์์ : Bean ํ์ฒ๋ฆฌ ๊ณผ์ Spring ์ปจํ
์ด๋๋
BeanFactoryPostProcessor
์AnnotationTransactionAttributeSource
๋ฅผ ์ด์ฉํด@Transactional
์ ๊ฐ์งํ๊ณ , ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ์คํ๋ง ์ปจํ ์ด๋์ ๋ฑ๋กํ๋ค. - Spring Application์ด ์์ํ ๋, ์ปจํ ์ด๋๋ ๊ฐ Bean์ ์์ฑํ๊ณ BeanPostProcessor ๋จ๊ณ์์ @Transactional ๋ฑ AOP ๊ด๋ จ ์ด๋ ธํ ์ด์ ์ด ๋ถ์ Bean์ ์ค์บํจ
- Caller์์ AOP ํ๋ก์๋ฅผ ํ๋ค. ์ด๋ ํ๊ฒ์ ํธ์ถํ์ง๋ ์๊ณ , ํ๋ก์๋ฅผ ํธ์ถํ๋ค.
- Caller: ์ฑ ๋ด๋ถ/์ธ๋ถ์์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ์ฃผ์ฒด (@Autowired๋ก ์ฃผ์ ๋ฐ์ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋, ์ค์ ๋ก๋ ๊ทธ ๊ฐ์ฒด์ “ํ๋ก์”๊ฐ ํธ์ถ๋๋ค. )
- ๊ทธ AOP ํ๋ก์๋ Advisor๋ฅผ ํธ์ถํ๋ค.DB์ฐ๊ฒฐ์ก๊ณ ์ค์ ํธ๋์ญ์
์ด ์์๋๋ค.
- Transaction Advisor: @Transactional์ ํด์ํ๊ณ ์์/์ปค๋ฐ/๋กค๋ฐฑ์ ๊ด๋ฆฌํ๋ ๊ด๋ฆฌ์.
- Custom Advisor๊ฐ ์๋ค๋ฉด, ํธ๋์ญ์ Advisor ์คํ ์ ํ๋ก ๋์ํ๋ค.
- CustomAdvisor: ๋ณ๋๋ก ๋ง๋ AOP์ค์ ์ด ์๋ค๋ฉด, TransactionAdvisor ์๋ค๋ก ๋ผ์ด๋ค์ด ๋์ํ๋ ์ถ๊ฐ์ ์ธ ์ด๋๋ฐ์ด์
- → ์ด๋ @Transactional์ ์ธ๋ถ ์ค์ ์ด ๋ฐ์๋จ (propagation, isolation ๋ฑ)
- @Transactional์ด ์์ผ๋ฏ๋ก ์ด ๋ฉ์๋๋ ํธ๋์ญ์ ์ด ํ์ํ๋ค. ์์ํด๋ฌ๋ผ๊ณ ํ๋ค.
- ์ค์ ๋ฉ์๋ ์คํ (Targer Method)์ด๋ ๋น์ฆ๋์ค ๋ก์ง์ด ์ํ๋๊ณ , DB์ ๊ทผ (์ฟผ๋ฆฌ)๋ @Transactional ๊ฒฝ๊ณ ์์์ ์งํ๋จ
- ์์ธ ๋ฐ์ → ๋กค๋ฐฑ ๋ฐ์ ๊ฐ๋ฅ
- ์ค๋ฅ ์์ → ์ปค๋ฐ ๋จ๊ณ๋ก ๋์ด๊ฐ ์ ์์
- ๋ชจ๋ Advisor๋ค์ด ์คํ ์ ์ ํด์ผํ ์ผ์ ๋ง์น๋ฉด ์ค์ Target ๊ฐ์ฒด์ ๋ฉ์๋๊ฐ ์คํ๋จ
- ๋ฉ์๋ ์คํ ๊ฒฐ๊ณผ ๋ฐํ
- ๊ฐ advisor์ after ํํธ ์คํ ๊ฐ๋ฅ
- TransactionalAdvisor๋ ๋กค๋ฐฑ / ์ปค๋ฐํ ์ง ์ต์ข ํ๋จํ์ฌ ์งํ
- JPA ์ฌ์ฉ ์ flush() ์คํ ํ ์ค์ ์ปค๋ฐ ์ํ
- ์ปค๋ฐ ์๋ฃ๋๋ฉด ํธ๋์ญ์ ์ข ๋ฃ ํ Connection ๋ฐํ
- ๋กค๋ฐฑ ์์๋ ์์์ฑ ์ปจํ ์คํธ ์ด๊ธฐํ
- ๋ชจ๋ ์ฒ๋ฆฌ๊ฐ ๋๋๋ฉด ๊ฒฐ๊ณผ๊ฐ์ AOP Proxy๊ฐ caller์๊ฒ ๋ฐํํจ
- ๋ฉ์๋ ์คํ์ด ์๋ฃ๋๋ฉด, ๋ค์ CustomAdvisor→TransactionAdvisor ์์ผ๋ก ๋์์ด
์ฃผ์์
- ๋ด๋ถ ํธ์ถ์ ํ๋ฉด ํธ๋์ญ์
์ด ๊ฑธ๋ฆฌ์ง ์์
@Service public class dkdkdkdService { @Transactional public void methodA{ methodB; // ๋ด๋ถ ํธ์ถ -> ํธ๋์ญ์ X } @Transactional public void methodB{ // ํธ๋์ญ์ ๊ฑธ๋ฆฌ๊ณ ์ถ์์ง๋ง ์คํจ }
- ๋ฐ๋์ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๊ฑฐ์ณ์ผ ํธ๋์ญ์ AOP ์ ์ฉ
'๐ฑ Backend > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JUnit, Mockito] TestCode ์์ฑํ๊ธฐ (1) | 2025.06.08 |
---|---|
@RequiredArgsContructor, @AllArgsContructor, @NoArgsContructor (0) | 2025.06.06 |
Bean ์๋ช ์ฃผ๊ธฐ, ApplicationContext, ๋น ์ด๊ธฐํ ์์ (0) | 2025.05.21 |
Spring Boot Health Check์ ๋์ ์๋ฆฌ์ ๋ด๋ถ ๊ตฌ์กฐ ๋ถ์ (0) | 2025.05.20 |
์คํ๋ง ์ปจํ ์ด๋์ ์คํ๋ง ๋น (1) | 2025.04.15 |