ํ’€์Šคํƒ ์›น๐ŸŒ ๊ฐœ๋ฐœ์ž ์ง€๋ง์ƒ ๐Ÿง‘๐Ÿฝโ€๐Ÿ’ป
โž• ์ธ๊ณต์ง€๋Šฅ ๊ด€์‹ฌ ๐Ÿค–


Categories


Recent views

  • 1
  • 2
  • 3
  • 4
  • 5

Spring5 ์ž…๋ฌธ-AOP

  1. ํ”„๋ก์‹œ ํŒจํ„ด
  2. AOP ๊ตฌํ˜„

AOP(Aspect Oriented Programming)

๐Ÿ—ฃ๏ธ ์ถœ์ฒ˜

_ ์ดˆ๋ณด ์›น ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ์Šคํ”„๋ง 5 ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ž…๋ฌธ _์™€ ์Šคํ”„๋ง ์ธ ์•ก์…˜ ์˜ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

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

์ด๋•Œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ๊ณผ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ๊ตฌ๋ถ„ํ•ด ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํ”„๋ก์‹œ ํŒจํ„ด์„ ์ด์šฉํ•˜๋ฉฐ, ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ์„ธ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‚˜๋‰œ๋‹ค.

  • ์ปดํŒŒ์ผ ์‹œ์ ์— ์ฝ”๋“œ์— ๊ณตํ†ต ๊ธฐ๋Šฅ ์‚ฝ์ž… -> AspectJ ๊ฐ™์€ AOP ์ „์šฉ ๋„๊ตฌ๋กœ ๊ตฌํ˜„
  • ํด๋ž˜์Šค ๋กœ๋”ฉ ์‹œ์ ์— ๋ฐ”์ดํŠธ ์ฝ”๋“œ์— ๊ณตํ†ต ๊ธฐ๋Šฅ ์‚ฝ์ž… -> AspectJ ๊ฐ™์€ AOP ์ „์šฉ ๋„๊ตฌ๋กœ ๊ตฌํ˜„
  • ๋Ÿฐํƒ€์ž„์— ํ”„๋ก์‹œ ๊ฐ์ฒด ์ƒ์„ฑํ•ด ๊ณตํ†ต ๊ธฐ๋Šฅ ์‚ฝ์ž… -> ์Šคํ”„๋ง์˜ ์ž๋™ ์ƒ์„ฑ ํ”„๋ก์‹œ ๊ฐ์ฒด๋กœ ๊ตฌํ˜„
โ„น๏ธ ํ”„๋ก์‹œ ๊ธฐ๋ฐ˜ AOP

์šฐ๋ฆฐ ์ด ์ค‘์— 3๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณผ ๊ฒƒ์ด๋‹ค.

ํ”„๋ก์‹œ ํŒจํ„ด

์•„๋ž˜ ์˜ˆ์‹œ ์ฝ”๋“œ์™€ ๊ฐ™์ด ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ ์‹คํ–‰์€ ๋‹ค๋ฅธ ๊ฐ์ฒด์— ์œ„์ž„ํ•˜๊ณ  ๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ํ”„๋ก์‹œ(Proxy)๋ผ๊ณ  ํ•˜๋ฉฐ, ์‹ค์ œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•˜๋Š” ๊ฐ์ฒด๋Š” ๋Œ€์ƒ ๊ฐ์ฒด๋ผ๊ณ  ํ•œ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ๊ณตํ†ต ๊ธฐ๋Šฅ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ณ  ์ˆ˜์ •ํ•˜๊ธฐ ์‰ฌ์šฐ๋ฉฐ ๊ฐ€๋…์„ฑ ์ข‹์€ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

โž• ์‚ฌ์‹ค์€, ์ €์ž๊ฐ€ ์ƒ๊ฐํ•˜๊ธฐ์—๋Š” ๊ธฐ๋Šฅ ์ถ”๊ฐ€์™€ ํ™•์žฅ์— ์ดˆ์ ์ด ๋งž์ถฐ์ ธ ์žˆ๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด์ด ์ข€ ๋” ๊ฐ€๊น๋‹ค๊ณ  ํ•œ๋‹ค. ํ”„๋ก์‹œ ํŒจํ„ด์€ ์ข€ ๋” ์ ‘๊ทผ ์ œ์–ด์™€ ๋ณด์•ˆ์— ๊ด€๋ จ๋จ

ํ”„๋ก์‹œ ํŒจํ„ด ์˜ˆ์‹œ

