Hello Kitty Eyes Shut
๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ’ป๊ณต๋ถ€ ๊ธฐ๋ก/๐Ÿ“Œ Backend

[Backend] @Transactional

๋ฐ˜์‘ํ˜•

 

 

 

 

 

 

๐Ÿ”Ž @Transactional ์ด๋ž€

Spring Framework์—์„œ @Transactional์€ ํŠธ๋žœ์žญ์…˜์„ ์„ ์–ธ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํ•ต์‹ฌ ์–ด๋…ธํ…Œ์ด์…˜์ด๋‹ค.

๊ฐœ๋ฐœ์ž๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋ฉ”์„œ๋“œ์— @Transactional์„ ๋ช…์‹œํ•จ์œผ๋กœ์จ,

ํ•ด๋‹น ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„์— ํŠธ๋žœ์žญ์…˜์˜ ์‹œ์ž‘๊ณผ ์ข…๋ฃŒ๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•œ๋‹ค.

 

์ด๋Š” PlatformTransactionalManager๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ,

๋‚ด๋ถ€์ ์œผ๋กœ๋Š” AOP (Aspect Oriented Programming)๋ฅผ ํ†ตํ•ด์„œ ๋™์ž‘ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

์ฆ‰, @Transactional์ด ๋ถ™์€ ๋งค์„œ๋“œ๋Š” Spring์ด ์ƒ์„ฑํ•œ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ํ˜ธ์ถœ๋˜๋ฉฐ,

ํ”„๋ก์‹œ ๋‚ด๋ถ€์—์„œ ํŠธ๋žœ์žญ์…˜์˜ ์‹œ์ž‘๊ณผ ์ข…๋ฃŒ๋ฅผ ๋‹ด๋‹นํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 


๐Ÿƒ๐Ÿป‍โ™‚๏ธ ํ”„๋ก์‹œ ๊ธฐ๋ฐ˜ ๋™์ž‘ ๊ตฌ์กฐ

์ข€ ๋” ํ’€์–ด์„œ ์„ค๋ช…ํ•˜์ž๋ฉด,

Spring์—์„œ๋Š” @Transactional์ด๋ผ๋Š” ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ํŠธ๋žœ์žญ์…˜์„ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ด์ค€๋‹ค.

์ด ์–ด๋…ธํ…Œ์ด์…˜์„ ํด๋ž˜์Šค ๋˜๋Š” ๋ฉ”์„œ๋“œ์— ๋ถ™์ด๊ธฐ๋งŒ ํ•˜๋ฉด,

Spring์ด ๋‚ด๋ถ€์ ์œผ๋กœ ํ•ด๋‹น ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•ด ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ๋กœ์ง์„ ์ž๋™์œผ๋กœ ์ ์šฉํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

๊ทธ๋ฆฌ๊ณ , ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์ด ๊ฐ€๋Šฅํ•œ ์ด์œ ๋Š” ๋ฐ”๋กœ ํ”„๋ก์‹œ (Proxy)๋ผ๋Š” ๊ธฐ์ˆ  ๋•๋ถ„์ด๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋  ๋•Œ, Spring์€ @Transactional์ด ๋ถ™์€ ํด๋ž˜์Šค๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ์‹ธ๋Š” ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

์ด ํ”„๋ก์‹œ๋Š” ์‹ค์ œ ์›๋ณธ ํด๋ž˜์Šค์˜ ๋™์ž‘์„ ๋Œ€์‹  ์ˆ˜ํ–‰ํ•˜๋Š” ๋Œ€๋ฆฌ ๊ฐ์ฒด์ด๋ฉฐ,

ํ•ต์‹ฌ์ ์ธ ์—ญํ• ์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ์‹คํ–‰ ์‹œ์ ์„ ๊ฐ€๋กœ์ฑ„์„œ, ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์ฆ‰, ์šฐ๋ฆฌ๊ฐ€ ์„œ๋น„์Šค๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด,

