[Spring][๊ฐœ๋…] ๐Ÿš€ ๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(AOP) ์™„๋ฒฝ ํ•ด๋ถ€! ์ฝ”๋“œ ์ค‘๋ณต ์ค„์ด๊ณ  ํšจ์œจ์„ฑ 200% ๋†’์ด๊ธฐ

๊น€์ƒ์šฑยท2024๋…„ 10์›” 16์ผ
post-thumbnail

๐Ÿ” AOP(Aspect Oriented Programming) ์™„๋ฒฝ ์ดํ•ด!

ํ•ต์‹ฌ ๊ด€์‹ฌ๊ณผ ๊ณตํ†ต ๊ด€์‹ฌ์„ ๊ตฌ๋ถ„ํ•˜๋Š” ์ƒˆ๋กœ์šด ์ ‘๊ทผ๋ฒ•


๐Ÿš€ AOP๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

AOP(Aspect Oriented Programming)๋Š” ๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ, ๊ธฐ์กด OOP(๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ)์˜ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ•œ ํŒจ๋Ÿฌ๋‹ค์ž„์ž…๋‹ˆ๋‹ค.
์ฃผ์š” ๋กœ์ง๊ณผ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋ถ€๊ฐ€ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜์—ฌ ํšจ์œจ์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค๋‹ˆ๋‹ค.


โš™๏ธ ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ๊ณผ ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์˜ ์ดํ•ด

  • ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ(Core Concern):
    ํ”„๋กœ๊ทธ๋žจ์˜ ๋ณธ์งˆ์ ์ธ ๊ธฐ๋Šฅ๊ณผ ๋กœ์ง์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‡ผํ•‘๋ชฐ ํ”„๋กœ๊ทธ๋žจ์ด๋ผ๋ฉด "์ƒํ’ˆ ์ฃผ๋ฌธ", "๊ฒฐ์ œ ์ฒ˜๋ฆฌ"์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์ด ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

  • ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ(Cross-cutting Concern):
    ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์—์„œ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋ถ€๊ฐ€์ ์ธ ๋กœ์ง์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด "๋กœ๊ทธ ๊ธฐ๋ก", "ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ", "๋ณด์•ˆ ๊ฒ€์‚ฌ" ๋“ฑ๊ณผ ๊ฐ™์€ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.
    ๐Ÿ‘‰ ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์— ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ๊ฐ€ ์ƒ๊ธธ ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.


โŒ OOP์˜ ํ•œ๊ณ„์™€ ๋ฌธ์ œ์ 

OOP(๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ)์—์„œ๋Š” ํด๋ž˜์Šค์™€ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด ๊ธฐ๋Šฅ์„ ๋ชจ๋“ˆํ™”ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ์—๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ์  ์˜ˆ์‹œ

  • ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๋™์ผํ•œ ๋กœ๊ทธ ๊ธฐ๋ก ์ฝ”๋“œ๊ฐ€ ์ค‘๋ณต๋ฉ๋‹ˆ๋‹ค.
  • ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์ง€๊ณ , ์ˆ˜์ • ์‹œ ๋ชจ๋“  ๊ณณ์„ ์ฐพ์•„ ๊ณ ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ณตํ†ต ๋กœ์ง์ด ํฉ์–ด์ ธ ์žˆ์–ด ์œ ์ง€๋ณด์ˆ˜ ๋น„์šฉ์ด ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก AOP๋กœ ํ•ด๊ฒฐํ•ด๋ณด์ž!

AOP๋Š” ํ•ต์‹ฌ ๋กœ์ง๊ณผ ๋ถ€๊ฐ€ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์„ ๋ชจ๋“ˆ(Aspect)๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
์ด๋ฅผ ํ†ตํ•ด ํ•ต์‹ฌ ๊ธฐ๋Šฅ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ž๋™์œผ๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

AOP ์ ์šฉ ์˜ˆ์‹œ

  • ๋กœ๊ทธ ๊ธฐ๋Šฅ์„ ๋ณ„๋„์˜ ๋ชจ๋“ˆ๋กœ ๋งŒ๋“ค์–ด ๋‘๊ณ , ์ด๋ฅผ ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์‹œ ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ํ•œ ๋ฒˆ๋งŒ ์ •์˜๋œ ๊ณตํ†ต ๋กœ์ง์ด ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๋™์‹œ ์ ์šฉ๋˜๋ฏ€๋กœ ์ฝ”๋“œ ์ค‘๋ณต์ด ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

๐ŸŽฏ AOP์˜ ์žฅ์ 

  1. ์ฝ”๋“œ ์ค‘๋ณต ๊ฐ์†Œ: ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์„ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ๋กœ ๊ด€๋ฆฌํ•˜์—ฌ ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์—†์•ฑ๋‹ˆ๋‹ค.
  2. ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด์„ฑ: ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์„ ํ•œ ๊ณณ์—์„œ ์ˆ˜์ •ํ•˜๋ฉด ์ „์ฒด์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.
  3. ๋ชจ๋“ˆํ™” ๊ฐ•ํ™”: ํ•ต์‹ฌ ๋กœ์ง๊ณผ ๋ถ€๊ฐ€ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๋” ๋‚˜์€ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  4. ๊ฐœ๋ฐœ ํšจ์œจ์„ฑ: ํ”„๋กœ๊ทธ๋žจ ์ „๋ฐ˜์˜ ๋ณต์žก๋„๋ฅผ ๋‚ฎ์ถฐ ๋” ๋น ๋ฅด๊ฒŒ ์œ ์ง€๋ณด์ˆ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โœจ AOP๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋Ÿฐ ์ ์ด ์ข‹์•„์š”!

  • ๋กœ๊ทธ ๊ธฐ๋ก์ด๋‚˜ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ๊ณณ์— ํ•„์š”ํ•œ ๊ณตํ†ต ๋กœ์ง์ด ์žˆ๋Š” ๊ฒฝ์šฐ.
  • ๋ณด์•ˆ ๊ฒ€์‚ฌ ๊ฐ™์€ ๋กœ์ง์„ ์ˆ˜์ •ํ•  ๋•Œ, ํ•œ ๋ฒˆ์˜ ์ˆ˜์ •์œผ๋กœ ํ”„๋กœ๊ทธ๋žจ ์ „์ฒด์— ๋ฐ˜์˜ํ•˜๊ณ  ์‹ถ์„ ๋•Œ.
  • ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ ์œ ์ง€๋ณด์ˆ˜ ๋น„์šฉ์„ ์ค„์ด๊ณ  ์‹ถ์„ ๋•Œ.

๐Ÿ” AOP(Aspect Oriented Programming): ํ•ต์‹ฌ๊ณผ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ๋ถ„๋ฆฌํ•˜๋Š” ๋งˆ๋ฒ•

OOP์˜ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๋Š” ์ƒˆ๋กœ์šด ํŒจ๋Ÿฌ๋‹ค์ž„


๐Ÿš€ AOP๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

AOP(Aspect Oriented Programming)๋Š” ๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ, ํ”„๋กœ๊ทธ๋žจ ๋‚ด ํ•ต์‹ฌ ๊ธฐ๋Šฅ๊ณผ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•ด ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ ์ค„์ด๊ณ  ์œ ์ง€๋ณด์ˆ˜๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.


โš™๏ธ ํ•ต์‹ฌ ๊ธฐ๋Šฅ๊ณผ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์˜ ๋ถ„๋ฆฌ

  • ํ•ต์‹ฌ ๊ธฐ๋Šฅ(Core Functionality):
    ํ”„๋กœ๊ทธ๋žจ์˜ ์ฃผ๋œ ๋กœ์ง๊ณผ ๋น„์ฆˆ๋‹ˆ์Šค ๋ชฉํ‘œ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
    ์˜ˆ) ์ฃผ๋ฌธ ์ฒ˜๋ฆฌ, ๊ฒฐ์ œ ์‹œ์Šคํ…œ

  • ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ(Auxiliary Functionality):
    ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์— ๊ฑธ์ณ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ•„์š”ํ•œ ๋ณด์กฐ ๋กœ์ง์ž…๋‹ˆ๋‹ค.
    ์˜ˆ) ๋กœ๊ทธ ๊ธฐ๋ก, ๋ณด์•ˆ ๊ฒ€์‚ฌ, ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ


โŒ OOP์˜ ํ•œ๊ณ„์™€ ๋ฌธ์ œ์ 

  • OOP์—์„œ๋Š” ๊ฐ์ฒด์™€ ํด๋ž˜์Šค์˜ ์‚ฌ์šฉ์œผ๋กœ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•˜์ง€๋งŒ, ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์˜ ๋ฐ˜๋ณต์„ ํ”ผํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.
  • ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๋™์ผํ•œ ์ฝ”๋“œ๊ฐ€ ๋ฐ˜๋ณต๋  ๊ฒฝ์šฐ ์œ ์ง€๋ณด์ˆ˜์˜ ๋ณต์žก์„ฑ์ด ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ ์˜ˆ์‹œ

  • ๋ณด์•ˆ ๊ฒ€์‚ฌ๋ฅผ ์œ„ํ•ด ๊ฐ ๋ฉ”์„œ๋“œ๋งˆ๋‹ค ๋™์ผํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ
  • ๋ชจ๋“  ๋ฉ”์„œ๋“œ์— ๋กœ๊ทธ ๊ธฐ๋ก ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋‹ค ๋ณด๋ฉด ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์ง‘๋‹ˆ๋‹ค.

๐Ÿ’ก AOP๋กœ ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ

AOP๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ๋…๋ฆฝ๋œ ๋ชจ๋“ˆ(Aspect)๋กœ ์ •์˜ํ•˜์—ฌ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์— ์ž๋™์œผ๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

AOP ์ ์šฉ ์˜ˆ์‹œ

  • ๋กœ๊ทธ ๊ด€๋ฆฌ: ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๋Š” ๋กœ์ง์„ ํ•œ ๋ฒˆ ์ •์˜ํ•œ ๋’ค, ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์‹œ ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ: ํŠธ๋žœ์žญ์…˜์„ ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ์—์„œ ์ค‘๋ณต ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ , ํ•„์š”ํ•œ ๊ณณ์— AOP๋กœ ์ž๋™ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋ณด์•ˆ ๊ฒ€์‚ฌ: ๋ชจ๋“  API์— ๋ณด์•ˆ ๊ฒ€์‚ฌ๋ฅผ AOP๋กœ ํ•œ ๋ฒˆ์— ์ ์šฉํ•˜์—ฌ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

๐ŸŽฏ AOP์˜ ์žฅ์ 

  1. ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ: ํ•ต์‹ฌ ๋กœ์ง๊ณผ ๋ถ€๊ฐ€ ๋กœ์ง์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  2. ์ž๋™ํ™”๋œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ์ ์šฉ: ๋กœ๊ทธ๋‚˜ ํŠธ๋žœ์žญ์…˜ ๊ฐ™์€ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ฝ”๋“œ ์—ฌ๋Ÿฌ ๊ณณ์— ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.
  3. ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด: ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ๋ณ€๊ฒฝ ์‹œ Aspect๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ์ „์ฒด ์‹œ์Šคํ…œ์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.
  4. ๊ฐ์ฒด์ง€ํ–ฅ์  ๊ฐ€์น˜ ๋ณด์กด: ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์„ค๊ณ„ ์‹œ ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ ์—†์ด ๋ณธ์งˆ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“Œ AOP๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 

  • ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์— ๊ฑธ์นœ ๊ณตํ†ต ๋กœ์ง์ด ๋ฐ˜๋ณต๋  ๋•Œ AOP๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.
  • ๋กœ๊ทธ ๊ด€๋ฆฌ, ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ, ๋ณด์•ˆ ๊ฒ€์‚ฌ ๋“ฑ ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ์˜ ๋ณต์žก์„ฑ์„ ์ค„์ด๊ณ  ์‹ถ์„ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ ํšจ์œจ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด AOP๊ฐ€ ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

๐ŸŽฏ AOP(Aspect Oriented Programming) ์ ์šฉ ์˜ˆ์‹œ: ์„ฑ๋Šฅ ๊ฒ€์‚ฌ๋ถ€ํ„ฐ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๊นŒ์ง€!

