AOP (Aspect Oriented Programming)

Spring Framework์˜ ํ•ต์‹ฌ ๊ฐœ๋… 3๊ฐ€์ง€

์†Œ์Šค ์ฝ”๋“œ์˜ ๋ณต์žก๋„๋ฅผ ์ค„์ด๊ณ , ํšจ์œจ์„ ๋†’์ด๊ณ , ์œ ์ง€๋ณด์ˆ˜๋ฅผ ์šฉ์ดํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด Spring์—์„œ๋Š” ๋‹ค์Œ์˜ 3๊ฐ€์ง€๋ฅผ ์ด์šฉํ•œ๋‹ค.

  1. AOP

AOP์˜ ์ •์˜

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

ํ•œ ๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€์—๋Š” ๋‹ค์–‘ํ•œ ๊ด€์‹ฌ์‚ฌ(Concern)๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ, AOP๋ฅผ ์ด์šฉํ•˜๋ฉด ์ด ๊ด€์‹ฌ์‚ฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์„ธ๋กœ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๋‹ค๋ฃจ๊ฒŒ ๋œ๋‹ค.

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

๋”ฐ๋ผ์„œ, ์ด๋ ‡๊ฒŒ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•ด์„œ ๋‹ค๋ฃจ๋ฉด ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

AOP ์šฉ์–ด

  • Aspect: Concern์„ ๋ชจ๋“ˆํ™”ํ•œ ๊ฒƒ์œผ๋กœ, ์ฃผ๋กœ ๊ณตํ†ต ๋กœ์ง์ธ ๊ด€์‹ฌ์‚ฌ 1๊ณผ 3์ด ์ด์— ํ•ด๋‹นํ•œ๋‹ค.

  • Advice: Aspect ๋‚ด ๋ฉ”์†Œ๋“œ๋“ค์„ ์ผ์ปซ๋Š” ์šฉ์–ด๋กœ, ์‹ค์ œ ๋กœ์ง์— ํ•ด๋‹น

  • JoinPoint: Advice๋ฅผ ์ ์šฉํ•  ์œ„์น˜

  • PointCut: ํŠน์ • ๋ฉ”์†Œ๋“œ์—๋งŒ Advice๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋งํ•จ

  • Target: Aspect๋ฅผ ์ ์šฉํ•  ํด๋ž˜์Šค, ๋ฉ”์†Œ๋“œ ๋“ฑ์„ ๋งํ•œ๋‹ค.

AOP in Spring

IoC ์ปจํ…Œ์ด๋„ˆ ๋‚ด์—์„œ Bean์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. ํ•ด๋‹น Bean์€ ํ”„๋ก์‹œ ๊ฐ์ฒด๋กœ, ๋Ÿฐํƒ€์ž„ ์‹œ์ ์— ์ƒ์„ฑ๋˜์–ด ์‚ฌ์šฉ๋œ๋‹ค.

AOP๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” @Aspect๋ฅผ ๋ถ™์ธ ํด๋ž˜์Šค์— Advice๋ฅผ ์ •์˜ํ•œ ๋’ค Advice์˜ ์ง€์ • ์‹œ์ (์ „, ํ›„, ์ „/ํ›„)์„ ์ •ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

@Aspect, @Pointcut, @Around

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
public class ExpTimeAspect {

    @Pointcut("execution(* ์ตœ์ƒ์œ„ํŒจํ‚ค์ง€๋ช…..*(..))")
    private void publicTarget() {
    }

    @Around("publicTarget()")
    public Object measure(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            return joinPoint.proceed(); // ์‹ค์ œ ๋กœ์ง ์‹คํ–‰
        } finally {
            long finish = System.currentTimeMillis();
            Signature signature = joinPoint.getSignature();
            System.out.printf("%s.%s(%s) ์‹คํ–‰ ์‹œ๊ฐ„: %d\n",
                    joinPoint.getTarget().getClass().getSimpleName(),
                    signature.getName(),
                    Arrays.toString(joinPoint.getArgs()),
                    (finish - start));
        }
    }

}
  • AOP๋„ Bean์œผ๋กœ ๋“ฑ๋ก๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ @Component ์–ด๋…ธํ…Œ์ด์…˜์ด ์‚ฌ์šฉ๋˜์—ˆ๋‹ค. @Pointcut์„ ํ†ตํ•ด ํŠน์ • Advice๊ฐ€ ์‚ฌ์šฉ๋  ํŒจํ‚ค์ง€ ๋ฒ”์œ„, ํŒŒ๋ผ๋ฏธํ„ฐ ๋“ฑ์„ ์„ค์ •ํ•œ๋‹ค.

  • ์ง€์ • ๋ฒ”์œ„, ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒฝ์šฐ Pointcut์œผ๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹จ ํ•œ ๋ฒˆ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ @Around ๋‚ด์— ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•ด๋„ ๋œ๋‹ค.

    • Pointcut๋งŒ ๋”ฐ๋กœ ๋ชจ์•„๋‘” common aspect๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๋„ ํšจ์œจ์ ์ด๋‹ค.

@Order

AOP๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ์ ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ๋ฉ”์ธ ๋กœ์ง์˜ ์‹คํ–‰ ์ „ํ›„๋กœ ์—ฌ๋Ÿฌ ํ”„๋ก์‹œ๋ฅผ ๊ฑฐ์น  ์ˆ˜ ์žˆ๋‹ค.

์ด ํ”„๋ก์‹œ๋“ค ๊ฐ„์— ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ๋˜์–ด์•ผ ํ•œ๋‹ค๋ฉด @Order ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

@Aspect
@Order(1)

@Aspect
@Order(2)

Last updated