์‹ค์ œ๋กœ๋Š” ์›๋ณธ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ, Spring์ด ๋งŒ๋“  ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ ๋จผ์ € ์š”์ฒญ์„ ๋ฐ›๊ฒŒ ๋œ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ , ์ด ํ”„๋ก์‹œ๋Š” ์š”์ฒญ์„ ๋ฐ›์ž๋งˆ์ž ์•„๋ž˜์™€ ๊ฐ™์€ ์ˆœ์„œ๋กœ ๋™์ž‘ํ•œ๋‹ค.

 

  1. ํ˜„์žฌ ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ์— ํŠธ๋žœ์žญ์…˜์ด ํ•„์š”ํ•œ์ง€ ํ™•์ธํ•œ๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด, @Transactional์ด ๋ถ™์–ด์žˆ๊ณ , ํŠธ๋žœ์žญ์…˜์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด, ์ƒˆ ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค.
  2. ํŠธ๋žœ์žญ์…˜์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ํŒ๋‹จ๋˜๋ฉด, Spring์€ ๋‚ด๋ถ€์ ์œผ๋กœ PlatformTransactionManager๋ฅผ ํ†ตํ•ด ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•œ๋‹ค.
    ๊ตฌ์ฒด์ ์œผ๋กœ๋Š” JDBC ์ปค๋„ฅ์…˜์˜ ์ž๋™ ์ปค๋ฐ‹์„ ๋„๊ณ , ํŠธ๋žœ์žญ์…˜์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๋กœ ์ง„์ž…ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
    ์ด ์‹œ์ ๋ถ€ํ„ฐ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ๋ชจ๋“  ๋ณ€๊ฒฝ ์ž‘์—…์ด ํŠธ๋žœ์žญ์…˜์˜ ๊ด€๋ฆฌ ํ•˜์— ๋†“์ด๊ฒŒ ๋œ๋‹ค.
  3. ํŠธ๋žœ์žญ์…˜์ด ์‹œ์ž‘๋œ ์ƒํƒœ์—์„œ๋Š” ์ด์ œ ์‹ค์ œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์‹คํ–‰๋œ๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด, DB์— ๊ฐ’์„ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์ด ์ด๋ฃจ์–ด์ง€๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
  4. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์ •์ƒ์ ์œผ๋กœ ์™„๋ฃŒ๋˜๋ฉด, Spring์€ ํŠธ๋žœ์žญ์…˜์„ ์ปค๋ฐ‹ํ•˜์—ฌ ๋ชจ๋“  ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ DB์— ์ตœ์ข… ๋ฐ˜์˜ํ•œ๋‹ค.
    ๋ฐ˜๋Œ€๋กœ, ๋กœ์ง ์ค‘๊ฐ„์— ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด Spring์€ ํŠธ๋žœ์žญ์…˜์„ ๋กค๋ฐฑํ•ด์„œ ์ง€๊ธˆ๊นŒ์ง€ ์ˆ˜ํ–‰๋œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๋ชจ๋‘ ์ทจ์†Œํ•œ๋‹ค.

์ด์ฒ˜๋Ÿผ ๊ฐœ๋ฐœ์ž๋Š” @Transactional์„ ๋ฉ”์„œ๋“œ์— ์„ ์–ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด,

ํŠธ๋žœ์žญ์…˜์œผ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ์ข…๋ฃŒํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ „ํ˜€ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„,

Spring์ด ๋Ÿฐํƒ€์ž„์— ์ƒ์„ฑํ•œ ํ”„๋ก์‹œ๊ฐ€ ์œ„์™€ ๊ฐ™์€ ์ž‘์—…์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค.

 

์ด ๋•๋ถ„์— ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ž์ฒด๋Š” ํŠธ๋žœ์žญ์…˜ ์ œ์–ด ๋กœ์ง์œผ๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌ๋˜์–ด ๊น”๋”ํ•˜๊ณ  ์ง๊ด€์ ์ธ ์ฝ”๋“œ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค โœจ

 


โš ๏ธ ๊ณ ๋ คํ•ด์•ผ ํ•  ๊ฒƒ๋“ค

Spring์—์„œ @Transactional ์–ด๋…ธํ…Œ์ด์…˜์€ ๋งค์šฐ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์ด์ง€๋งŒ,

๋‚ด๋ถ€ ๋™์ž‘ ๋ฐฉ์‹์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜์ง€ ๋ชปํ•œ ์ฑ„ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋™์ž‘์ด๋‚˜ ๋ฒ„๊ทธ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