OOP์˜ ํ•œ๊ณ„๋ฅผ ๋„˜์–ด์„œ, AOP๋กœ ๋” ํšจ์œจ์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”!


1๏ธโƒฃ ๊ฐ„๋‹จํ•œ ๋ฉ”์„œ๋“œ์˜ ์„ฑ๋Šฅ ๊ฒ€์‚ฌ

  • ๋ฐฐ์น˜ ์ž‘์—… ์„ฑ๋Šฅ ๊ฐœ์„ :
    ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ DB์— ๋„ฃ๊ฑฐ๋‚˜ ๋นผ๋Š” ์ž‘์—…์—์„œ ์ฟผ๋ฆฌ ์„ฑ๋Šฅ์„ ์ธก์ •ํ•˜๊ณ  ๊ฐœ์„ ํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์ฝ”๋“œ ์ž‘์„ฑ ๋ฐฉ์‹:
    • ๋ณดํ†ต ๋ฉ”์„œ๋“œ์˜ ์‹œ์ž‘๊ณผ ๋์— System.currentTimeMillis()๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜
      ์Šคํ”„๋ง์—์„œ ์ œ๊ณตํ•˜๋Š” StopWatch๋ฅผ ํ™œ์šฉํ•ด ์‹œ๊ฐ„์„ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿšง ๋ฌธ์ œ์ 

  • ๊ฐ ๋ฉ”์„œ๋“œ์— ์ผ์ผ์ด ์„ฑ๋Šฅ ์ธก์ • ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ์ฝ”๋“œ ์ค‘๋ณต์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฉ”์„œ๋“œ๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ์ด๋Ÿฌํ•œ ์ฝ”๋“œ๋ฅผ ์œ ์ง€๋ณด์ˆ˜ํ•˜๋Š” ์ผ์ด ๋ณต์žกํ•ด์ง‘๋‹ˆ๋‹ค.

๐Ÿ’ก AOP ์ ์šฉ ๋ฐฉ๋ฒ•

  • ์„ฑ๋Šฅ ์ธก์ • ๋กœ์ง์„ Aspect๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ํ•„์š”ํ•  ๋•Œ ์ž๋™์œผ๋กœ ์„ฑ๋Šฅ์„ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฐฐ์น˜ ์ž‘์—…๊ณผ ๊ฐ™์€ ๋ฉ”์„œ๋“œ์—์„œ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๊ณ ์ž ํ•  ๋•Œ, ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์— ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ์ž๋™์œผ๋กœ StopWatch ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ์ž๋™ํ™”

  • ํŠธ๋žœ์žญ์…˜์€ ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ๊ณผ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ˆ˜ํ–‰ ์ค‘์— ๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜๋กœ ์ธํ•ด DB์— ๋ฐ˜์˜๋œ ์ž‘์—…์„ ๋˜๋Œ๋ ค์•ผ ํ•  ๋•Œ ํŠธ๋žœ์žญ์…˜์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๐Ÿšง ๋ฌธ์ œ์ 

  • ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด try-catch ๋ธ”๋ก์„ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ด๋Š” ์ฝ”๋“œ๊ฐ€ ๊ธธ๊ณ  ๋ณต์žกํ•ด์ง€๋Š” ์›์ธ์ด ๋ฉ๋‹ˆ๋‹ค.
  • ๋™์ผํ•œ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ์ฝ”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๋ฐ˜๋ณต๋˜๋ฉด์„œ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜๋„ ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค.

๐Ÿ’ก AOP ์ ์šฉ ๋ฐฉ๋ฒ•

  • ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ๋กœ์ง์„ Aspect๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„์— ์ž๋™์œผ๋กœ ํŠธ๋žœ์žญ์…˜์ด ์‹œ์ž‘๋˜๊ณ  ์ข…๋ฃŒ๋˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ์ฝ”๋“œ ๋‚ด๋ถ€์—์„œ ๋งค๋ฒˆ ํŠธ๋žœ์žญ์…˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ํ•„์š” ์—†์ด, AOP๋ฅผ ํ†ตํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3๏ธโƒฃ ์˜ˆ์™ธ ๋ฐ˜ํ™˜ ์ฒ˜๋ฆฌ

  • ์Šคํ”„๋ง์—์„œ๋Š” DataAccessException๊ณผ ๊ฐ™์€ ํ‘œ์ค€ํ™”๋œ ์˜ˆ์™ธ ๊ณ„์ธต์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ, ํŠน์ • ํ”„๋ ˆ์ž„์›Œํฌ(์˜ˆ: Hibernate)์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋Š” ๋ณ„๋„์˜ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿšง ๋ฌธ์ œ์ 

  • ํ”„๋ ˆ์ž„์›Œํฌ๋งˆ๋‹ค ๋‹ค๋ฅธ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.
  • ์—ฌ๋Ÿฌ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ฝ”๋“œ๋ฅผ ๋ฐ˜๋ณต ์ž‘์„ฑํ•ด์•ผ ํ•˜๊ณ , ์ฝ”๋“œ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก AOP ์ ์šฉ ๋ฐฉ๋ฒ•

  • AOP๋ฅผ ํ™œ์šฉํ•ด ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ์˜ˆ์™ธ๋ฅผ ํ‘œ์ค€ ์˜ˆ์™ธ๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, ์‚ฌ์šฉ์ž ์ •์˜ ์˜ˆ์™ธ๋กœ ์žฌ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋Ÿฌํ•œ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์€ ์ฝ”๋“œ์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ณ , ์œ ์ง€๋ณด์ˆ˜๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ œ3์˜ ํ”„๋ ˆ์ž„์›Œํฌ ์˜ˆ์™ธ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์–ด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์—์„œ ๋™์ผํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

4๏ธโƒฃ ์•„ํ‚คํ…์ฒ˜ ๊ฒ€์ฆ

  • ๋Œ€๊ทœ๋ชจ ์‹œ์Šคํ…œ์—์„œ๋Š” ํŠน์ • ๋ฉ”์„œ๋“œ๊ฐ€ ์•„ํ‚คํ…์ฒ˜ ๊ทœ์น™์„ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š๋Š”์ง€ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฉ”์„œ๋“œ๊ฐ€ ์™ธ๋ถ€ ๋ชจ๋“ˆ์— ๋ถˆํ•„์š”ํ•œ ์ ‘๊ทผ์„ ํ•˜์ง€ ์•Š๋„๋ก ์ œ์–ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก AOP ์ ์šฉ ๋ฐฉ๋ฒ•

  • Aspect๋กœ ๊ทœ์น™์„ ์ •์˜ํ•˜๊ณ , ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
  • ๊ทœ์น™ ์œ„๋ฐ˜ ์‹œ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๊ฑฐ๋‚˜ ์‹คํ–‰์„ ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

5๏ธโƒฃ ๊ธฐํƒ€ ํ™œ์šฉ ์˜ˆ์‹œ

  • Hibernate์™€ JDBC์˜ ๋™๊ธฐํ™” ๋ฌธ์ œ ํ•ด๊ฒฐ:
    Hibernate์™€ JDBC๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ DB ๋™๊ธฐํ™” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. AOP๋ฅผ ํ†ตํ•ด ์ด ๋ฌธ์ œ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ์˜ ๋ฝ(lock) ์„ค์ •:
    ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ์— ๋ฝ์„ ์„ค์ •ํ•˜์—ฌ ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฐ๋“œ๋ฝ ๋ฐฉ์ง€:
    PessimisticLockingFailureException๊ณผ ๊ฐ™์€ ์˜ˆ์™ธ๋ฅผ AOP๋กœ ํฌ์ฐฉํ•ด ๋ฐ๋“œ๋ฝ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ๋Œ€์‘ํ•ฉ๋‹ˆ๋‹ค.

  • ๋กœ๊ทธ, ์ธ์ฆ, ๊ถŒํ•œ ๊ด€๋ฆฌ:
    ๋ชจ๋“  ๋ฉ”์„œ๋“œ์— ๋กœ๊ทธ๋‚˜ ์ธ์ฆ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ , AOP๋ฅผ ํ†ตํ•ด ์ค‘์•™์—์„œ ํ•œ ๋ฒˆ์— ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ“Œ AOP์˜ ํšจ๊ณผ์™€ ์žฅ์ 

  1. ์ฝ”๋“œ ์ค‘๋ณต ๊ฐ์†Œ: ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด์„ฑ: ๊ณตํ†ต ๋กœ์ง์„ Aspect๋กœ ๋ถ„๋ฆฌํ•ด ๊ด€๋ฆฌํ•˜๋ฉด, ์ˆ˜์ • ์‹œ Aspect๋งŒ ๋ณ€๊ฒฝํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.
  3. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์ง‘์ค‘: ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ฝ”๋“œ ๋‚ด๋ถ€์— ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์–ด, ๋ณธ์งˆ์ ์ธ ๋กœ์ง์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  4. ์ผ๊ด€์„ฑ ์œ ์ง€: ๋‹ค์–‘ํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์™€ ๊ทœ์น™ ๊ฒ€์ฆ์ด ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
  5. ์œ ์—ฐํ•œ ํ™•์žฅ: ์ƒˆ๋กœ์šด ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•  ๋•Œ๋„ ์‰ฝ๊ฒŒ Aspect๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŒฑ Spring AOP ์šฉ์–ด ์„ค๋ช…


1๏ธโƒฃ Target

  • ์ •์˜:
    Target์€ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์„ ๋‹ด๊ณ  ์žˆ๋Š” ๋ชจ๋“ˆ๋กœ, ์—ฌ๊ธฐ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ(Aspect)์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • ์‰ฝ๊ฒŒ ๋งํ•ด, ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ๋ถ€์—ฌํ•  ๋Œ€์ƒ์ด ๋˜๋Š” ํ•ต์‹ฌ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ:
    ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฒฐ์ œ ์‹œ์Šคํ…œ์—์„œ ๊ฒฐ์ œ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ”๋กœ Target์ด ๋ฉ๋‹ˆ๋‹ค.
    ์—ฌ๊ธฐ์— ๋กœ๊ทธ ๊ธฐ๋ก์ด๋‚˜ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ๊ฐ™์€ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ Advice

  • ์ •์˜:
    Advice๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์˜ ๊ตฌ์ฒด์ ์ธ ๋กœ์ง์ž…๋‹ˆ๋‹ค. ํŠน์ • ์‹œ์ (์˜ˆ: ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „/ํ›„)์— ์ˆ˜ํ–‰๋  Aspect์˜ ๋™์ž‘์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

    • Target์— ์ œ๊ณต๋  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ๋‹ด๊ณ  ์žˆ๋Š” ๋ชจ๋“ˆ์ž…๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ:
    ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „์— ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•˜๊ฑฐ๋‚˜, ๋ฉ”์„œ๋“œ๊ฐ€ ๋๋‚œ ํ›„ ํŠธ๋žœ์žญ์…˜์„ ์ข…๋ฃŒํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ Advice์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

  • Advice ์œ ํ˜•:

    • Before Advice: ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „์— ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.
    • After Advice: ๋ฉ”์„œ๋“œ ์‹คํ–‰ ํ›„์— ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.
    • Around Advice: ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„๋ฅผ ๋‘˜๋Ÿฌ์‹ธ๋ฉฐ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋ฉ”์„œ๋“œ์˜ ์‹คํ–‰์„ ์ œ์–ดํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
    • After-Throwing Advice: ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ๋งŒ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

3๏ธโƒฃ JoinPoint

  • ์ •์˜:
    JoinPoint๋Š” Aspect๊ฐ€ ์ ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ์‹œ์ ์ž…๋‹ˆ๋‹ค.

    • ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด๋‚˜ ํ•„๋“œ ์ ‘๊ทผ ๋“ฑ์˜ ํŠน์ • ์‹œ์ ์—์„œ AOP๊ฐ€ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • Target ๊ฐ์ฒด๊ฐ€ ๊ตฌํ˜„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋Š” JoinPoint๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ:
    ๋งŒ์•ฝ ํŠน์ • API์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๋ ค๋ฉด, ์ด ๋ฉ”์„œ๋“œ์˜ ํ˜ธ์ถœ ์ง€์ ์ด JoinPoint๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.