๐Ÿงพ๏ธ ํ”„๋ก์‹œ ๊ฐ์ฒด์™€ ๋Œ€์ƒ ๊ฐ์ฒด ์˜ˆ์‹œ
public interface Printer {
	public String print(String words);
}

public class TargetObject implements Printer{
	@Override	
	public String print(String words) {	
		System.out.printf("TargetObject.print()");
		return result;	
	}
}

public class ProxyObject implements Printer {	
	private Printer delegate;	
	public ProxyObject(Printer delegate) {
		this.delegate = delegate;
	}
	@Override
	public String print(String words) {	
		System.out.printf("Before TargetObject.print()");	
		String result = delegate.print(words);
		System.out.printf("After TargetObject.print()");		
		return result;
	}
}
๐Ÿงพ๏ธ ํ”„๋ก์‹œ ํŒจํ„ด ์˜ˆ์‹œ
public class MainProxy {
	public static void main(String[] args) {
		ProxyObject proxy = new ProxyObject(new TargetObject());
		System.out.println("%s", proxy.print("result"));
	}
}
/* console:
Before TargetObject.print()
TargetObject.print()
After TargetObject.print()
result
*/

AOP ๊ตฌํ˜„

์Šคํ”„๋ง์˜ aspectjweaver ์˜์กด์„ ์ถ”๊ฐ€ํ•˜๋ฉด AOP๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์Šคํ”„๋ง AOP๋Š” ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด ์ฃผ๋ฉฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์šฉ์–ด๊ฐ€ ์กด์žฌํ•œ๋‹ค.

  • Aspect : ๊ณตํ†ต์œผ๋กœ ์ ์šฉํ•  ๊ธฐ๋Šฅ, ๋ฉ”์„œ๋“œ, ์˜ˆ์‹œ๋กœ ํŠธ๋žœ์žญ์…˜, ๋ณด์•ˆ, ์บ์‹œ, ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง ๋“ฑ์ด ์žˆ์Œ
  • Advice : Aspect์„ ์ ์šฉํ•  ์‹œ์ , ๋ฉ”์„œ๋“œ ์ „(Before), ํ›„(After), ์ •์ƒ ์ž‘๋™ ํ›„(After Returning), ์˜ค๋ฅ˜ ํ›„(After Throwing) ๋“ฑ์ด ์กด์žฌํ•˜์ง€๋งŒ ๋ชจ๋“  ์‹œ์ ์— ์ž์œ ๋กญ๊ฒŒ ์ ์šฉ๊ฐ€๋Šฅํ•œ Around Adivce๋ฅผ ๊ฐ€์žฅ ์ž์ฃผ ์‚ฌ์šฉํ•œ๋‹ค.
  • Joinpoint: Advice๋ฅผ ์ ์šฉ ๊ฐ€๋Šฅํ•œ ๋ถ€๋ถ„, ๋ฉ”์„œ๋“œ, ํ•„๋“œ ๊ฐ’ ๋ณ€๊ฒฝ ๋“ฑ์ด ์กด์žฌํ•˜์ง€๋งŒ ์Šคํ”„๋ง์€ ๋ฉ”์„œ๋“œ์—๋งŒ ์ ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • Pointcut: ํ•ด๋‹น ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ ์šฉํ•  ํด๋ž˜์Šค, ๋นˆ ๊ฐ์ฒด ๋“ฑ์˜ ๋ฒ”์œ„๋ฅผ ์ง€์ •
  • Weaving: ์ด๋Ÿฌํ•œ AOP๋ฅผ ํŠน์ • ๊ฐ์ฒด์— ์„ค์ •ํ•ด์ฃผ๋Š” ํ–‰์œ„๋ฅผ ์˜๋ฏธ

Aspect ํด๋ž˜์Šค ๊ตฌํ˜„

์Šคํ”„๋ง AOP์—์„œ ๊ฐ€์žฅ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” Around Advice๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค.

  1. Aspect๋กœ ์‚ฌ์šฉํ•  ํด๋ž˜์Šค์— @Aspect ์–ด๋…ธํ…Œ์ด์…˜ ์ ์šฉ
  2. @Pointcut ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ๊ฐ์ฒด๋ฅผ ์ง€์ •
  3. ๊ณตํ†ต ๊ธฐ๋Šฅ ๊ตฌํ˜„ ๋ฉ”์„œ๋“œ์— @Around ์–ด๋…ธํ…Œ์ด์…˜ ์ ์šฉํ•˜์—ฌ ๋Œ€์ƒ ๋ฉ”์„œ๋“œ ์ „ํ›„ ์‹คํ–‰์— ๊ด€๋ จํ•œ ๋กœ์ง ์ž‘์„ฑ