ํŠนํžˆ, ์‹ค๋ฌด ํ™˜๊ฒฝ์—์„œ๋Š” ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ์˜ ์ •ํ™•์„ฑ๊ณผ ์ผ๊ด€์„ฑ์ด ์‹œ์Šคํ…œ ์ „์ฒด์˜ ์•ˆ์ •์„ฑ๊ณผ ์ง๊ฒฐ๋˜๊ธฐ ๋•Œ๋ฌธ์—,

์•„๋ž˜์™€ ๊ฐ™์€ ํ•ญ๋ชฉ๋“ค์„ ๋ฐ˜๋“œ์‹œ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

 

1๏ธโƒฃ ํ”„๋ก์‹œ ์šฐํšŒ ํ˜ธ์ถœ ๋ฌธ์ œ

@Transactional์€ ํ”„๋ก์‹œ ๊ธฐ๋ฐ˜ AOP ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.
์ด ๋ง์€ ๊ณง, ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ๋กœ์ง์ด ์‹ค์ œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋ฉ”์„œ๋“œ์— ์ง์ ‘ ์กด์žฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ,
ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ํ”„๋ก์„ธ ๊ฐ์ฒด์—์„œ ํŠธ๋žœ์žญ์…˜์„ ๊ด€๋ฆฌํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

์ด ๊ตฌ์กฐ์—์„œ ํ•œ ๊ฐ€์ง€ ํ”ํžˆ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š”๋ฐ,
๋ฐ”๋กœ ๋™์ผ ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ์˜ ์ž๊ธฐ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ํด๋ž˜์Šค A์— methodA()์™€ methodB()๊ฐ€ ์žˆ๊ณ ,
methodA()์—๋Š” @Transactional์ด ๋ถ™์–ด ์žˆ์œผ๋ฉฐ,
methodB()๋Š” methodA()๋ฅผ ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.

์ด ๊ฒฝ์šฐ, methodB()๊ฐ€ this.methodA()์ฒ˜๋Ÿผ ์ž๊ธฐ ์ž์‹ ์„ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ methodA()๋ฅผ ์‹คํ–‰ํ•˜๋ฉด,
ํ•ด๋‹น ํ˜ธ์ถœ์€ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํŠธ๋žœ์žญ์…˜์ด ์ „ํ˜€ ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.

์ด๋Š” ์Šคํ”„๋ง AOP ๊ตฌ์กฐ์˜ ๊ทผ๋ณธ์ ์ธ ์ œ์•ฝ์œผ๋กœ,
ํŠธ๋žœ์žญ์…˜ ๋กœ์ง์€ ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์šฐํšŒ ํ˜ธ์ถœ๋  ๋•Œ์—๋งŒ ์ ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋”ฐ๋ผ์„œ ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”,
ํŠธ๋žœ์žญ์…˜ ๊ฒฝ๊ณ„๊ฐ€ ํ•„์š”ํ•œ ๋กœ์ง์„ ๋ณ„๋„์˜ ์„œ๋น„์Šค ํด๋ž˜์Šค๋กœ ๋ถ„๋ฆฌํ•˜๊ฑฐ๋‚˜,
AopContext.currentProxy()๋ฅผ ํ™œ์šฉํ•ด์„œ ํ˜„์žฌ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ๊ฐ„์ ‘ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

๋‹ค๋งŒ, ํ›„์ž๋Š” ์‚ฌ์šฉ์ด ๊นŒ๋‹ค๋กญ๊ณ  ์ฝ”๋“œ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๋ฏ€๋กœ, ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ํด๋ž˜์Šค ๋ถ„๋ฆฌ๋ฅผ ๊ถŒ์žฅํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

 


2๏ธโƒฃ ์ฒดํฌ ์˜ˆ์™ธ ๋ก๋ฐฑ ์—ฌ๋ถ€

Spring์˜ ๊ธฐ๋ณธ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ์ •์ฑ…์—์„œ๋Š”,

RuntimeException๊ณผ Error ํƒ€์ž…์˜ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ๋งŒ ํŠธ๋žœ์žญ์…˜์„ ๋กค๋ฐฑํ•˜๊ณ ,

Exception ์ฒ˜๋Ÿผ ์ฒดํฌ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ํŠธ๋žœ์žญ์…˜์„ ์ปค๋ฐ‹ํ•˜๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ ๋™์ž‘์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

์ด๋Ÿฌํ•œ ์„ค๊ณ„๋Š” ์ž๋ฐ”์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ทœ์น™์„ ๋”ฐ๋ฅด๊ธฐ ์œ„ํ•œ ๊ฒƒ์œผ๋กœ,

