๐Ÿงต AOP์™€ Spring AOP ์ •๋ฆฌ ๋…ธํŠธ

๋„๋‘๋งจยท2025๋…„ 6์›” 13์ผ

๊ณต๋ถ€

๋ชฉ๋ก ๋ณด๊ธฐ
16/23

๋ฐฐํ‚ค์˜ AOP์™€ Spring AOP ๊ฐ•์˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.


๐Ÿงญ AOP๋ž€?

AOP (Aspect-Oriented Programming)
โ†’ ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ๋ฅผ ํ—ˆ์šฉํ•จ์œผ๋กœ์จ ๋ชจ๋“ˆ์„ฑ์„ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„์ž…๋‹ˆ๋‹ค.

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

๐ŸŽฏ ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ(Cross-Cutting Concern)๋ž€?

์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ํ•„์š”ํ•˜์ง€๋งŒ ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ๋Š” ๊ฑฐ๋ฆฌ๊ฐ€ ๋จผ ๊ธฐ๋Šฅ๋“ค

์˜ˆ์‹œ:

  • โœ… ๋กœ๊น…
  • โœ… ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ
  • โœ… ๋ณด์•ˆ ์ธ์ฆ

๐Ÿ’ก AOP๋ฅผ ๋„์ž…ํ•œ ์ด์œ 

  • ์ค‘๋ณต ๋กœ์ง์ด ๋งŽ์„ ๊ฒฝ์šฐ ๋ณ€๊ฒฝ ์‹œ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›€
  • ํ•ต์‹ฌ ๊ด€์‹ฌ์‚ฌ์™€ ๋ถ„๋ฆฌํ•˜์—ฌ ๋ณ€๊ฒฝ ์ง€์ ์„ ํ•˜๋‚˜๋กœ ๋ชจ๋“ˆํ™” ๊ฐ€๋Šฅ

๐Ÿ“š AOP ํ•ต์‹ฌ ์šฉ์–ด

์šฉ์–ด์„ค๋ช…
Aspect๋ถ€๊ฐ€ ๊ธฐ๋Šฅ(Advice) + ์ ์šฉ ์œ„์น˜(Pointcut)์˜ ์กฐํ•ฉ
Advice๋ถ€๊ฐ€๊ธฐ๋Šฅ์„ ์ •์˜ํ•œ ์ฝ”๋“œ (ex: ๋กœ๊น…)
Pointcut์–ด๋–ค JoinPoint์— Advice๋ฅผ ์ ์šฉํ• ์ง€ ์ •์˜
JoinPointAdvice๊ฐ€ ์ ์šฉ ๊ฐ€๋Šฅํ•œ ์ง€์  (ex: ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ)
WeavingAdvice๋ฅผ ํ•ต์‹ฌ ๋กœ์ง์— ์ ์šฉํ•˜๋Š” ๊ณผ์ •

๐Ÿ› ๏ธ AOP ์ ์šฉ ํ”„๋ ˆ์ž„์›Œํฌ

ํ”„๋ ˆ์ž„์›Œํฌ์„ค๋ช…
AspectJ์ž๋ฐ”์— AOP ์ ์šฉ, ์ปดํŒŒ์ผ ์‹œ์ /ํด๋ž˜์Šค ๋กœ๋”ฉ ์‹œ์ /๋Ÿฐํƒ€์ž„ ์ง€์›
Spring AOP์Šคํ”„๋ง์—์„œ ์ œ๊ณตํ•˜๋Š” AOP ๊ตฌํ˜„ (๋Ÿฐํƒ€์ž„ ๊ธฐ๋ฐ˜, ํ”„๋ก์‹œ ์‚ฌ์šฉ)

๐Ÿ’ป ์˜ˆ์ œ: ๋กœ๊น… ๊ธฐ๋Šฅ ๋ถ„๋ฆฌ

Before: ์ค‘๋ณต ์ฝ”๋“œ ์กด์žฌ

@Slf4j
public class HelloService {
  public void printA() {
    long startTime = System.currentTimeMillis();
    for (int i = 0; i < 1000; i++) {
      System.out.println("hello A");
    }
    long endTime = System.currentTimeMillis();
    log.info("์ด ๊ฑธ๋ฆฐ ์‹œ๊ฐ„: {}ms", endTime - startTime);
  }

  public void printB() {
    long startTime = System.currentTimeMillis();
    for (int i = 0; i < 10000; i++) {
      System.out.println("hello B");
    }
    long endTime = System.currentTimeMillis();
    log.info("์ด ๊ฑธ๋ฆฐ ์‹œ๊ฐ„: {}ms", endTime - startTime);
  }
}

After: AOP๋กœ ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ

@Slf4j
@Aspect
public class LoggingAspect {
  @Around("execution(* hello.proxy.aop..print*(..))")
  public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable {
    long startTime = System.currentTimeMillis();
    joinPoint.proceed(); // ํ•ต์‹ฌ ๋กœ์ง ์‹คํ–‰
    long endTime = System.currentTimeMillis();
    log.info("์ด ๊ฑธ๋ฆฐ ์‹œ๊ฐ„: {}ms", endTime - startTime);
    return result;
  }
}

๐Ÿงฌ Spring AOP์˜ ๋™์ž‘ ์›๋ฆฌ

๐Ÿ“Œ ์œ„๋น™(Weaving)

  • Advice๋ฅผ ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์—ฐ๊ฒฐํ•˜๋Š” ์ž‘์—…
  • Spring AOP๋Š” ๋Ÿฐํƒ€์ž„ ์‹œ์ ์— ์ˆ˜ํ–‰ (ํ”„๋ก์‹œ ๊ธฐ๋ฐ˜)

๐ŸŒฑ AOP ์ ์šฉ ์ „ ๋นˆ ๋“ฑ๋ก ๊ณผ์ •

AOP ์ „

๐ŸŒฟ AOP ์ ์šฉ ํ›„ ๋นˆ ๋“ฑ๋ก ๊ณผ์ •

AOP ํ›„

๐Ÿ”ง BeanPostProcessor์—์„œ ํ”„๋ก์‹œ ์ƒ์„ฑ

๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ

  • ์ด์ „๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋นˆ์„ ์ƒ์„ฑํ•ด์„œ ๋นˆ์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ proxy๋ฅผ ์ƒ์„ฑํ•ด๊ฐ€์ง€๊ณ  proxy๋ฅผ ๋นˆ ๊ฐ์ฒด๋กœ ์ €์žฅํ•จ

๐Ÿ“Œ ์ •๋ฆฌ

  • AOP๋ž€?
    ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ๋ชจ๋“ˆ์„ฑ์„ ๋†’์ด๊ณ  ์ค‘๋ณต์„ ์ค„์ด๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„

  • Spring AOP๋ž€?
    Spring์—์„œ AOP๋ฅผ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ. ๋Ÿฐํƒ€์ž„์— ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํ•ต์‹ฌ ๊ธฐ๋Šฅ๊ณผ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์—ฐ๊ฒฐ

  • ์‚ฌ์šฉ ๋ชฉ์ 
    ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ, ์ฝ”๋“œ ๊ด€๋ฆฌ ์šฉ์ด์„ฑ, ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ

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