DevPoong 2022. 7. 2. 13:16

AOP(Aspect Oriented Programming)

1. AOP๊ฐ€ ํ•„์š”ํ•œ Example

public Long join(Member member){

    long start = System.currentTimeMillis();

    try{
        //๊ฐ™์€ ์ด๋ฆ„์ด ์žˆ๋Š” ์ค‘๋ณต ํšŒ์›X ๋ผ๊ณ  ๊ฐ€์ •
        validateDuplicateMember(member); //์ค‘๋ณต ํšŒ์› ๊ฒ€์ฆ

        memberRepository.save(member);
        return member.getId();
    }finally {
        long finish = System.currentTimeMillis();
        long timeMs = finish - start;
        System.out.println("join = " + timeMs + "ms");
    }

}

๋งŒ์•ฝ ์œ„์™€ ๊ฐ™์ด ํšŒ์›๊ฐ€์ž…, ํšŒ์›์กฐํšŒ ๋“ฑ๋“ฑ ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ์—์„œ ์‹œ๊ฐ„ ์ธก์ •์„ ํ•ด์•ผํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์‹œ๊ฐ„ ์ธก์ • ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.

 

๋ฌธ์ œ์ 

1. ํšŒ์›๊ฐ€์ž…, ์กฐํšŒ ๋“ฑ์˜ ๊ธฐ๋Šฅ์—์„œ ์‹œ๊ฐ„ ์ธก์ •์€ ํ•ต์‹ฌ ๊ด€์‹ฌ์‚ฌํ•ญ X

2. ์‹œ๊ฐ„ ์ธก์ • ๋กœ์ง์€ ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญO

3. ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง์— ์‹œ๊ฐ„ ์ธก์ • ๋กœ์ง์ด ์„ž์—ฌ์„œ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›€.

4. ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง์„ ๋”ฐ๋กœ ๋นผ์„œ ๊ณตํ†ต ๋กœ์ง์œผ๋กœ ๋งŒ๋“ค๊ธฐ๋Š” ์–ด๋ ค์›€.

5. ๋งŒ์•ฝ ์‹œ๊ฐ„์ธก์ • ๋กœ์ง์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋ฉด ํ•˜๋‚˜์”ฉ ๋‹ค ์ฐพ์•„๊ฐ€๋ฉด์„œ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ๋”์ฐํ•œ ์ƒํ™ฉ์ด ๋ฒŒ์–ด์ง.


2. ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ vs ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ์˜ ๋ถ„๋ฆฌ

  • ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ(cross-cutting concern)
  • ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ(core concern)

๊ณตํ†ต๊ด€์‹ฌ์‚ฌํ•ญ์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์ ์šฉ

  • ์Šคํ”„๋ง์—์„œ๋Š” ์œ„์™€ ๊ฐ™์ด ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์„ ์ ์šฉ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ธฐ์ˆ ์„ ์ง€์›ํ•œ๋‹ค.

3. AOP ์‚ฌ์šฉํ•˜์—ฌ ๋ถ„๋ฆฌ ํ•ด๋ณด์ž!

(1) aop / TimeTraceAop.java

@Aspect
public class TimeTraceAop {

    @Around("execution(* hello.hellospring..*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable{
        long start = System.currentTimeMillis();
        System.out.println("START: " + joinPoint.toString());
        try{
            return joinPoint.proceed(); //๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰
        }finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");
        }
    }
}

@Aspect๋ฅผ ๋ถ™์—ฌ์ค˜์•ผ AOP๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

@Around๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์ ์šฉํ•  ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

(2) SpringConfig.java

@Configuration
public class SpringConfig {

    private final MemberRepository memberRepository;

    @Autowired
    public SpringConfig(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }


    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository);
    }

    @Bean
    public TimeTraceAop timeTraceAop(){
        return new TimeTraceAop();
    }
}

AOPํด๋ž˜์Šค๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•ด์ค˜์•ผ ํ•จ.

Component Scan๋ฐฉ์‹์„ ์จ๋„ ๋˜์ง€๋งŒ ํŠน๋ณ„ํ•œ ํด๋ž˜์Šค ์ด๋ฏ€๋กœ ์ง์ ‘ Bean์œผ๋กœ ๋“ฑ๋กํ•ด์ฃผ๋Š”๊ฒŒ ์ข‹๋‹ค.

ํšŒ์›๋ชฉ๋ก์„ ํด๋ฆญํ•˜์—ฌ ์š”์ฒญ์„ ๋ณด๋‚ด๋ณด๋ฉด ์œ„์™€ ๊ฐ™์ด

Controller, Service, Repository ์ˆœ์œผ๋กœ ์‹œ์ž‘๋˜๊ณ  ์—ญ์œผ๋กœ ์ข…๋ฃŒ๋˜๊ณ  ์‹œ๊ฐ„ ์ธก์ •์ด ๋œ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