์ฒดํฌ ์˜ˆ์™ธ๋Š” ์›์น™์ ์œผ๋กœ ๋ณต๊ตฌ ๊ฐ€๋Šฅํ•œ ์˜ˆ์™ธ๋กœ ๊ฐ„์ฃผ๋˜๊ธฐ ๋•Œ๋ฌธ์—

Spring์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์˜๋„์ ์œผ๋กœ ์ปค๋ฐ‹์„ ์›ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํ•ด์„ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์‹ค๋ฌด์—์„œ๋Š” ์ฒดํฌ ์˜ˆ์™ธ ์—ญ์‹œ ๋กค๋ฐฑ๋˜์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

 

๋”ฐ๋ผ์„œ,

์˜ˆ๋ฅผ ๋“ค์–ด ํŒŒ์ผ ์—…๋กœ๋“œ๋‚˜ ์™ธ๋ถ€ API ํ†ต์‹  ๋“ฑ์—์„œ IOException๊ณผ ๊ฐ™์€ ์ฒดํฌ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ์—๋„ DB ์ž‘์—…์„ ๋กค๋ฐฑํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด,

@Transactional ์–ด๋…ธํ…Œ์ด์…˜์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ช…์‹œ์ ์œผ๋กœ ๋กค๋ฐฑ ๋Œ€์ƒ์„ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

@Transactional(rollbackFor = IOException.class)

 

๋˜๋Š”, ๋ณด๋‹ค ์ผ๋ฐ˜์ ์ธ ๋ฐฉ์‹์œผ๋กœ๋Š” rollbackFor = Exception.class์™€ ๊ฐ™์ด ๋ชจ๋“  ์ฒดํฌ ์˜ˆ์™ธ๋ฅผ ํฌํ•จ์‹œํ‚ฌ ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

 

์ด๋Ÿฌํ•œ ๊ฒƒ๋“ค์„ ๋ช…ํ™•ํžˆ ํ•˜์ง€ ์•Š์œผ๋ฉด,

์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , DB์— ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ปค๋ฐ‹๋˜๋Š” ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ์œผ๋‹ˆ ์ž˜ ์‹ ๊ฒฝ์จ์ฃผ์–ด์•ผ๊ฒ ๋‹ค ๐Ÿคฏ

 


3๏ธโƒฃ readOnly ์˜ต์…˜์˜ ์˜๋ฏธ์™€ ์ฃผ์˜์ 

@Transactional ์–ด๋…ธํ…Œ์ด์…˜์€ readOnly ์†์„ฑ์„ ์ง€์›ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ์ด ์†์„ฑ์„ ์•„๋ž˜์™€ ๊ฐ™์ด true๋กœ ์„ค์ •ํ•˜๋ฉด ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์€ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์ฒ˜๋ฆฌ๋  ๊ฒƒ์ด๋‹ค.

@Transactional(readOnly = true)

 

์ด ์„ค์ •์€ JPA ๋˜๋Š” JDBC ๋“œ๋ผ์ด๋ฒ„์—๊ฒŒ

"์ด ํŠธ๋žœ์žญ์…˜์—์„œ๋Š” ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์•„."๋ผ๋Š” ํžŒํŠธ๋ฅผ ์ œ๊ณตํ•ด์ค€๋‹ค.

์ด๋กœ ์ธํ•ด Hibernate๋Š” dirty checking์„ ๋น„ํ™œ์„ฑํ™” ํ•˜๊ณ  flush๋ฅผ ์ƒ๋žตํ•˜๋Š” ๋“ฑ, ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ ์ตœ์ ํ™”๋ฅผ ์ ์šฉํ•œ๋‹ค.

 

ํ•˜์ง€๋งŒ ์ฃผ์˜ํ•  ์ ์€, readOnly = true๊ฐ€ ๊ฐ•์ œ์ ์ธ ์“ฐ๊ธฐ ๋ฐฉ์ง€ ๊ธฐ๋Šฅ์€ ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์ด๋‹ค.

์ฆ‰, ํŠธ๋žœ์žญ์…˜ ๋‚ด๋ถ€์—์„œ ์‹ค์ˆ˜๋กœ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์‚ฝ์ž…ํ•˜๋Š” ๊ฒฝ์šฐ,