๐Ÿงพ๏ธ Aspect ํด๋ž˜์Šค ๊ตฌํ˜„
package aspect; 
import java.util.Arrays;

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.core.annotation.Order;

@Aspect //ํ”„๋ก์‹œ ๊ฐ์ฒด ๊ตฌํ˜„์„ ์œ„ํ•œ Aspect ๊ฐ์ฒด๋กœ ์ง€์ •
@Order(1) // ์—ฌ๋Ÿฌ AOP ์ ์šฉ์‹œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ์Œ€ ์šฐ์„ ์ˆœ์œ„, ๋‚ฎ์„์ˆ˜๋ก ๋จผ์ € ๊ฐ์‹ผ๋‹ค.
public class ExeTimeAspect {
    @Pointcut("execution(public * chap07..*(..))") // chap07 ํŒจํ‚ค์ง€ ๋‚ด์˜ ๋ชจ๋“  ํผ๋ธ”๋ฆญ ๋ฉ”์„œ๋“œ๋“ค์ด ๋Œ€์ƒ
    private void publicTarget() {
    }
    @Around("publicTarget()") // ์•„๋ž˜ Around Adivce ๊ธฐ๋Šฅ์€ publicTarget์—์„œ ์„ค์ •ํ•œ ๋ฒ”์œ„์—๋งŒ ์ ์šฉ๋œ๋‹ค.
    public Object measure(ProceedingJoinPoint joinPoint) throws Throwable { // ๊ณตํ†ต ๊ธฐ๋Šฅ ๊ตฌํ˜„ ๋ฉ”์„œ๋“œ, ๋ฆฌํ„ด ํƒ€์ž…์€ ๋ชจ๋“  ๊ฐ’์„ ์•„์šฐ๋ฅผ ์ˆ˜ ์žˆ๊ฒŒ ์›์‹œ ํƒ€์ž…์ธ Object
        long start = System.nanoTime();
        try {
            Object result = joinPoint.proceed(); // ์ ์šฉ ๋Œ€์ƒ ๋ฉ”์„œ๋“œ ์‹คํ–‰, ProceedingJoinPoint์— ๋Œ€ํ•ด์„œ ์•„๋ž˜ ์ชฝ์— ์„ค๋ช…
            return result;
        } finally {
            long finish = System.nanoTime();
            Signature sig = joinPoint.getSignature();
            System.out.printf("%s.%s(%s) ์‹คํ–‰ ์‹œ๊ฐ„ : %d ns\n",
                    joinPoint.getTarget().getClass().getSimpleName(), // ์ ์šฉ ๋Œ€์ƒ ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ์ •๋ณด
                    sig.getName(), Arrays.toString(joinPoint.getArgs()),
                    (finish - start));
        }
    }
}
โž• execution ๋ช…์‹œ์ž

pointcut ๋ฉ”์„œ๋“œ ์„ค์ •์„ ์œ„ํ•œ ๋ฒ”์œ„ ์ง€์ •์„ ์œ„ํ•ด ์‚ฌ์šฉ๋จ

@Around ์–ด๋…ธํ…Œ์ด์…˜ ์•ˆ์— ์ง์ ‘ ๋ช…์‹œํ•ด๋„ ๋ฒ”์œ„๊ฐ€ ์ง€์ •๋˜์ง€๋งŒ, ์œ„ ์˜ˆ์‹œ์™€ ๊ฐ™์ด PublicTarget() ์ฒ˜๋Ÿผ @Pointcut ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋‹ค๋ฅธ ํŒจํ‚ค์ง€์—์„œ ์ž„ํฌํŠธํ•˜๊ฑฐ๋‚˜ @Around("ํŒจํ‚ค์ง€๋ช….Aspect๊ฐ์ฒด.publicTarget()")์ฒ˜๋Ÿผ ์žฌํ™œ์šฉ ๊ฐ€๋Šฅ