4๏ธโƒฃ Pointcut

  • ์ •์˜:
    Pointcut์€ ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์„ ์ ์šฉํ•  JoinPoint๋ฅผ ์„ ํƒํ•˜๋Š” ๊ทœ์น™์ž…๋‹ˆ๋‹ค.

    • ์ •๊ทœ ํ‘œํ˜„์‹์ด๋‚˜ ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ๋น„๊ต ๋“ฑ์„ ํ†ตํ•ด ํŠน์ • ๋ฉ”์„œ๋“œ๋ฅผ ์„ ๋ณ„ํ•ฉ๋‹ˆ๋‹ค.
  • Pointcut ํ‘œํ˜„์‹:

    • execution(* com.example.service.*.*(..))
      ์œ„ ํ‘œํ˜„์‹์€ ํŠน์ • ํŒจํ‚ค์ง€์˜ ๋ชจ๋“  ์„œ๋น„์Šค ํด๋ž˜์Šค์— ์žˆ๋Š” ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ JoinPoint๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

5๏ธโƒฃ Aspect

  • ์ •์˜:
    ์—ฌ๋Ÿฌ ๊ฐ์ฒด์— ๊ฑธ์ณ ๊ณตํ†ต์œผ๋กœ ์ ์šฉ๋˜๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ(๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ)์ž…๋‹ˆ๋‹ค.

    • ์˜ˆ) ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ, ๋กœ๊น…, ๋ณด์•ˆ ๋“ฑ
    • AOP์˜ ๊ธฐ๋ณธ ๋ชจ๋“ˆ๋กœ์„œ, ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ(Advice)๊ณผ ๊ทธ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋  ์‹œ์ (Pointcut)์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • ๊ตฌ์„ฑ:

    • Aspect = Advice + Pointcut
      ์ฆ‰, ์–ด๋–ค ๊ธฐ๋Šฅ์„ ์–ด๋–ค ์‹œ์ ์— ์ ์šฉํ• ์ง€๋ฅผ ๋ชจ๋‘ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฒƒ์ด Aspect์ž…๋‹ˆ๋‹ค.
  • ํŠน์ง•:

    • Aspect๋Š” ๋ณดํ†ต Singleton ํ˜•ํƒœ์˜ ๊ฐ์ฒด๋กœ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

6๏ธโƒฃ Advisor

  • ์ •์˜:
    Advisor๋Š” Advice์™€ Pointcut์˜ ์กฐํ•ฉ์œผ๋กœ, Spring AOP์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํŠน๋ณ„ํ•œ ์šฉ์–ด์ž…๋‹ˆ๋‹ค.

    • Aspect์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ, ๋ณด๋‹ค ์„ธ๋ถ€์ ์ธ ์„ค์ •์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ:
    ํŠน์ • ๋ฉ”์„œ๋“œ์—๋งŒ ์ ์šฉ๋˜๋Š” Advisor๋ฅผ ์„ค์ •ํ•ด, ๋กœ๊ทธ ๊ธฐ๋ก์ด๋‚˜ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๋ฅผ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


7๏ธโƒฃ Weaving

  • ์ •์˜:
    Weaving์€ Advice๋ฅผ ํŠน์ • Pointcut์— ์‚ฝ์ž…ํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

    • ์ฆ‰, ์ฝ”๋“œ์— ์ง์ ‘ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ ๋„ ํ•„์š”ํ•œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ(Advice)์„ ์ž๋™์œผ๋กœ ์ถ”๊ฐ€ํ•˜๋Š” ๊ณผ์ •์„ ๋œปํ•ฉ๋‹ˆ๋‹ค.
  • ์ข…๋ฅ˜:

    • ์ปดํŒŒ์ผ ํƒ€์ž„ Weaving: ์ฝ”๋“œ๊ฐ€ ์ปดํŒŒ์ผ๋  ๋•Œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์‚ฝ์ž…๋ฉ๋‹ˆ๋‹ค.
    • ๋Ÿฐํƒ€์ž„ Weaving: ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์ค‘์— ๋™์ ์œผ๋กœ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค.
    • ๋กœ๋“œ ํƒ€์ž„ Weaving: ํด๋ž˜์Šค๊ฐ€ ๋กœ๋”ฉ๋  ๋•Œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์‚ฝ์ž…๋ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ:
    ๋กœ๊ทธ ๊ธฐ๋ก์„ ์œ„ํ•ด ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„์— ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด Weaving์„ ํ†ตํ•ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ํ•ต์‹ฌ ๋กœ์ง์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.


๐Ÿ“Œ Spring AOP์˜ ์ฃผ์š” ๊ฐœ๋… ์ •๋ฆฌ

์šฉ์–ด์„ค๋ช…
Target๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ํ•ต์‹ฌ ๊ธฐ๋Šฅ์„ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฐ์ฒด
AdviceํŠน์ • ์‹œ์ ์— ์ ์šฉ๋  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ •์˜ํ•œ ๋ชจ๋“ˆ
JoinPointAOP๊ฐ€ ์ ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ์‹œ์  (์˜ˆ: ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ, ํ•„๋“œ ์ ‘๊ทผ ๋“ฑ)
PointcutํŠน์ • JoinPoint๋ฅผ ์„ ํƒํ•˜๋Š” ๊ธฐ์ค€ (์ •๊ทœ ํ‘œํ˜„์‹ ๋“ฑ)
AspectAdvice์™€ Pointcut์˜ ์กฐํ•ฉ์œผ๋กœ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ •์˜ํ•œ ๋ชจ๋“ˆ
AdvisorAdvice์™€ Pointcut์˜ ์„ธ๋ถ€ ์„ค์ •์„ ํฌํ•จํ•œ ์กฐํ•ฉ
Weavingํ•ต์‹ฌ ๊ธฐ๋Šฅ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ž๋™์œผ๋กœ ์‚ฝ์ž…ํ•˜๋Š” ๊ณผ์ •

๐Ÿ” AOP ํ‘œํ˜„์‹ ์ •๋ฆฌ ๋ฐ ์˜ˆ์ œ


1๏ธโƒฃ AspectJ ํ‘œํ˜„์‹์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์™€์ผ๋“œ์นด๋“œ

ํ‘œํ˜„์‹์„ค๋ช…
*0๊ฐœ ์ด์ƒ์˜ ๋ฌธ์ž๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ (.)์„ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ๋ชจ๋“  ๋ฌธ์ž์™€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค.
..0๊ฐœ ์ด์ƒ์˜ ํŒจํ‚ค์ง€๋‚˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ (.)์„ ํฌํ•จํ•œ ๊ณ„์ธต ๊ตฌ์กฐ๊นŒ์ง€ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
+ํŠน์ • ํด๋ž˜์Šค์˜ ์„œ๋ธŒ ํด๋ž˜์Šค๋‚˜ ์„œ๋ธŒ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ํ•˜์œ„ ํด๋ž˜์Šค๋‚˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋ชจ๋‘ ๋งค์นญํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ:

  • com.example.*: com.example ํŒจํ‚ค์ง€ ๋‚ด ๋ชจ๋“  ํด๋ž˜์Šค
  • com.example..*: com.example์™€ ๊ทธ ํ•˜์œ„ ํŒจํ‚ค์ง€์˜ ๋ชจ๋“  ํด๋ž˜์Šค
  • UserService+: UserService์™€ ๊ทธ ํ•˜์œ„ ํด๋ž˜์Šค ํฌํ•จ

2๏ธโƒฃ AspectJ ๋…ผ๋ฆฌ ์—ฐ์‚ฐ์ž