Hibernate๋Š” flush ์‹œ์ ์— ํ•ด๋‹น ๋ณ€๊ฒฝ ๋‚ด์šฉ์„ ๋ฐ˜์˜ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๊ฒŒ ๋˜๋ฉฐ,

์ด๋กœ ์ธํ•ด์„œ flush ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜ ์˜๋„์น˜ ์•Š์€ ์“ฐ๊ธฐ ์ž‘์—…์ด ์ง„ํ–‰๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

 

๋”ฐ๋ผ์„œ readOnly ํŠธ๋žœ์žญ์…˜์—์„œ๋Š” ์ •๋ง๋กœ ์ฝ๊ธฐ ์ „์šฉ ์ž‘์—…๋งŒ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์ฝ”๋“œ ๊ตฌ์กฐ๋ฅผ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•˜๊ณ ,

์“ฐ๊ธฐ ์ž‘์—…์€ ๋ฐ˜๋“œ์‹œ readOnly = false๊ฐ€ ์ ์šฉ๋œ ๋ณ„๋„์˜ ํŠธ๋žœ์žญ์…˜์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•  ๊ฒƒ์ด๋‹ค.

 


4๏ธโƒฃ ํŠธ๋žœ์žญ์…˜์˜ ํฌ๊ธฐ ์กฐ์ ˆ

ํŠธ๋žœ์žญ์…˜์ด ์ ์šฉ๋˜๋Š” ์ฝ”๋“œ ๋ธ”๋ก์˜ ๊ธธ์ด๋‚˜ ์ง€์† ์‹œ๊ฐ„ ๋˜ํ•œ ์ค‘์š”ํ•œ ๊ณ ๋ ค ์‚ฌํ•ญ์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

๋งŒ์•ฝ, ํŠธ๋žœ์žญ์…˜์ด ๋„ˆ๋ฌด ์งง์€ ๊ฒฝ์šฐ์—๋Š”,

๋นˆ๋ฒˆํ•œ begin๊ณผ commit ๋˜๋Š” rollback์ด ๋ฐœ์ƒํ•ด์„œ ์˜คํžˆ๋ ค ์„ฑ๋Šฅ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—

๋‹จ์ˆœํ•œ ์กฐํšŒ๋‚˜ ์งง์€ ์ž‘์—…์— ํŠธ๋žœ์žญ์…˜์„ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋งŽ์ด ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๋„ ๋‚ญ๋น„์ธ ๊ฒƒ์ด๋‹ค.

 

๋ฐ˜๋Œ€๋กœ, ํŠธ๋žœ์žญ์…˜์ด ๋„ˆ๋ฌด ๊ธด ๊ฒฝ์šฐ์—๋Š”,

์ปค๋„ฅ์…˜์ด ์žฅ์‹œ๊ฐ„ ์ ์œ ๋˜๊ฑฐ๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฝ์ด ์˜ค๋žซ๋™์•ˆ ์œ ์ง€๋˜์–ด ๋™์‹œ์„ฑ ๋ฌธ์ œ๋‚˜ deadlock ๋ฐœ์ƒ ํ™•๋ฅ ์ด ๋†’์•„์ง„๋‹ค๊ณ  ํ•œ๋‹ค.

 

๋”ฐ๋ผ์„œ ํŠธ๋žœ์žญ์…˜์€ DB์— ๋ฐ˜์˜๋˜์–ด์•ผ ํ•˜๋Š” ์ž‘์—… ๋‹จ์œ„๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ช…ํ™•ํžˆ ์ •์˜ํ•ด์•ผ ํ•˜๋ฉฐ,

๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋„“์€ ๋ฒ”์œ„๋ฅผ ๊ฐ€์ง€์ง€ ์•Š๋„๋ก ํ•ญ์ƒ ์œ ์˜ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

 

์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ํ•˜๋‚˜์˜ ๋…ผ๋ฆฌ์  ์ž‘์—… ๋‹จ์œ„๊ฐ€ ํŠธ๋žœ์žญ์…˜์˜ ๊ฒฝ๊ณ„๊ฐ€ ๋˜์–ด์•ผ ํ•จ์„ ๊ธฐ์–ตํ•˜์ž.

 


5๏ธโƒฃ ๋น„๋™๊ธฐ ๋กœ์ง๊ณผ ํŠธ๋žœ์žญ์…˜์˜ ๊ด€๊ณ„