execution(์ˆ˜์‹์–ดํŒจํ„ด? ๋ฆฌํ„ดํƒ€์ž…ํŒจํ„ด ํด๋ž˜์Šค์ด๋ฆ„ํŒจํ„ด?๋ฉ”์„œ๋“œ์ด๋ฆ„ํŒจํ„ด(ํŒŒ๋ผ๋ฏธํ„ฐํŒจํ„ด))
*: ๋ชจ๋“  ๊ฐ’
.. : 0๊ฐœ ์ด์ƒ
โž• ProceedingJoinPoint ๊ฐ์ฒด์˜ ์ธํ„ฐํŽ˜์ด์Šค
  • proceed(): ์ง€์ • ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ์‹œ์ ์„ ์˜๋ฏธ, ๋ฉ”์„œ๋“œ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฆฌํ„ดํ•˜๋ฉฐ, ์ด๋ฅผ ๋‹ค์‹œ ๋ฆฌํ„ดํ•ด์ค˜์•ผ ํ•จ.
  • getSignature(): ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ๊ฐ์ฒด
    • ๋ฆฌํ„ด ๊ฐ’์ธ Signature ๊ฐ์ฒด๋กœ ๋ถ€ํ„ฐ ๋ฉ”์„œ๋“œ๋ช…(getName()), ์‹œ๊ทธ๋‹ˆ์ฒ˜ ์ •๋ณด(toLongString()) ๋“ฑ์„ ๊ตฌํ•จ
  • getTarget(): ๋Œ€์ƒ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค
  • getArgs(): ๋Œ€์ƒ ๋ฉ”์„œ๋“œ ํŒŒ๋ฆฌ๋ฏธํ„ฐ

Aspect ํด๋ž˜์Šค ์ ์šฉ

์ดํ›„ ์™„์„ฑํ•œ ํด๋ž˜์Šค๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑ ํด๋ž˜์Šค์— ๋“ฑ๋กํ•˜๋ฉด ์ ์šฉ๋œ๋‹ค.

๐Ÿงพ๏ธ AppCtx ๊ตฌ์„ฑ ํด๋ž˜์Šค ์˜ˆ์‹œ
//...
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy // ํ•„์ˆ˜ Enable๋ฅ˜ ์–ด๋…ธํ…Œ์ด์…˜, AOP ๊ฐ์ฒด ์‚ฌ์šฉ์„ ์œ„ํ•œ ์„ค์ • ๋นˆ ๊ฐ์ฒด๋“ค์„ ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•ด์คŒ
public class AppCtx {
    @Bean
    public ExeTimeAspect exeTimeAspect() { // ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  Aspect
        return new ExeTimeAspect();
    }

	@Bean
	public Calculator calculator() {
		return new RecCalculator();
	}
//...

์ดํ›„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋นˆ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์™€ ํด๋ž˜์Šค๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด ์ž๋™ ์ƒ์„ฑ๋œ ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿงพ๏ธ AOP ๋Œ€์ƒ์ด ๋œ ๋นˆ ๊ฐ์ฒด ์‹คํ–‰์˜ˆ
Calculator cal = ctx.getBean("calculator", Calculator.class); 
long fiveFact = cal.factorial(5);
System.out.println("cal.factorial(5) = " + fiveFact);
System.out.println(cal.getClass().getName()); // com.sum.proxy.%Proxy17 => RecCalculator ํด๋ž˜์Šค๊ฐ€ ์•„๋‹ˆ๋ผ ์ž๋™ ์ƒ์„ฑ๋œ ํ”„๋ก์‹œ ๊ฐ์ฒด
ctx.close();
/* console:
RecCalculator.factorial([5]) ์‹คํ–‰ ์‹œ๊ฐ„: 50201 ns
cal.factorial(5)=120
com.sum.proxy.%Proxy17
*/

์ด๋•Œ %Proxy17์˜ ํƒ€์ž…์€ ๋ฉ”์„œ๋“œ์˜ ๋ฆฌํ„ด ํƒ€์ž…์ธ Calculator๋ฅผ ์ƒ์†๋ฐ›์•„ ์ƒ์„ฑ๋จ

โž• ๋งŒ์•ฝ ์›๋ณธ ํด๋ž˜์Šค์ธ RecCalculator ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด

์–ด๋…ธํ…Œ์ด์…˜ @EnableAspectJAutoProxy(proxyTargetClass = true)๋กœ ์„ค์ •ํ•˜๋ฉด ๋ฉ”์„œ๋“œ ๋ฆฌํ„ดํƒ€์ž…์ด ์•„๋‹Œ, ์‹ค์ œ ๊ฒฐ๊ณผ๊ฐ’์˜ ํƒ€์ž…์œผ๋กœ ์„ค์ •๋œ๋‹ค.