๊ฒฐ๊ณผ

  • ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง์„ ๋ณ„๋„์˜ ๊ณตํ†ต ๋กœ์ง์œผ๋กœ ๋งŒ๋“ค์–ด ํ•ต์‹ฌ ๊ด€์‹ฌ์‚ฌํ•ญ๊ณผ ๊ณตํ†ต ๊ด€์‹ฌ์‚ฌํ•ญ์„ ๋ถ„๋ฆฌํ•˜์˜€๋‹ค.
  • ๋ณ€๊ฒฝํ•˜๊ธฐ ํŽธํ•˜์—ฌ ์œ ์ง€๋ณด์ˆ˜์— ์šฉ์ดํ•˜๋‹ค.
  • AOP๋ฅผ ์ ์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ๋Œ€์ƒ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค.


4. AOP ๋‚ด๋ถ€ ๋™์ž‘ ์›๋ฆฌ

(1) AOP ์ ์šฉ ์ „ ์˜์กด๊ด€๊ณ„

 

(2) AOP ์ ์šฉ ํ›„ ์˜์กด๊ด€๊ณ„

์Šคํ”„๋ง์ด ์ปจํ…Œ์ด๋„ˆ์— ๋นˆ์„ ๋“ฑ๋กํ•  ๋•Œ ์ง„์งœ Spring Bean๋ง๊ณ  Proxy(๋Œ€๋ฆฌ, ๊ฐ€์งœ) Spring Bean์„ ์ง„์งœ ์•ž์— ๋“ฑ๋กํ•ด์ค€๋‹ค. jointPoint๋กœ ์–ด๋–ค ์‹คํ–‰์ด ๋ฐœ์ƒํ•˜๋ฉด ๊ทธ๋•Œ ์ง„์งœ Bean์„ ํ˜ธ์ถœ ํ•ด์ค€๋‹ค.

์‹ค์ œ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ @Autowired๋กœ Service๋ฅผ ์ž๋™ ์ฃผ์ž…๋ฐ›์„ ๋•Œ service.getClass()๋ฅผ ํ†ตํ•ด ์–ด๋–ค ํด๋ž˜์Šค๊ฐ€ ์ฃผ์ž…๋˜์—ˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•ด๋ณผ ๋•Œ ๊ทธ๋ƒฅ MemberService๊ฐ€ ์•„๋‹ˆ๋ผ ๋’ค์— $$EnhancerBySpringCGLB ๊ฐ€ ๋’ค์— ๋ถ™์€ Proxy Service ๊ฐ์ฒด๊ฐ€ ์ฃผ์ž…๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์‹œ ์ถ”๊ฐ€ํ•ด์„œ ๋งํ•˜์ž๋ฉด @Configuration์ด ๋ถ™์œผ๋ฉด @Bean์ด ๋ถ™์€ ๊ฒƒ์— ๋Œ€ํ•ด์„œ

์Šคํ”„๋ง์ด CGLB ๋ฐ”์ดํŠธ์ฝ”๋“œ ์กฐ์ž‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ ์ž„์˜์˜ Proxy ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ๊ทธ Proxy ํด๋ž˜์Šค๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•œ ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์‹ฑ๊ธ€ํ†ค์„ ๋ณด์žฅํ•˜์—ฌ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•˜๋‹ค.

(3) AOP ์ ์šฉ ์ „ ์ „์ฒด ์˜์กด๊ด€๊ณ„

 

(4) AOP ์ ์šฉ ํ›„ ์ „์ฒด ์˜์กด๊ด€๊ณ„

์ด๊ฑธ Spring์—์„œ๋Š” Proxy๋ฐฉ์‹์˜ AOP๋ผ๊ณ  ํ•œ๋‹ค.


์ง€๊ธˆ๊นŒ์ง€ ์Šคํ”„๋ง ์ž…๋ฌธ - ์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ, ์›น MVC, DB ์ ‘๊ทผ ๊ธฐ์ˆ (๊น€์˜ํ•œ) ๊ฐ•์˜๋ฅผ ์™„๊ฐ•ํ•˜๋ฉด์„œ Spring ์ „๋ฐ˜์ ์ธ ๋‚ด์šฉ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

์ด์ œ ํ•˜๋‚˜ํ•˜๋‚˜์”ฉ ๋””ํ…Œ์ผ์„ ์ถ”๊ฐ€ํ•  ์ฐจ๋ก€๋‹ค.

์ด์–ด์„œ ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ - ๊ธฐ๋ณธํŽธ(๊น€์˜ํ•œ) ๊ฐ•์˜๋ฅผ ๋“ค์œผ๋ฉฐ ์Šคํ”„๋ง์˜ ๋ณธ์งˆ๊ณผ ๊ฐ์ฒด ์ง€ํ–ฅ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ค๊ณ„์™€ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์„ ํ‚ค์šฐ๋ ค๊ณ  ํ•œ๋‹ค.