Spring์—์„œ๋Š” @Async๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฉ”์„œ๋“œ๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด ๋ฐฉ์‹์€ ๋ณ„๋„์˜ ์“ฐ๋ ˆ๋“œ์—์„œ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌด์—, ๊ธฐ์กด ํŠธ๋žœ์žญ์…˜ ์ปจํ…์ŠคํŠธ์™€๋Š” ์™„์ „ํžˆ ๋ถ„๋ฆฌ๋œ ์ƒํƒœ์—์„œ ๋™์ž‘ํ•œ๋‹ค.

 

์ฆ‰, @Transactional์ด ์ ์šฉ๋œ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ @Async ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด,

ํ•ด๋‹น ๋น„๋™๊ธฐ ๋ฉ”์„œ๋“œ๋Š” ํŠธ๋žœ์žญ์…˜์ด ์•„์ง ์ปค๋ฐ‹๋˜๊ธฐ ์ „์— ์‹คํ–‰๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ,

๋™์ผํ•œ ํŠธ๋žœ์žญ์…˜ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— DB ์ผ๊ด€์„ฑ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

 

๋”ฐ๋ผ์„œ ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ๋Š” ํŠธ๋žœ์žญ์…˜์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ปค๋ฐ‹๋œ ์ดํ›„์—๋งŒ ๋น„๋™๊ธฐ ๋กœ์ง์ด ์‹คํ–‰๋˜๋„๋ก ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•˜๋‹ค.

 

Spring์—์„œ๋Š” ์ด๋ฅผ ์œ„ํ•ด @TransactionalEventListener(phase = AFTER_COMMIT)์„ ์ œ๊ณตํ•œ๋‹ค.

์ด ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด, ์ง€์ •๋œ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋Š” ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹ ์งํ›„์— ์‹คํ–‰๋˜๋ฏ€๋กœ,

DB์— ๋ฐ˜์˜์ด ํ™•์ •๋œ ์ดํ›„์˜ ์•ˆ์ „ํ•œ ์‹œ์ ์—์„œ ์•Œ๋ฆผ ๋ฐœ์†ก์ด๋‚˜ ๋ฉ”์‹œ์ง€ ํ ๋ฐœํ–‰ ๋“ฑ์˜ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

 


๐Ÿ“š ๊ฒฐ๋ก 

์œ„์—์„œ ์‚ดํŽด๋ณธ ๋‚ด์šฉ์„ ์ข…ํ•ฉํ•˜๋ฉด,

@Transactional์€ ์„ ์–ธ์ ์ธ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ๋งค์šฐ ํŽธ๋ฆฌํ•œ ๋„๊ตฌ์ด์ง€๋งŒ,

ํ”„๋ก์‹œ ๊ธฐ๋ฐ˜์˜ ๋™์ž‘ ํŠน์„ฑ๊ณผ ํŠธ๋žœ์žญ์…˜ ์ „ํŒŒ ๋ฐ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ •์ฑ…์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜์ง€ ์•Š์œผ๋ฉด

์‹ค๋ฌด์—์„œ ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋™์ž‘์„ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

 

์˜ค๋Š˜ ์ •๋ฆฌํ•œ ๋‚ด์šฉ๋“ค์„ ์ฒด๊ณ„์ ์œผ๋กœ ์ดํ•ดํ•˜๊ณ  ์ ์šฉํ•ด์„œ,

@Transactional์„ ์•ˆ์ •์ ์ด๊ณ  ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ

์—ฌ๋Ÿฌ DB ์—ฐ์‚ฐ์ด ์–ฝํžŒ ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ๋„ ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ๊ณผ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์™„์„ฑ๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ๊ฒ ๋‹ค.

๋ฐ˜์‘ํ˜•

'๐Ÿ’ป๊ณต๋ถ€ ๊ธฐ๋ก > ๐Ÿ“Œ Backend' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Backend] RedisConfig ์ž‘์„ฑ: Redis ์—ฐ๋™ํ•˜๊ธฐ  (1) 2025.06.29
[Backend] RedisTemplate  (1) 2025.06.28
[Backend] Redis TTL + JWT  (0) 2025.06.22
[Backend] JWT  (0) 2025.06.21
[Backend] Java 17 VS Java 21  (2) 2025.06.17