ํ‘œํ˜„์‹์„ค๋ช…
!ํ•ด๋‹น ์กฐ๊ฑด์— ํฌํ•จ๋˜์ง€ ์•Š๋Š” ๋ชจ๋“  JoinPoint๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
&&๋‘ ์กฐ๊ฑด์„ ๋ชจ๋‘ ๋งŒ์กฑํ•˜๋Š” JoinPoint๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
`

์˜ˆ์ œ:

  • !execution(* get*(..)): get์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ๋ฉ”์„œ๋“œ
  • execution(* set*(..)) && within(com.example..*): set์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ค‘ com.example ํŒจํ‚ค์ง€ ๋‚ด์—์„œ๋งŒ ์ ์šฉ
  • execution(* get*(..)) || execution(* set*(..)): get์ด๋‚˜ set์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ํ•ด๋‹นํ•˜๋ฉด JoinPoint๋กœ ์ง€์ •

|| ์‚ฌ์šฉ ์œ ์˜์‚ฌํ•ญ: AOP ํ‘œํ˜„์‹์—์„œ๋Š” ์—ฌ๋Ÿฌ ์กฐ๊ฑด์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด get ๋˜๋Š” set์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋งŒ์กฑํ•˜๋ฉด ํ•ด๋‹น JoinPoint๊ฐ€ ์„ ํƒ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ™œ์šฉํ•ด ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์„ ๋™์‹œ์— ๋งค์นญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


3๏ธโƒฃ AOP ๋งคํ•‘ ๊ธฐ๋ณธ ํ‘œํ˜„์‹

ํ‘œํ˜„์‹์„ค๋ช…
get*(..)get์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ชจ๋“  ๋ฉ”์„œ๋“œ. ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ๊ฐœ์ˆ˜๋‚˜ ํƒ€์ž…์— ์ƒ๊ด€์—†์ด ๋งค์นญ๋ฉ๋‹ˆ๋‹ค.
* get*(..)๋ฆฌํ„ด ํƒ€์ž…์ด ๋ฌด์—‡์ด๋“  ์ƒ๊ด€์—†์ด get์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ

์˜ˆ์ œ:

  • execution(public * *(..)): public ์ ‘๊ทผ ์ œ์–ด์ž๋ฅผ ๊ฐ€์ง„ ๋ชจ๋“  ๋ฉ”์„œ๋“œ
  • execution(* set*(..)): set์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ชจ๋“  ๋ฉ”์„œ๋“œ
  • execution(* com.example.service.UserService.*(..)): UserService ํด๋ž˜์Šค ๋‚ด ๋ชจ๋“  ๋ฉ”์„œ๋“œ

4๏ธโƒฃ ํด๋ž˜์Šค ์ง€์ • ํ‘œํ˜„์‹

ํ‘œํ˜„์‹์„ค๋ช…
com.example.*com.example ํŒจํ‚ค์ง€์˜ ๋ชจ๋“  ํด๋ž˜์Šค
com.example..*com.example ํŒจํ‚ค์ง€์™€ ๊ทธ ํ•˜์œ„ ํŒจํ‚ค์ง€์˜ ๋ชจ๋“  ํด๋ž˜์Šค
MemberService+MemberService์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
!MemberServiceMemberService ํด๋ž˜์Šค๋Š” ์ œ์™ธํ•˜๊ณ  ๋‚˜๋จธ์ง€ ๋ชจ๋“  ํด๋ž˜์Šค

์˜ˆ์ œ:

  • com.project.*: project ํŒจํ‚ค์ง€์˜ ๋ชจ๋“  ํด๋ž˜์Šค
  • com.project..*: project ํŒจํ‚ค์ง€์™€ ํ•˜์œ„ ํŒจํ‚ค์ง€์˜ ๋ชจ๋“  ํด๋ž˜์Šค
  • UserService+: UserService์™€ ๊ทธ ํ•˜์œ„ ํด๋ž˜์Šค ํฌํ•จ

5๏ธโƒฃ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ƒ์„ฑ์ž ์ง€์ •

๋งค๊ฐœ๋ณ€์ˆ˜ ์ง€์ • ํ‘œํ˜„์‹:

ํ‘œํ˜„์‹์„ค๋ช…
* addUser(..)๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐœ์ˆ˜์™€ ํƒ€์ž… ์ƒ๊ด€์—†์ด addUser ๋ฉ”์„œ๋“œ
* addUser(String)1๊ฐœ์˜ String ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง„ addUser ๋ฉ”์„œ๋“œ
* addUser(*, ..)์ฒซ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ดํ›„๋Š” ์–ด๋–ค ํƒ€์ž…์ด๋“  ํ—ˆ์šฉ

์ƒ์„ฑ์ž ์ง€์ • ํ‘œํ˜„์‹:

ํ‘œํ˜„์‹์„ค๋ช…
new(..)๋ชจ๋“  ์ƒ์„ฑ์ž๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
UserService new(*)UserService์˜ ๋ชจ๋“  ์ƒ์„ฑ์ž๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ›  AOP ํ‘œํ˜„์‹ ์‚ฌ์šฉ ์˜ˆ์‹œ

1. ๋กœ๊ทธ ๊ธฐ๋ก์— ์‚ฌ์šฉ๋˜๋Š” AOP ํ‘œํ˜„์‹

@Around("execution(* com.example.service.*.*(..))")
public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("Method started: " + joinPoint.getSignature());
    Object result = joinPoint.proceed();
    System.out.println("Method ended: " + joinPoint.getSignature());
    return result;
}
  • ์„ค๋ช…:
    ์œ„ ์ฝ”๋“œ๋Š” com.example.service ํŒจํ‚ค์ง€์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„์— ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•˜๋Š” AOP ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

2. ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ์— ์‚ฌ์šฉ๋˜๋Š” AOP ํ‘œํ˜„์‹

@Before("execution(* com.example.dao.*.*(..))")
public void beginTransaction() {
    System.out.println("Transaction started");
}
  • ์„ค๋ช…:
    com.example.dao ํŒจํ‚ค์ง€์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „์— ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

3. ์กฐ๊ฑด๋ถ€ AOP ์‚ฌ์šฉ ์˜ˆ์ œ (||, && ํ™œ์šฉ)

@Before("execution(* get*(..)) || execution(* set*(..))")
public void logGetterAndSetter() {
    System.out.println("Getter or Setter method invoked");
}
  • ์„ค๋ช…:
    get ๋˜๋Š” set์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์‹คํ–‰๋  ๋•Œ ๋กœ๊ทธ๋ฅผ ๋‚จ๊น๋‹ˆ๋‹ค.

โš™๏ธ OOP vs AOP: ๊ฐ์ฒด ์ง€ํ–ฅ๊ณผ ๊ด€์  ์ง€ํ–ฅ์˜ ์ฐจ์ด์ 


1๏ธโƒฃ OOP (Object-Oriented Programming, ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ)

OOP๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐ์ฒด ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„์–ด ๊ธฐ๋Šฅ์„ ๋ชจ๋“ˆํ™”ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ๊ฐ์ฒด๋Š” Primary Concern(ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ)์„ ์ค‘์‹ฌ์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ์ฃผ์š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

OOP์˜ ๊ตฌ์กฐ์™€ ๋ฌธ์ œ์ :

  • Primary Concern: ๊ฐ ๊ฐ์ฒด๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ํ•ต์‹ฌ ๋กœ์ง์„ ์ค‘์‹ฌ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • Cross-Cutting Concern: ๊ฐ์ฒด์˜ ํ•ต์‹ฌ ๋กœ์ง๊ณผ๋Š” ๋ณ„๊ฐœ๋กœ ์—ฌ๋Ÿฌ ๊ฐ์ฒด์— ๊ณตํ†ต์œผ๋กœ ์ ์šฉ๋˜์–ด์•ผ ํ•˜๋Š” ๋ถ€๊ฐ€์ ์ธ ๋กœ์ง์ž…๋‹ˆ๋‹ค.
    • ์˜ˆ์‹œ: ๋กœ๊ทธ ๊ธฐ๋ก, ๋ณด์•ˆ ๊ฒ€์‚ฌ, ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ๋“ฑ.

๋ฌธ์ œ์ :

OOP์—์„œ๋Š” Cross-Cutting Concern์ด ์—ฌ๋Ÿฌ ๊ฐ์ฒด์— ๊ฑธ์ณ ์ค‘๋ณต๋ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐ ๋ฉ”์„œ๋“œ์— ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์ค‘๋ณต๋˜๊ฑฐ๋‚˜, ๋ณด์•ˆ ๊ฒ€์ฆ์„ ์ถ”๊ฐ€ํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ณณ์— ๋ฐ˜๋ณต๋ฉ๋‹ˆ๋‹ค.


2๏ธโƒฃ AOP (Aspect-Oriented Programming, ๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ)

AOP๋Š” OOP์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ํ•ต์‹ฌ ๋กœ์ง(Primary Concern)๊ณผ ๋ถ€๊ฐ€ ๋กœ์ง(Cross-Cutting Concern)์„ ๋ถ„๋ฆฌํ•˜์—ฌ, ํ•„์š”ํ•  ๋•Œ๋งŒ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ํ•ต์‹ฌ ๋กœ์ง์— ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

AOP์˜ ๊ตฌ์กฐ:

  • Primary Concern: ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ๋ณ€ํ•จ์—†์ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  • Cross-Cutting Concern: ๋ถ€๊ฐ€ ๋กœ์ง์€ Aspect๋กœ ๋ถ„๋ฆฌ๋˜์–ด ํ•„์š”ํ•  ๋•Œ๋งŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

AOP์˜ ์ฃผ์š” ๊ฐœ๋…:

  • Point-Cut: ๋ถ€๊ฐ€ ๋กœ์ง์ด ์ ์šฉ๋  ํŠน์ • ์ง€์ ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํŠน์ • ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์‹œ, ํŠน์ • ํŒจํ„ด์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ๋“ฑ.

  • Advice: Point-Cut์—์„œ ์–ด๋–ค ์‹œ์ ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ• ์ง€๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” Before(๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „), After(๋ฉ”์„œ๋“œ ์‹คํ–‰ ํ›„), ๋˜๋Š” Around(๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„)๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Weaving: ๋ถ€๊ฐ€ ๋กœ์ง(Aspect)์„ ํ•ต์‹ฌ ๋กœ์ง์— ๊ฒฐํ•ฉํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ํ•ต์‹ฌ ๋กœ์ง์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ๋„ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.


3๏ธโƒฃ OOP vs AOP์˜ ๋น„๊ต ์š”์•ฝ

OOP์—์„œ์˜ ๊ตฌ์กฐ:

  • Primary Concern๊ณผ Cross-Cutting Concern์ด ๊ฐ™์€ ๊ฐ์ฒด์— ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
    • ํ•ต์‹ฌ ๋กœ์ง๊ณผ ๋ถ€๊ฐ€ ๋กœ์ง์ด ํ•จ๊ป˜ ์ฝ”๋“œ ๋‚ด์—์„œ ๊ด€๋ฆฌ๋˜๋ฏ€๋กœ, ๋ถ€๊ฐ€ ๋กœ์ง์ด ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ๋ฐ˜๋ณต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

AOP์—์„œ์˜ ๊ตฌ์กฐ:

  • Cross-Cutting Concern์„ ๋ณ„๋„์˜ Aspect๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ, ํ•„์š”ํ•  ๋•Œ๋งŒ ํ•ต์‹ฌ ๋กœ์ง์— ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค.
    • Point-Cut์„ ํ†ตํ•ด ๋ถ€๊ฐ€ ๋กœ์ง์„ ์ ์šฉํ•  ์ง€์ ์„ ์ง€์ •ํ•˜๊ณ , Advice๋กœ ๋ถ€๊ฐ€ ๋กœ์ง์„ ์ •์˜ํ•œ ํ›„, ํ•ต์‹ฌ ๋กœ์ง์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

4๏ธโƒฃ AOP์˜ ์žฅ์ 

  • ํ•ต์‹ฌ ๋กœ์ง๊ณผ ๋ถ€๊ฐ€ ๋กœ์ง ๋ถ„๋ฆฌ: ํ•ต์‹ฌ ๋กœ์ง์€ ๋ณธ๋ž˜์˜ ๊ธฐ๋Šฅ์„ ์œ ์ง€ํ•˜๊ณ , ๋ถ€๊ฐ€ ๋กœ์ง์€ ๋ณ„๋„๋กœ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  • ์ฝ”๋“œ ์ค‘๋ณต ๊ฐ์†Œ: ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ๋กœ ๊ด€๋ฆฌํ•ด ์ฝ”๋“œ ์ค‘๋ณต์„ ์ค„์ž…๋‹ˆ๋‹ค.
  • ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด: ๊ณตํ†ต๋œ ๋กœ์ง(๋กœ๊ทธ, ๋ณด์•ˆ, ํŠธ๋žœ์žญ์…˜ ๋“ฑ)์„ ์ค‘์•™์—์„œ ํ•œ ๋ฒˆ์— ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด, ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๊ฐ„ํŽธํ•ฉ๋‹ˆ๋‹ค.
  • ๋™์  ์ ์šฉ: ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ํŠน์ • ์ง€์ ์—๋งŒ ๋™์ ์œผ๋กœ ๊ฒฐํ•ฉํ•˜์—ฌ, ํ•„์š”ํ•œ ๊ณณ์—์„œ๋งŒ ์ ์šฉ๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

5๏ธโƒฃ ์‹ค์ œ ์ ์šฉ ์˜ˆ์‹œ

OOP ๋ฐฉ์‹:

  • ๋กœ๊ทธ ๊ธฐ๋ก, ๋ณด์•ˆ ๊ฒ€์ฆ, ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ๊ฐ™์€ ๋กœ์ง์„ ๊ฐ ํด๋ž˜์Šค์— ์ค‘๋ณตํ•˜์—ฌ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์ฝ”๋“œ์˜ ๋ณต์žก์„ฑ์ด ์ฆ๊ฐ€ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค.

AOP ๋ฐฉ์‹:

  • ๋กœ๊ทธ ๊ธฐ๋ก: ๋ชจ๋“  ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๋ ค๋ฉด, ๋กœ๊ทธ ๊ธฐ๋ก ๋กœ์ง์„ Aspect๋กœ ์ •์˜ํ•˜๊ณ  AOP๋กœ ์ž๋™ ์ ์šฉ์‹œํ‚ต๋‹ˆ๋‹ค.
  • ๋ณด์•ˆ ๊ฒ€์ฆ: API ํ˜ธ์ถœ๋งˆ๋‹ค ๋ณด์•ˆ ๊ฒ€์ฆ์ด ํ•„์š”ํ•  ๊ฒฝ์šฐ, ๋ณด์•ˆ ๊ฒ€์ฆ ๋กœ์ง์„ Advice๋กœ ์ •์˜ํ•˜๊ณ  ํŠน์ • ๋ฉ”์„œ๋“œ์—๋งŒ ์ ์šฉ๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ›  Spring AOP ํŠน์ง•: ํ”„๋ก์‹œ ๊ธฐ๋ฐ˜ AOP์˜ ์ดํ•ด


1๏ธโƒฃ Spring์€ ํ”„๋ก์‹œ(Proxy) ๊ธฐ๋ฐ˜ AOP๋ฅผ ์ง€์›

Spring AOP์˜ ํ•ต์‹ฌ์€ ํ”„๋ก์‹œ(Proxy) ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด Target ๊ฐ์ฒด์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๊ณ , ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์€ ์‹คํ–‰ ์‹œ๊ฐ„(Runtime)์— ๋™์ ์œผ๋กœ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

๐Ÿ”‘ ์ฃผ์š” ๊ฐœ๋…:

  • Target: ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฐ์ฒด.
  • Proxy: Target์„ ๊ฐ์‹ธ๋Š” ๊ฐ์ฒด๋กœ, Target์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋™์ ์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. Caller๋Š” Target ๋Œ€์‹  Proxy๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • Advice: Proxy๊ฐ€ Target์— ์ ์šฉํ•˜๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์œผ๋กœ, ๋ถ€๊ฐ€์ ์ธ ๋กœ์ง์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

โš™๏ธ ๋™์ž‘ ๋ฐฉ์‹:

  • Spring์€ Target ๊ฐ์ฒด์— ๋Œ€ํ•œ Proxy๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜์—ฌ, ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ Target์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด Proxy๋Š” ์‹คํ–‰ ์‹œ๊ฐ„์— ๋™์ ์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋˜๋ฉด์„œ Proxy๊ฐ€ Target์— ๋Œ€ํ•ด ๋งŒ๋“ค์–ด์ง€๋ฉฐ, Target์˜ ๋กœ์ง์„ ํ˜ธ์ถœํ•  ๋•Œ Proxy๋ฅผ ํ†ตํ•ด ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • Proxy๋Š” Advice๋ฅผ ์‚ฌ์šฉํ•ด Target ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๋ฉฐ, ํ•ต์‹ฌ ๋กœ์ง์„ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ๋ถ€๊ฐ€ ๋กœ์ง์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

  • ๋กœ๊ทธ ๊ธฐ๋ก์„ ๋‚จ๊ธธ ๋•Œ, Caller๋Š” Target ๋Œ€์‹  Proxy๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , Proxy๋Š” ๋จผ์ € ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธด ํ›„์— Target์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

2๏ธโƒฃ ํ”„๋ก์‹œ(Proxy)๊ฐ€ ํ˜ธ์ถœ์„ ๊ฐ€๋กœ์ฑˆ๋‹ค (Intercept)

Spring AOP์—์„œ Proxy๋Š” Target ๊ฐ์ฒด์— ๋Œ€ํ•œ ํ˜ธ์ถœ์„ ๊ฐ€๋กœ์ฑ„๋Š”(Intercept) ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด Proxy๊ฐ€ ํ˜ธ์ถœ์„ ๋ฐ›์œผ๋ฉฐ, ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ๋จผ์ € ์‹คํ–‰ํ•œ ๋’ค Target์˜ ์‹ค์ œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

โš™๏ธ ๋™์ž‘ ๊ณผ์ •:

  1. Caller๊ฐ€ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, Proxy๊ฐ€ ํ˜ธ์ถœ์„ ๋จผ์ € ๋ฐ›์Šต๋‹ˆ๋‹ค.
  2. Proxy๋Š” Advice์—์„œ ์ •์˜ํ•œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•˜๊ฑฐ๋‚˜ ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๋Š” ์ž‘์—…์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
  3. ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ๋ชจ๋‘ ์‹คํ–‰๋œ ํ›„, Proxy๋Š” Target์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ›  ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹:

  • ์ „์ฒ˜๋ฆฌ(Pre-processing) Advice: ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋กœ๊ทธ๋ฅผ ๋‚จ๊น๋‹ˆ๋‹ค.
  • ํ›„์ฒ˜๋ฆฌ(Post-processing) Advice: ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋œ ํ›„์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํŠธ๋žœ์žญ์…˜์„ ์ข…๋ฃŒํ•˜๊ฑฐ๋‚˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

  • ์ „์ฒ˜๋ฆฌ Advice: ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๊ณ  ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.
  • ํ›„์ฒ˜๋ฆฌ Advice: ๋ฉ”์„œ๋“œ ์‹คํ–‰์ด ๋๋‚œ ํ›„ ํŠธ๋žœ์žญ์…˜์„ ์ข…๋ฃŒํ•˜๊ฑฐ๋‚˜ ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ๋กค๋ฐฑ ์ฒ˜๋ฆฌ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.

3๏ธโƒฃ Spring AOP๋Š” ๋ฉ”์„œ๋“œ JoinPoint๋งŒ ์ง€์›

Spring AOP๋Š” ๋ฉ”์„œ๋“œ JoinPoint๋งŒ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, Spring AOP์—์„œ๋Š” ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ์ ์—๋งŒ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‹ค๋ฅธ ์‹œ์ (์˜ˆ: ํ•„๋“œ ์ ‘๊ทผ, ๊ฐ์ฒด ์ƒ์„ฑ ๋“ฑ)์€ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๐Ÿ›  JoinPoint๋ž€?

JoinPoint๋Š” AOP์—์„œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ํŠน์ • ์‹œ์ ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. Spring AOP์—์„œ๋Š” ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์‹œ์ ๋งŒ JoinPoint๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.

Spring AOP์˜ ์ œํ•œ:

  • Spring AOP๋Š” ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์‹œ์ ์—๋งŒ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์ฒด ์ƒ์„ฑ, ํ•„๋“œ ์กฐํšŒ ๋ฐ ์ˆ˜์ •, static ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ๋“ฑ์€ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๐Ÿ”ง ๊ณ ๊ธ‰ AOP ๊ธฐ๋Šฅ (AspectJ):

  • AspectJ ๊ฐ™์€ ๊ณ ๊ธ‰ AOP ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋” ๋‹ค์–‘ํ•œ JoinPoint๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์ฒด ์ƒ์„ฑ ์‹œ์ , ํ•„๋“œ ์ ‘๊ทผ ๋ฐ ์ˆ˜์ •, static ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ๋“ฑ ๋‹ค์–‘ํ•œ ์‹œ์ ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

  • Spring AOP: ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ์ ์—๋งŒ ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • AspectJ: ๊ฐ์ฒด ์ƒ์„ฑ ์‹œ์ ์ด๋‚˜ ํ•„๋“œ ๊ฐ’ ์กฐํšŒ ๋ฐ ์ˆ˜์ • ์‹œ์ ์—๋„ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“ ๊ฒฐ๋ก : Spring AOP์˜ ์žฅ์ ๊ณผ ํ•œ๊ณ„

Spring AOP๋Š” ํ”„๋ก์‹œ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ํ•ต์‹ฌ ๋กœ์ง๊ณผ ๋ถ€๊ฐ€ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•ด ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ์ ์—์„œ๋งŒ ๋™์ž‘ํ•˜๋ฏ€๋กœ, ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ๋„ ํ•„์š”ํ•œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์žฅ์ :

  • ์ฝ”๋“œ ์ค‘๋ณต์„ ์ค„์ž„: ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๊ณตํ†ต์ ์œผ๋กœ ํ•„์š”ํ•œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ต์‹ฌ ๋กœ์ง๊ณผ ๋ถ€๊ฐ€ ๋กœ์ง์„ ๋ถ„๋ฆฌ: ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ: ๊ณตํ†ต์ ์ธ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ(๋กœ๊ทธ, ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ๋“ฑ)์„ ๋ณ„๋„๋กœ ๊ด€๋ฆฌํ•ด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค.

ํ•œ๊ณ„:

  • Spring AOP๋Š” ๋ฉ”์„œ๋“œ JoinPoint๋งŒ ์ง€์›ํ•˜์—ฌ, ๊ฐ์ฒด ์ƒ์„ฑ, ํ•„๋“œ ์ ‘๊ทผ ๋“ฑ์˜ ์ž‘์—…์—๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•  ๊ฒฝ์šฐ, AspectJ ๊ฐ™์€ ๊ณ ๊ธ‰ AOP ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”ง Spring AOP ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

Spring AOP๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๋ฐฉ์‹์ด ์žˆ์Šต๋‹ˆ๋‹ค: POJO ๊ธฐ๋ฐ˜ ๊ตฌํ˜„, Spring API ๊ธฐ๋ฐ˜ ๊ตฌํ˜„, ์–ด๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜ ๊ตฌํ˜„. ๊ฐ ๋ฐฉ์‹์˜ ํŠน์„ฑ๊ณผ ์žฅ๋‹จ์ ์„ ์‚ดํŽด๋ณด๊ณ , ์–ด๋–ค ์ƒํ™ฉ์—์„œ ๊ฐ€์žฅ ์ ํ•ฉํ•œ์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


1๏ธโƒฃ POJO Class๋ฅผ ์ด์šฉํ•œ AOP ๊ตฌํ˜„

POJO(Plain Old Java Object)๋Š” ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ๊ฐ์ฒด๋กœ, ํŠน๋ณ„ํ•œ ์ƒ์†์ด๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ ์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. POJO ๊ธฐ๋ฐ˜์˜ AOP ๊ตฌํ˜„์€ ์ž๋ฐ” ํด๋ž˜์Šค์— ์ข…์†๋˜์ง€ ์•Š๊ณ  ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ์ฝ”๋“œ๋กœ AOP๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

๐Ÿ“Œ ํŠน์ง•:

  • ์ˆœ์ˆ˜ํ•œ ํด๋ž˜์Šค ๊ตฌ์กฐ: POJO ํด๋ž˜์Šค๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜์กดํ•˜์ง€ ์•Š์œผ๋ฉฐ, ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด AOP๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  • ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ƒ์„ฑ: AOP ์ ์šฉ ์‹œ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์ „ํ›„๋กœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ(Advice)์„ ์ˆ˜๋™์œผ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๐ŸŸข ์žฅ์ :

  • ํ”„๋ ˆ์ž„์›Œํฌ ๋…๋ฆฝ์„ฑ: Spring์ด๋‚˜ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์— ์ข…์†๋˜์ง€ ์•Š๊ณ  ์ž๋ฐ”๋งŒ์œผ๋กœ AOP๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์œ ์—ฐ์„ฑ: ๋ณ„๋„์˜ ์„ค์ •์ด๋‚˜ ์ œํ•œ์ด ์—†์–ด ์–ด๋–ค ํ”„๋กœ์ ํŠธ์—๋„ ์ ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”ด ๋‹จ์ :

  • ๋ณต์žกํ•œ ์„ค์ •: AOP ๊ตฌํ˜„์„ ์œ„ํ•ด ๊ฐœ๋ฐœ์ž๊ฐ€ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ, Spring API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์„ค์ •์ด ๋ณต์žกํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

public class MyService {
    public void myMethod() {
        System.out.println("Executing my method...");
    }
}

public class MyServiceProxy extends MyService {
    @Override
    public void myMethod() {
        // ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ: ๋กœ๊ทธ ์ถœ๋ ฅ
        System.out.println("Logging before method execution.");
        super.myMethod();
        // ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ: ๋กœ๊ทธ ์ถœ๋ ฅ
        System.out.println("Logging after method execution.");
    }
}

์ด ์ฝ”๋“œ๋Š” ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„๋กœ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.


2๏ธโƒฃ Spring API๋ฅผ ์ด์šฉํ•œ AOP ๊ตฌํ˜„

Spring AOP๋Š” Spring์ด ์ œ๊ณตํ•˜๋Š” API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ AOP๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ, POJO๋ณด๋‹ค ๋” ๊ฐ„ํŽธํ•˜๊ณ  ๊ฐ•๋ ฅํ•˜๊ฒŒ AOP๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Spring์—์„œ๋Š” ProxyFactoryBean ๋“ฑ์˜ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ , ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ ํŠน์ง•:

  • Spring์˜ ProxyFactoryBean ์‚ฌ์šฉ: Spring์—์„œ๋Š” ProxyFactoryBean์„ ํ†ตํ•ด ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๋Š” ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ„๋‹จํ•œ ์„ค์ •: Spring API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ณ„๋„์˜ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ณ , ์ž๋™์œผ๋กœ AOP๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŸข ์žฅ์ :

  • ๊ฐ„ํŽธํ•œ ๊ตฌํ˜„: Spring API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์ฝ”๋“œ์˜ ๋ณต์žก์„ฑ์ด ์ค„์–ด๋“ค๊ณ , ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ž๋™ ๊ด€๋ฆฌ: ํ”„๋ก์‹œ ์ƒ์„ฑ๊ณผ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ์ ์šฉ์ด ์ž๋™์œผ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.

๐Ÿ”ด ๋‹จ์ :

  • Spring ์ข…์†์„ฑ: Spring API์— ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ์—, Spring ํ™˜๊ฒฝ์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

ProxyFactoryBean proxyFactory = new ProxyFactoryBean();
proxyFactory.setTarget(new MyService());
proxyFactory.addAdvice(new LoggingAdvice());
MyService proxy = (MyService) proxyFactory.getObject();
proxy.myMethod();

์ด ์ฝ”๋“œ์—์„œ๋Š” Spring์˜ ProxyFactoryBean์„ ์‚ฌ์šฉํ•ด ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•œ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ํ›„, ํ•ด๋‹น ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.


3๏ธโƒฃ Annotation์„ ์ด์šฉํ•œ AOP ๊ตฌํ˜„

Spring 2.0 ์ดํ›„๋ถ€ํ„ฐ๋Š” ์–ด๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์˜ AOP ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•œ AOP๋Š” AspectJ ์Šคํƒ€์ผ์˜ ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ AOP๋ฅผ ์ ์šฉํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์„ค์ • ํŒŒ์ผ์ด๋‚˜ Bean์„ ์ž‘์„ฑํ•  ํ•„์š” ์—†์ด ๊ฐ„๋‹จํ•˜๊ฒŒ AOP๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“Œ ํŠน์ง•:

  • @AspectJ ์–ด๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ: @Aspect, @Before, @After, @Around ๋“ฑ์˜ ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ๋ฉ”์„œ๋“œ์— ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋Ÿฐํƒ€์ž„ ๋˜๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— ๋™์ ์œผ๋กœ ์ ์šฉ: ๋Ÿฐํƒ€์ž„์ด๋‚˜ ์ปดํŒŒ์ผ ์‹œ์ ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ๋™์ ์œผ๋กœ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

๐ŸŸข ์žฅ์ :

  • ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ: ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์„œ๋“œ์— ์‰ฝ๊ฒŒ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์„ค์ • ํŒŒ์ผ ์˜์กด์„ฑ ๊ฐ์†Œ: XML ์„ค์ •์ด๋‚˜ Bean ์„ค์ • ์—†์ด ์–ด๋…ธํ…Œ์ด์…˜๋งŒ์œผ๋กœ AOP๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”ด ๋‹จ์ :

  • ์œ ์—ฐ์„ฑ ์ œํ•œ: ๋ณต์žกํ•œ ์กฐ๊ฑด์ด๋‚˜ ๋กœ์ง์„ ์ ์šฉํ•˜๊ธฐ์—๋Š” ์–ด๋…ธํ…Œ์ด์…˜ ๋ฐฉ์‹์ด ์ œํ•œ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿด ๋•Œ๋Š” Spring API๋‚˜ XML ์„ค์ •์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

@Aspect
public class LoggingAspect {
    
    @Before("execution(* MyService.*(..))")
    public void logBefore() {
        System.out.println("Logging before method execution");
    }

    @After("execution(* MyService.*(..))")
    public void logAfter() {
        System.out.println("Logging after method execution");
    }
}

์ด ์ฝ”๋“œ์—์„œ๋Š” ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„์— ๋กœ๊ทธ ๊ธฐ๋ก ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ›  Spring AOP ๊ตฌํ˜„ ๋ฐฉ์‹ ๋น„๊ต

๊ตฌํ˜„ ๋ฐฉ์‹์„ค๋ช…์žฅ์ ๋‹จ์ 
POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„์ˆœ์ˆ˜ ์ž๋ฐ” ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ก์‹œ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ƒ์„ฑํ•ด AOP ๊ตฌํ˜„ํ”„๋ ˆ์ž„์›Œํฌ ๋…๋ฆฝ์ , ์œ ์—ฐ์„ฑ์„ค์ •๊ณผ ๊ตฌํ˜„์ด ๋ณต์žกํ•จ
Spring API ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„Spring์ด ์ œ๊ณตํ•˜๋Š” ProxyFactoryBean ๋“ฑ์„ ์‚ฌ์šฉํ•ด AOP ๊ตฌํ˜„Spring์˜ ๊ฐ•๋ ฅํ•œ API ์ง€์›, ๊ฐ„ํŽธํ•œ ์„ค์ •Spring ํ”„๋ ˆ์ž„์›Œํฌ์— ์ข…์†๋จ
Annotation ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„@AspectJ ์Šคํƒ€์ผ์˜ ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด AOP ์ ์šฉ์ฝ”๋“œ ๊ฐ„๊ฒฐ์„ฑ, ์„ค์ • ํŒŒ์ผ ์˜์กด์„ฑ ๊ฐ์†Œ๋ณต์žกํ•œ ๋กœ์ง ๊ตฌํ˜„ ์‹œ ์œ ์—ฐ์„ฑ ๋ถ€์กฑ

โš™๏ธ POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - ์„ค์ • ๋ฐฉ๋ฒ•


1๏ธโƒฃ POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - ์„ค์ • ๋ฐฉ๋ฒ• (1/5)

Spring AOP๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด XML Schema๋ฅผ ์ด์šฉํ•ด AOP ๊ด€๋ จ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„ค์ž„์ŠคํŽ˜์ด์Šค์™€ ์Šคํ‚ค๋งˆ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ์„ค์ • ๋‚ด์šฉ:

  • xmlns:aop: AOP ๊ด€๋ จ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก AOP ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
  • xsi:schemaLocation: AOP ์Šคํ‚ค๋งˆ ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•˜์—ฌ Spring์ด AOP ์„ค์ •์„ ํŒŒ์‹ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ์˜ˆ์‹œ ์ฝ”๋“œ:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>

์„ค๋ช…:
์ด ์„ค์ •์€ XML์—์„œ AOP ๊ด€๋ จ ํƒœ๊ทธ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๊ณ , AOP ๊ธฐ๋Šฅ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„ค์ž„์ŠคํŽ˜์ด์Šค์™€ ์Šคํ‚ค๋งˆ๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.


2๏ธโƒฃ POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - ์„ค์ • ๋ฐฉ๋ฒ• (2/5)

AOP ์„ค์ •์€ Advice, Aspect, Pointcut์„ ์ •์˜ํ•˜์—ฌ ํŠน์ • ๋ฉ”์„œ๋“œ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๋Š” ๊ณผ์ •์œผ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ์ด ์„ค์ •์„ ํ†ตํ•ด ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์‹œ ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๊ฑฐ๋‚˜ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก ์„ค์ • ๋‚ด์šฉ:

  • <bean> ํƒœ๊ทธ: loggingAdvice๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ๋กœ๊ทธ ๊ธฐ๋ก ๊ธฐ๋Šฅ์„ ํ•˜๋Š” Advice๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. LoggingAdvice ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • <aop:aspect> ํƒœ๊ทธ: loggingAspect๋ผ๋Š” Aspect๋ฅผ ์ •์˜ํ•˜๊ณ , ํŠน์ • ๋ฉ”์„œ๋“œ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋  ์ง€์ ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. publicMethods๋ผ๋Š” Pointcut์„ ์ •์˜ํ•˜์—ฌ ํŠน์ • ํŒจํ‚ค์ง€์˜ public ๋ฉ”์„œ๋“œ์—๋งŒ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ์˜ˆ์‹œ ์ฝ”๋“œ:

<bean id="loggingAdvice" 
      class="com.example.aop.LoggingAdvice" />

<aop:config>
    <aop:aspect id="loggingAspect" ref="loggingAdvice">
        <aop:pointcut id="publicMethods" 
                      expression="execution(public * com.example.service..*.*(..))" />
        <aop:before method="logBefore" pointcut-ref="publicMethods" />
    </aop:aspect>
</aop:config>

์„ค๋ช…:

  • com.example.service ํŒจํ‚ค์ง€ ๋‚ด์˜ public ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. logBefore ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „์— ๋กœ๊ทธ ๊ธฐ๋ก์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

3๏ธโƒฃ POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - ์„ค์ • ๋ฐฉ๋ฒ• (3/5)

AOP์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ฃผ์š” ํƒœ๊ทธ๋ฅผ ์ •์˜ํ•˜์—ฌ Aspect, Pointcut, Advice๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ํƒœ๊ทธ๋Š” AOP ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ›  AOP ์„ค์ • ํƒœ๊ทธ ์„ค๋ช…:

  • <aop:config>: AOP ์„ค์ •์˜ ๋ฃจํŠธ ํƒœ๊ทธ๋กœ AOP ์„ค์ •์„ ๋ฌถ์–ด์„œ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • <aop:aspect>: Aspect๋ฅผ ์ •์˜ํ•˜๋ฉฐ, ํŠน์ • ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  Advice๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • <aop:pointcut>: ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋  ๋ฉ”์„œ๋“œ๋‚˜ ํด๋ž˜์Šค์˜ ์ง€์ ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ›  Advice ์„ค์ • ํƒœ๊ทธ ์„ค๋ช…:

  • <aop:before>: ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „์— ์‹คํ–‰๋  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
  • <aop:after-returning>: ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋œ ํ›„์— ์ ์šฉํ•  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
  • <aop:after-throwing>: ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ค‘ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ ์šฉ๋  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
  • <aop:after>: ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ ์‹คํ–‰ ๋˜๋Š” ์˜ˆ์™ธ ๋ฐœ์ƒ๊ณผ ๊ด€๊ณ„์—†์ด ์‹คํ–‰ ํ›„์— ์ ์šฉ๋  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
  • <aop:around>: ๋ฉ”์„œ๋“œ ์ „ํ›„ ๋ชจ๋‘์— ์ ์šฉ๋  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

4๏ธโƒฃ POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - ์„ค์ • ๋ฐฉ๋ฒ• (4/5)

Aspect๋Š” ์—ฌ๋Ÿฌ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ(Advice)์„ ํ•˜๋‚˜๋กœ ๋ฌถ์–ด ๊ด€๋ฆฌํ•˜๋ฉฐ, Pointcut์„ ์‚ฌ์šฉํ•ด ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์–ด๋–ค ๋ฉ”์„œ๋“œ์— ์ ์šฉํ• ์ง€ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ์„ค์ • ๋‚ด์šฉ:

  • <aop:aspect> ํƒœ๊ทธ: loggingAspect๋ผ๋Š” Aspect๋ฅผ ์ •์˜ํ•˜๊ณ , ๋กœ๊ทธ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” Advice๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. ์ด Aspect๋Š” publicMethods๋ผ๋Š” Pointcut์„ ํ†ตํ•ด ํŠน์ • ๋ฉ”์„œ๋“œ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ref ์†์„ฑ: Aspect์—์„œ ์ฐธ์กฐํ•  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ(Advice)์„ bean์œผ๋กœ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
  • id ์†์„ฑ: Aspect ํƒœ๊ทธ์˜ ์‹๋ณ„์ž๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ Pointcut์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“ ์˜ˆ์‹œ ์ฝ”๋“œ:

<aop:config>
    <aop:aspect id="loggingAspect" ref="loggingAdvice">
        <aop:pointcut id="publicMethods" 
                      expression="execution(public * com.example.service..*.*(..))" />
        <aop:before method="logBefore" pointcut-ref="publicMethods" />
    </aop:aspect>
</aop:config>

์„ค๋ช…:

  • ์ด ์„ค์ •์€ loggingAspect๋ผ๋Š” Aspect๋ฅผ ํ†ตํ•ด public ๋ฉ”์„œ๋“œ์— ๋กœ๊ทธ ๊ธฐ๋ก์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Pointcut์„ ํ†ตํ•ด ์ง€์ •๋œ public ๋ฉ”์„œ๋“œ์—์„œ๋งŒ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

5๏ธโƒฃ POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - ์„ค์ • ๋ฐฉ๋ฒ• (5/5)

Pointcut์€ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋  ์ง€์ ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ํŠน์ • ํŒจํ‚ค์ง€, ํด๋ž˜์Šค, ๋ฉ”์„œ๋“œ ๋“ฑ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, AOP ํ‘œํ˜„์‹์„ ํ†ตํ•ด ์›ํ•˜๋Š” ๋Œ€๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก ์„ค์ • ๋‚ด์šฉ:

  • <aop:pointcut>: AOP ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•ด ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋  ์ง€์ ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. execution(public * com.example.service..*.*(..)) ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ public ๋ฉ”์„œ๋“œ์—๋งŒ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • id ์†์„ฑ: Pointcut์˜ ๊ณ ์œ  ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค. ์ดํ›„ Advice ํƒœ๊ทธ์—์„œ ์ฐธ์กฐํ•˜์—ฌ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • expression ์†์„ฑ: ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋  Pointcut์„ ์ง€์ •ํ•˜๋Š” ํ‘œํ˜„์‹์ž…๋‹ˆ๋‹ค.

๐Ÿ“ ์˜ˆ์‹œ ์ฝ”๋“œ:

<aop:pointcut id="publicMethods" 
              expression="execution(public * com.example.service..*.*(..))" />

์„ค๋ช…:

  • com.example.service ํŒจํ‚ค์ง€ ๋‚ด public ๋ฉ”์„œ๋“œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ AOP ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๋Š” Pointcut์„ ์ •์˜ํ•œ ์„ค์ •์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๋ฉ”์„œ๋“œ์—๋งŒ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ” POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - Advice ์ข…๋ฅ˜ (1/5)

๐ŸŒŸ Before Advice ์‹คํ–‰ ์ˆœ์„œ

Before Advice๋Š” ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „์— ํŠน์ • ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ๋™์ž‘ ์ˆœ์„œ:

  1. Client๊ฐ€ Target ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, Spring AOP์—์„œ ์ƒ์„ฑ๋œ Proxy ๊ฐ์ฒด๊ฐ€ ์ด ํ˜ธ์ถœ์„ ๊ฐ€๋กœ์ฑ•๋‹ˆ๋‹ค.
  2. Proxy ๊ฐ์ฒด๋Š” ๋จผ์ € Before Advice์— ์ •์˜๋œ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  3. Before Advice๊ฐ€ ์™„๋ฃŒ๋œ ํ›„์—** Target Bean์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์ฃผ์˜: ๋งŒ์•ฝ Target ๋ฉ”์„œ๋“œ์—์„œ Exception(์˜ˆ์™ธ)์ด ๋ฐœ์ƒํ•˜๋ฉด, Before Advice๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๐Ÿ“‚ ์˜ˆ์‹œ ์ฝ”๋“œ:

public class LoggingAdvice {
    public void logBefore() {
        System.out.println("๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ ๋กœ๊ทธ ๊ธฐ๋ก");
    }
}

์„ค๋ช…:

  • logBefore ๋ฉ”์„œ๋“œ๋Š” Target ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ” POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - Advice ์ข…๋ฅ˜ (2/5)

๐ŸŒŸ After Returning Advice

After Returning Advice๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋œ ํ›„ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์™„๋ฃŒ๋œ ํ›„์—๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ๋™์ž‘ ์ˆœ์„œ:

  1. Client๊ฐ€ Target ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , Proxy ๊ฐ์ฒด๊ฐ€ ์ด๋ฅผ ๊ฐ€๋กœ์ฑ•๋‹ˆ๋‹ค.
  2. Proxy ๊ฐ์ฒด๋Š” Target ๋ฉ”์„œ๋“œ๋ฅผ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰ํ•œ ํ›„, After Returning Advice๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  3. After Returning Advice๋Š” ๋ฐ˜ํ™˜๋œ ๊ฐ’์„ ์ด์šฉํ•˜์—ฌ ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“‚ ์˜ˆ์‹œ ์ฝ”๋“œ:

public class ResultLoggingAdvice {
    public void logAfterReturning(Object returnValue) {
        System.out.println("๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๊ฐ’: " + returnValue);
    }
}

์„ค๋ช…:

  • logAfterReturning ๋ฉ”์„œ๋“œ๋Š” Target ๋ฉ”์„œ๋“œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋œ ํ›„์—, ๋ฐ˜ํ™˜๋œ ๊ฐ’์„ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”‘ Advice ์„ค์ •:

<aop:aspect id="resultAspect" ref="resultLoggingAdvice">
    <aop:pointcut id="serviceMethods" expression="execution(* com.example.service..*(..))" />
    <aop:after-returning method="logAfterReturning" pointcut-ref="serviceMethods" returning="resultValue" />
</aop:aspect>

๐Ÿ” POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - Advice ์ข…๋ฅ˜ (3/5)

๐ŸŒŸ After Throwing Advice

After Throwing Advice๋Š” ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ค‘ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ค‘ ๋ฐœ์ƒํ•œ Exception์„ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“ ๋™์ž‘ ์ˆœ์„œ:

  1. Client๊ฐ€ Target ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๋™์•ˆ Exception(์˜ˆ์™ธ)์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  2. Proxy ๊ฐ์ฒด๋Š” ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ ํ›„์— After Throwing Advice๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“‚ ์˜ˆ์‹œ ์ฝ”๋“œ:

public class ExceptionLoggingAdvice {
    public void logAfterThrowing(Exception ex) {
        System.out.println("์˜ˆ์™ธ ๋ฐœ์ƒ: " + ex.getMessage());
    }
}

์„ค๋ช…:

  • logAfterThrowing ๋ฉ”์„œ๋“œ๋Š” Target ๋ฉ”์„œ๋“œ์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ํ•ด๋‹น ์˜ˆ์™ธ ์ •๋ณด๋ฅผ ๋กœ๊ทธ๋กœ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”‘ Advice ์„ค์ •:

<aop:aspect id="exceptionAspect" ref="exceptionLoggingAdvice">
    <aop:pointcut id="serviceMethods" expression="execution(* com.example.service..*(..))" />
    <aop:after-throwing method="logAfterThrowing" pointcut-ref="serviceMethods" throwing="ex" />
</aop:aspect>

๐Ÿ” POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - Advice ์ข…๋ฅ˜ (4/5)

๐ŸŒŸ After (Finally) Advice

After Advice๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜๋“ , ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋“  ์ƒ๊ด€์—†์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. Java์˜ finally ๋ธ”๋ก๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ๋™์ž‘ ์ˆœ์„œ:

  1. Client๊ฐ€ Target ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, Proxy ๊ฐ์ฒด๋Š” Target ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  2. Target ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์™„๋ฃŒ๋˜๊ฑฐ๋‚˜ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„, After Advice๋Š” ๋ฌด์กฐ๊ฑด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“‚ ์˜ˆ์‹œ ์ฝ”๋“œ:

public class AfterMethodAdvice {
    public void afterMethod() {
        System.out.println("๋ฉ”์„œ๋“œ ์‹คํ–‰ ํ›„ ๋ฌด์กฐ๊ฑด ์‹คํ–‰๋˜๋Š” ๋กœ์ง");
    }
}

์„ค๋ช…:

  • afterMethod ๋ฉ”์„œ๋“œ๋Š” Target ๋ฉ”์„œ๋“œ์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ์™€ ์ƒ๊ด€์—†์ด ๋ฌด์กฐ๊ฑด ์‹คํ–‰๋˜๋Š” ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”‘ Advice ์„ค์ •:

<aop:aspect id="afterAspect" ref="afterMethodAdvice">
    <aop:pointcut id="serviceMethods" expression="execution(* com.example.service..*(..))" />
    <aop:after method="afterMethod" pointcut-ref="serviceMethods" />
</aop:aspect>

๐Ÿ” POJO ๊ธฐ๋ฐ˜ AOP ๊ตฌํ˜„ - Advice ์ข…๋ฅ˜ (5/5)

๐ŸŒŸ Around Advice

Around Advice๋Š” ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „๊ณผ ํ›„์— ๋ชจ๋‘ ์‹คํ–‰๋˜๋Š” Advice์ž…๋‹ˆ๋‹ค. ProceedingJoinPoint๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ž์ฒด๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“ ๋™์ž‘ ์ˆœ์„œ:

  1. Client๊ฐ€ Target ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, Proxy ๊ฐ์ฒด๋Š” Around Advice๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  2. ProceedingJoinPoint๋ฅผ ์‚ฌ์šฉํ•ด ๋ฉ”์„œ๋“œ ์‹คํ–‰์„ ์ง์ ‘ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
  3. ๋ฉ”์„œ๋“œ ์‹คํ–‰ ํ›„, ๋‹ค์‹œ Around Advice๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“‚ ์˜ˆ์‹œ ์ฝ”๋“œ:

public class TimingAdvice {
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();  // ์‹ค์ œ ๋ฉ”์„œ๋“œ ์‹คํ–‰
        long endTime = System.currentTimeMillis();
        System.out.println("๋ฉ”์„œ๋“œ ์‹คํ–‰ ์‹œ๊ฐ„: " + (endTime - startTime) + "ms");
        return result;
    }
}

์„ค๋ช…:

  • aroundMethod ๋ฉ”์„œ๋“œ๋Š” ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„๋กœ ์‹คํ–‰๋˜๋ฉฐ, ๋ฉ”์„œ๋“œ์˜ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”‘ Advice ์„ค์ •:

<aop:aspect id="timingAspect" ref="timingAdvice">
    <aop:pointcut id="serviceMethods" expression="execution(* com.example.service..*(..))" />
    <aop:around method="aroundMethod" pointcut-ref="serviceMethods" />
</aop:aspect>

๐ŸŒŸ JoinPoint Class ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ ์ƒ์„ธ ์„ค๋ช…


1. JoinPoint Class๋ž€?

JoinPoint๋Š” Spring AOP์—์„œ ์ค‘์š”ํ•œ ๊ฐœ๋…์œผ๋กœ, ๋Œ€์ƒ ๊ฐ์ฒด(Target Object)์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. Aspect๊ฐ€ ์ ์šฉ๋˜๋Š” ๋ฉ”์„œ๋“œ์˜ ์‹คํ–‰ ์‹œ์ ์— ํ•ด๋‹น ๋ฉ”์„œ๋“œ์™€ ๊ด€๋ จ๋œ ๋‹ค์–‘ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด AOP Advice์—์„œ ๋ฉ”์„œ๋“œ ์‹คํ–‰์„ ์ œ์–ดํ•˜๊ฑฐ๋‚˜, ์ •๋ณด๋ฅผ ๋กœ๊น…ํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

JoinPoint๋Š” org.aspectj.lang ํŒจํ‚ค์ง€์— ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ, AOP์—์„œ ์‚ฌ์šฉํ•˜๋Š” Advice ๋ฉ”์„œ๋“œ์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ๊ณผ ๊ด€๋ จ๋œ ์—ฌ๋Ÿฌ ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


2. ์ฃผ์š” ๋ฉ”์„œ๋“œ ์„ค๋ช…

JoinPoint ํด๋ž˜์Šค๋Š” ๋‹ค์–‘ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ๋Œ€์ƒ ๋ฉ”์„œ๋“œ์˜ ์ •๋ณด๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋Šฅ์„ ์•„๋ž˜์—์„œ ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค:


๐Ÿ› ๏ธ Object getTarget()

  • ์„ค๋ช…: JoinPoint๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋Œ€์ƒ ๊ฐ์ฒด(Target Object)๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ์ฒด๋Š” ์‹ค์ œ๋กœ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฐ์ฒด์ด๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ž‘์—…์„ ์ถ”๊ฐ€๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ: ๋งŒ์•ฝ AOP๊ฐ€ ์ ์šฉ๋œ ๋ฉ”์„œ๋“œ๊ฐ€ UserService ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ผ๋ฉด, getTarget() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด UserService ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

๐Ÿ› ๏ธ Object[] getArgs()

  • ์„ค๋ช…: ๋Œ€์ƒ ๋ฉ”์„œ๋“œ๋กœ ์ „๋‹ฌ๋œ ์ธ์ž(Arguments)๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌ๋œ ์ธ์ž ๊ฐ’๋“ค์„ ํ™•์ธํ•˜๊ณ , ๊ทธ ๊ฐ’์„ ์กฐ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋กœ๊น…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํŠน์ง•: ๋งŒ์•ฝ ๋ฉ”์„œ๋“œ์— ์ธ์ž๊ฐ€ ์—†์œผ๋ฉด ๋นˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ: ๋งŒ์•ฝ saveUser(String name, int age)๋ผ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ๋‹ค๋ฉด, getArgs() ๋ฉ”์„œ๋“œ๋Š” ["name", 25]์™€ ๊ฐ™์€ ์ธ์ž ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ› ๏ธ Signature getSignature()

  • ์„ค๋ช…: JoinPoint๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ˜ธ์ถœ๋œ ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„, ๋ฐ˜ํ™˜ ํƒ€์ž…, ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž… ๋“ฑ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ: ๋งŒ์•ฝ UserService ํด๋ž˜์Šค์˜ createUser(String name) ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ๋‹ค๋ฉด, getSignature()๋Š” ํ•ด๋‹น ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„๊ณผ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    • getSignature().getName()์„ ํ˜ธ์ถœํ•˜๋ฉด "createUser"๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

๐Ÿ› ๏ธ String getName()

  • ์„ค๋ช…: JoinPoint๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ์ถ”์ ํ•˜๊ฑฐ๋‚˜ ๋กœ๊น…ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ: getSignature().getName()์„ ํ˜ธ์ถœํ•˜๋ฉด, ๋Œ€์ƒ ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„(์˜ˆ: "createUser")์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ› ๏ธ String toLongString()

  • ์„ค๋ช…: ํ˜ธ์ถœ๋œ ๋ฉ”์„œ๋“œ ์ „์ฒด์˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…, ๋ฉ”์„œ๋“œ ์ด๋ฆ„, ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž… ๋“ฑ์„ ํฌํ•จํ•œ ์ „์ฒด์ ์ธ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ: ๋งŒ์•ฝ ๋ฉ”์„œ๋“œ๊ฐ€ public void createUser(String name)๋ผ๋ฉด, toLongString()์€ public void createUser(String)๊ณผ ๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฉ”์„œ๋“œ์˜ ์ „์ฒด์ ์ธ ๊ตฌ์กฐ๋ฅผ ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ› ๏ธ String toShortString()

  • ์„ค๋ช…: ํ˜ธ์ถœ๋œ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ•์•ฝ๋œ ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฉ”์„œ๋“œ ์ด๋ฆ„๋งŒ ๋ฐ˜ํ™˜๋˜๋ฉฐ, ๋” ๊ฐ„๋‹จํ•œ ๋กœ๊ทธ ์ถœ๋ ฅ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ: ๋งŒ์•ฝ ๋ฉ”์„œ๋“œ๊ฐ€ public void createUser(String name)๋ผ๋ฉด, toShortString()์€ createUser()์ฒ˜๋Ÿผ ์ถ•์•ฝ๋œ ๋ฉ”์„œ๋“œ ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

3. JoinPoint Class์˜ ์ฃผ์š” ํ™œ์šฉ ์˜ˆ์‹œ

AOP์—์„œ JoinPoint๋Š” ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ •๋ณด๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋กœ๊ทธ ๊ธฐ๋ก, ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์‹œ๊ฐ„ ์ธก์ •, ๋ฉ”์„œ๋“œ ์ธ์ž ๊ฐ’ ํ™•์ธ ๋ฐ ๊ฒ€์ฆ ๋“ฑ์˜ ์ž‘์—…์— ๋งค์šฐ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“‚ ์ฝ”๋“œ ์˜ˆ์‹œ:

@Aspect
public class LoggingAspect {

    // Before Advice: ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๊ธฐ ์ „์— ์‹คํ–‰
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „: " + joinPoint.getSignature().getName());
        System.out.println("๋ฉ”์„œ๋“œ ์ธ์ž: " + Arrays.toString(joinPoint.getArgs()));
    }

    // After Returning Advice: ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋œ ํ›„ ์‹คํ–‰
    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("๋ฉ”์„œ๋“œ ์‹คํ–‰ ํ›„: " + joinPoint.getSignature().getName());
        System.out.println("๋ฉ”์„œ๋“œ ๊ฒฐ๊ณผ: " + result);
    }
}

4. ํ™œ์šฉ ์˜ˆ์‹œ ์„ค๋ช…

  • logBefore():
    • ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „, JoinPoint์˜ getSignature()๋ฅผ ์ด์šฉํ•ด ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„์„ ์ถœ๋ ฅํ•˜๊ณ , getArgs()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌ๋œ ์ธ์ž ๊ฐ’์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • logAfterReturning():
    • ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋œ ํ›„, JoinPoint๋ฅผ ํ†ตํ•ด ๋ฉ”์„œ๋“œ ์ด๋ฆ„๊ณผ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๋กœ๊น…ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ JoinPoint๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฉ”์„œ๋“œ ์‹คํ–‰๊ณผ ๊ด€๋ จ๋œ ์—ฌ๋Ÿฌ ์ •๋ณด๋ฅผ ๋‹ค๋ฃจ๊ณ , ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋™์ž‘์„ ์ œ์–ดํ•˜๊ฑฐ๋‚˜ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐ŸŒŸ @Aspect Annotation์„ ์ด์šฉํ•œ AOP ๊ตฌํ˜„ (์ผ๋ฐ˜์ ์ธ ์˜ˆ์‹œ)


1. @Aspect Annotation์„ ์ด์šฉํ•œ AOP ๊ตฌํ˜„ ๊ธฐ๋ณธ ๊ฐœ๋…

1๏ธโƒฃ ์„ค์ • ํŒŒ์ผ์— ๋ฐ˜๋“œ์‹œ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š” ํ•ญ๋ชฉ

Spring์—์„œ @Aspect๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ AOP๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์„ค์ • ํŒŒ์ผ์— ๋‹ค์Œ ํ•ญ๋ชฉ์„ ๋ฐ˜๋“œ์‹œ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

<aop:aspectj-autoproxy />

์ด ์„ค์ •์€ Spring์ด AspectJ ๊ธฐ๋ฐ˜ AOP ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด, AOP ์„ค์ •์ด ์ž๋™์œผ๋กœ ์ ์šฉ๋˜์–ด ๋‹ค์–‘ํ•œ Aspect๊ฐ€ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ Aspect Class๋ฅผ ์œผ๋กœ ๋“ฑ๋ก

Aspect Class๋Š” ๋ฐ˜๋“œ์‹œ Spring์˜ Bean์œผ๋กœ ๋“ฑ๋ก๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Spring์ด ํ•ด๋‹น Aspect๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  Advice๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐ŸŒŸ @Aspect์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ฃผ์š” ์–ด๋…ธํ…Œ์ด์…˜

@Before("pointcut")

  • Before Advice๋ฅผ ์ •์˜ํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น Advice๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

@AfterReturning(pointcut = "", returning = "")

  • After Returning Advice๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์™„๋ฃŒ๋œ ํ›„์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ฐ˜ํ™˜๋œ ๊ฐ’์„ ๋ฐ›์•„ ์ถ”๊ฐ€ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@AfterThrowing(pointcut = "", throwing = "")

  • After Throwing Advice๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@After("pointcut")

  • After Advice๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ ์‹คํ–‰ ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ฉ”์„œ๋“œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜๋“ , ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋“  ์ƒ๊ด€์—†์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

@Around("pointcut")

  • Around Advice๋Š” ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „๊ณผ ํ›„ ๋ชจ๋‘์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„์˜ ์ž‘์—…์„ ์ •์˜ํ•˜๊ฑฐ๋‚˜, ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โš™๏ธ JoinPoint์™€ ProceedingJoinPoint

  • JoinPoint: Before, AfterReturning, AfterThrowing, After์—์„œ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ ์‹คํ–‰์— ๋Œ€ํ•œ ์ •๋ณด(๋ฉ”์„œ๋“œ ์ด๋ฆ„, ์ธ์ž ๊ฐ’ ๋“ฑ)๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ProceedingJoinPoint: Around์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด๋กœ, proceed() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Target ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŒŸ ์ผ๋ฐ˜์ ์ธ ์˜ˆ์‹œ ์„ค๋ช…

์ด์ œ @Aspect์™€ ๋‹ค์–‘ํ•œ ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•œ ์ผ๋ฐ˜์ ์ธ ์˜ˆ์‹œ๋ฅผ ์„ค๋ช…ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ“‚ ์ฝ”๋“œ ์˜ˆ์‹œ:

@Aspect
public class LoggingAspect {

    // Pointcut: ํŠน์ • ๋ฉ”์„œ๋“œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋Š” ์กฐ๊ฑด ์ •์˜
    @Pointcut("execution(public * com.example.service.*.*(..))")
    public void logForServiceMethods() {}

    // Around Advice: ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„์— ์ ์šฉ๋˜๋Š” Advice
    @Around("logForServiceMethods()")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        // ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ ์‹œ์ : ์‹คํ–‰ ์‹œ์ž‘ ์‹œ๊ฐ„ ๊ธฐ๋ก
        long startTime = System.currentTimeMillis();

        System.out.println("๋ฉ”์„œ๋“œ ์‹œ์ž‘: " + joinPoint.getSignature());

        // ์‹ค์ œ ๋ฉ”์„œ๋“œ ์‹คํ–‰
        Object result = joinPoint.proceed();  // Target ๋ฉ”์„œ๋“œ ์‹คํ–‰

        // ๋ฉ”์„œ๋“œ ์‹คํ–‰ ํ›„ ์‹œ์ : ์‹คํ–‰ ์™„๋ฃŒ ์‹œ๊ฐ„ ๊ธฐ๋ก ๋ฐ ์‹คํ–‰ ์‹œ๊ฐ„ ์ถœ๋ ฅ
        long endTime = System.currentTimeMillis();
        System.out.println("๋ฉ”์„œ๋“œ ์ข…๋ฃŒ: " + joinPoint.getSignature());
        System.out.println("์‹คํ–‰ ์‹œ๊ฐ„: " + (endTime - startTime) + "ms");

        return result;
    }
}

์ฝ”๋“œ ์„ค๋ช…:

  1. @Aspect: LoggingAspect ํด๋ž˜์Šค๋Š” AOP Aspect์ž„์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค์—๋Š” Advice์™€ Pointcut์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  2. @Pointcut:

    • "execution(public * com.example.service.*.*(..))"๋Š” Pointcut ํ‘œํ˜„์‹์ž…๋‹ˆ๋‹ค. ์ด๋Š” com.example.service ํŒจํ‚ค์ง€์˜ ๋ชจ๋“  public ๋ฉ”์„œ๋“œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.
    • logForServiceMethods() ๋ฉ”์„œ๋“œ๋Š” ์ด Pointcut์„ ์‹๋ณ„ํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋ฉฐ, ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ Advice๊ฐ€ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.
  3. @Around("logForServiceMethods()"):

    • Around Advice๋Š” Target ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „๊ณผ ํ›„์— ๋ชจ๋‘ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋ฉ”์„œ๋“œ์˜ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๊ณ , ์‹คํ–‰ ์ „๊ณผ ํ›„์— ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
  4. ProceedingJoinPoint:

    • ProceedingJoinPoint ๊ฐ์ฒด๋Š” ๋ฉ”์„œ๋“œ ์‹คํ–‰์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. proceed() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Target ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์ด ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„์— ์›ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฉ”์„œ๋“œ์˜ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋“ฑ ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๐ŸŒŸ Annotation์„ ์ด์šฉํ•œ AOP ๊ตฌํ˜„์˜ ์žฅ์ 

  • ๊ฐ„๊ฒฐํ•˜๊ณ  ์ง๊ด€์ : ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด Aspect๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์–ด, XML ์„ค์ • ์—†์ด๋„ AOP๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์œ ์—ฐ์„ฑ: ๋‹ค์–‘ํ•œ Advice ํƒ€์ž…(์˜ˆ: Before, AfterReturning, AfterThrowing, Around)์„ ํ†ตํ•ด ๋ฉ”์„œ๋“œ์˜ ๋‹ค์–‘ํ•œ ์‹คํ–‰ ์‹œ์ ์—์„œ ์ œ์–ด๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ: ์ฝ”๋“œ ์ž์ฒด์—์„œ ์ง์ ‘์ ์œผ๋กœ AOP ์„ค์ •์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๊ฐ€๋…์„ฑ์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค.
  • ๊ฐ•๋ ฅํ•œ ์ œ์–ด: ProceedingJoinPoint๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”์„œ๋“œ ์‹คํ–‰ ํ๋ฆ„์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด, ๋ฉ”์„œ๋“œ ์‹คํ–‰์„ ์ง€์—ฐ์‹œํ‚ค๊ฑฐ๋‚˜ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€