SRPING

JPA ๊ฐ์ฒด์˜ ์ƒํƒœ / @Transactional

imheee 2023. 1. 30. 03:25

1. JPA ๊ฐ์ฒด์˜ ์ƒํƒœ

1) Transient 

๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ฐ’์„ ์ฃผ์–ด๋„ JPA๋‚˜ hibernate๊ฐ€ ๊ทธ ๊ฐ์ฒด์— ๊ด€ํ•ด ์•„๋ฌด๊ฒƒ๋„ ๋ชจ๋ฅด๋Š” ์ƒํƒœ. ์ฆ‰, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋งคํ•‘๋œ ๊ฒƒ์ด ์•„๋ฌด๊ฒƒ๋„ ์—†๋‹ค.

2) Persistent

์ €์žฅ์„ ํ•˜๊ณ ๋‚˜์„œ, JPA๊ฐ€ ์•„๋Š” ์ƒํƒœ(๊ด€๋ฆฌํ•˜๋Š” ์ƒํƒœ)๊ฐ€ ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ .save()๋ฅผ ํ–ˆ๋‹ค๊ณ  ํ•ด์„œ, ์ด ์ˆœ๊ฐ„ ๋ฐ”๋กœ DB์— ์ด ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. JPA๊ฐ€ persistent ์ƒํƒœ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค๊ฐ€, ํ›„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค.(1์ฐจ ์บ์‹œ, Dirty Checking(๋ณ€๊ฒฝ์‚ฌํ•ญ ๊ฐ์ง€), Write Behind(์ตœ๋Œ€ํ•œ ๋Šฆ๊ฒŒ, ํ•„์š”ํ•œ ์‹œ์ ์— DB์— ์ ์šฉ) ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค)

3) Detached

JPA๊ฐ€ ๋”์ด์ƒ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š” ์ƒํƒœ. JPA๊ฐ€ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ๋“ค์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ๋‹ค์‹œ persistent ์ƒํƒœ๋กœ ๋Œ์•„๊ฐ€์•ผํ•œ๋‹ค.

4) Removed

JPA๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์ƒํƒœ์ด๊ธด ํ•˜์ง€๋งŒ, ์‹ค์ œ commit์ด ์ผ์–ด๋‚  ๋•Œ, ์‚ญ์ œ๊ฐ€ ์ผ์–ด๋‚œ๋‹ค.

 

2. @Transactional 

ํ† ํฐ๊ฐ’์ด DB ์— ์ €์žฅ๋˜์ง€ ์•Š์•„์„œ ํ™•์ธํ•ด๋ณด๋‹ˆ, ๊ณ„์ • ์ €์žฅ ํ›„, ์ด๋ฉ”์ผ ํ† ํฐ์„ ์ƒ์„ฑ.

Detached ์ƒํƒœ์˜ ๊ฐ์ฒด์˜€๋˜ ๊ฒƒ์ด๋‹ค.

 

[AS-IS]

private Account saveNewAccount(@Valid SignUpForm signUpForm) {
    Account account = Account.builder()
            ....
            .build();
    return accountRepository.save(account);
}

public void processNewAccount(SignUpForm signUpForm) {
    Account newAccount = saveNewAccount(signUpForm);
    newAccount.generateEmailToken();
    sendSignupConfirmEmail(newAccount);
}

accountRepository.save(account) ๋ฉ”์†Œ๋“œ ์•ˆ์—์„œ๋Š” transaction ์ฒ˜๋ฆฌ๊ฐ€ ๋œ๋‹ค. ์ด์— ํ•ด๋‹นํ•˜๋Š” Entity๊ฐ€ JPA life cycle ์ค‘ Persistent ์ƒํƒœ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๋ฉ”์ผ ์ธ์ฆ์„ ์œ„ํ•ด ์„ ์–ธ๋œ newAccount ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ, Detached ์ƒํƒœ์ด๋‹ค. ์ด๋ฏธ transcation ๋ฒ”์œ„ ๋ฐ–์ด๊ธฐ ๋•Œ๋ฌธ์— Entity๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค๊ณ  ํ•ด์„œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ €์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค.

 

[TO-BE]

private Account saveNewAccount(@Valid SignUpForm signUpForm) {
    Account account = Account.builder()
            ....
            .build();
    return accountRepository.save(account);
}

@Transactional
public void processNewAccount(SignUpForm signUpForm) {
    Account newAccount = saveNewAccount(signUpForm);
    newAccount.generateEmailToken();
    sendSignupConfirmEmail(newAccount);
}

์ด ๋•Œ @Transactional ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ processNewAccount์˜ ๊ฐ์ฒด๋„ transaction ๋ฒ”์œ„๋‚ด์— ๋“ค๋„๋ก ํ•œ๋‹ค. ๊ทธ๋Ÿผ Detached ์ƒํƒœ๊ฐ€ ์•„๋‹Œ Persistent ์ƒํƒœ๊ฐ€ ์œ ์ง€๊ฐ€ ๋œ๋‹ค. Persisent ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ, transaction์ด ์ข…๋ฃŒ๋  ๋•Œ DB์— sync ๋œ๋‹ค. ๋”ฐ๋ผ์„œ, ์ƒ์„ฑ๋œ ํ† ํฐ ๊ฐ’๋„ ์ €์žฅ๋œ๋‹ค.

 

 

*์ฐธ๊ณ ์ž๋ฃŒ

๋ฐฑ๊ธฐ์„  ์ธํ”„๋Ÿฐ ๊ฐ•์˜