[Spring Boot][1] 7. AOP

sorzzzzyยท2021๋…„ 8์›” 16์ผ
0

Spring Boot - ์ž…๋ฌธํŽธ

๋ชฉ๋ก ๋ณด๊ธฐ
9/10
post-thumbnail

๐Ÿท AOP๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ

AOP๋Š” ์–ธ์ œ ์‚ฌ์šฉํ•˜๋Š” ์ง€ ์•Œ๋ฉด ์ „~ํ˜€ ์–ด๋ ค์šด ๊ฐœ๋…์ด ์•„๋‹ˆ๋‹ค!

๊ทธ๋Ÿผ ๋Œ€์ฒด ์–ธ์ œ ์‚ฌ์šฉํ•˜๋Š”์ง€ โ“

-> ๋ชจ๋“  ๋ฉ”์†Œ๋“œ์˜ ํ˜ธ์ถœ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ

โœ”๏ธ MemberService ํšŒ์› ์กฐํšŒ ์‹œ๊ฐ„ ์ธก์ • ์ถ”๊ฐ€

main/java/hello.hellospring/service/MemberService.java ์ฝ”๋“œ ์ˆ˜์ •ํ•˜๊ธฐ

package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Transactional
public class MemberService {

    // private final MemberRepository memberRepository = new MemoryMemberRepository();
    private final MemberRepository memberRepository;

    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
    // ํšŒ์› ๊ฐ€์ž…
    public Long join(Member member) {

        long start = System.currentTimeMillis();

        try {
            // //์ค‘๋ณต ํšŒ์› ๊ฒ€์ฆ ํ•„์š”
            validateDuplicateMember(member);
            memberRepository.save(member);

            return member.getId();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;

            System.out.println("join " + timeMs + "ms");
        }
    }

    private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
                .ifPresent(m -> {
                    throw new IllegalStateException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค.");
                });
    }

    // ์ „์ฒด ํšŒ์› ์กฐํšŒ
    public List<Member> findMembers() {
        long start = System.currentTimeMillis();

        try {
            return memberRepository.findAll();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;

            System.out.println("findMembers " + timeMs + "ms");
        }
    }

    public Optional<Member> findOne(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

โœ”๏ธ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋กœ ํšŒ์›๊ฐ€์ž… ๋Œ๋ ค๋ณด๊ธฐ


โœ”๏ธ findMembers๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด localhost:8080 ์ ‘์†ํ•˜๊ธฐ

์—ฌ๊ธฐ์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๐Ÿคš๐Ÿป

  • ํšŒ์›๊ฐ€์ž…, ํšŒ์›์กฐํšŒ์˜ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๊ฒƒ์€ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ด ์•„๋‹˜! ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง์€ ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์ผ ๋ฟ, ์šฐ๋ฆฌ์˜ ๊ด€์‹ฌ์‚ฌ(=ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง)๋Š” try ์•ˆ์˜ ๋‚ด์šฉ์ด๋‹ค!
  • ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง๊ณผ ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค์˜ ๋กœ์ง์ด ์„ž์—ฌ์„œ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๊ฒ๋‚˜ ๊ท€์ฐฎ๊ณ  ์–ด๋ ต๋‹ค.
  • ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง์„ ๋ณ„๋„์˜ ๊ณตํ†ต ๋กœ์ง์œผ๋กœ ๋งŒ๋“ค๊ธฐ ๋งค์šฐ ์–ด๋ ต๋‹ค.
  • ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง์„ ๋ณ€๊ฒฝํ•  ๋•Œ ๋ชจ๋“  ๋กœ์ง์„ ์ฐพ์•„๊ฐ€๋ฉด์„œ ํ•˜๋‚˜ํ•˜๋‚˜ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.


๐Ÿท AOP ์ ์šฉ

๋Œ€๋‹จํ•œ ๊ณ ๋Œ€ ์šฐ๋ฆฌ์˜ ๊ฐœ๋ฐœ์ž๋ถ„๋“ค...^^ ์—ฌ๋Ÿฌ ๊ณ ๋ฏผ์„ ํ•˜๋‹ค ๋‚˜์˜จ ๊ฒฐ๊ณผ!

  • AOP: Aspect Oriented Programming (๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ)
  • ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ(cross-cutting concern) ๊ณผ ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ(core concern)์„ ๋ถ„๋ฆฌํ•œ ๊ฒƒ
  • ์ด์ „๊นŒ์ง€๋Š” ์‹œ๊ฐ„ ์ธก์ • ๋กœ์ง์„ ๋งค์„œ๋“œ์— ๋‹ค ๋ถ™์˜€๋Š”๋ฐ, ์ด์ œ๋Š” ์‹œ๊ฐ„ ์ธก์ • ๋กœ์ง์„ ํ•œ ๊ณณ์— ๋‹ค ๋ชจ์œผ๊ณ  ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ณณ์— ๋ถ™์—ฌ๋ฒ„๋ฆฌ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ AOP !!!

โœ”๏ธ ์‹œ๊ฐ„ ์ธก์ • AOP ๋“ฑ๋กํ•˜๊ธฐ

main/java/hello.hellospring/aop/TimeTraceAop.java ํŒŒ์ผ ์ƒ์„ฑ

package hello.hellospring.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
// ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•  ๋•Œ ์ด๋ ‡๊ฒŒ @Component๋กœ ๊ฑธ์–ด์ค˜๋„ ๋˜๊ณ ,
// SpringConfig.java ํŒŒ์ผ์— ์ง์ ‘ ๋“ฑ๋กํ•ด์ค˜๋„ ๋จ
@Component
// AOP๋Š” @Aspect๋ฅผ ์ ์–ด์ค˜์•ผ ํ•จ
@Aspect
public class TimeTraceAop {
    // @Around - ์–ด๋””์— ์ ์šฉํ•  ๊ฒƒ์ธ์ง€ ํƒ€๊ฒŸํŒ… ํ•˜๋Š” ๊ฒƒ
    // hello.hellospring ์ด๋ผ๋Š” ํŒจํ‚ค์ง€์˜ ํ•˜์œ„์— ๋ชจ๋‘ ๋‹ค ์ ์šฉํ•˜๋ผ๋Š” ๋œป
    @Around("execution(* hello.hellospring..*(..))")

    // joinPoint๊ฐ€ ๊ฐ€์ง„ ๋ฉ”์†Œ๋“œ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์Œ.
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        // ์Šคํƒ€ํŠธ ๋ผ์ธ ์ฐ์–ด๋ณด๊ธฐ(์–ด๋–ค ๋ฉ”์†Œ๋“œ๊ฐ€ ์ง„ํ–‰๋˜๋Š”์ง€ ๋‹ค ์•Œ๋ ค์คŒ)
        System.out.println("START: " + joinPoint.toString());
        try {
            // joinPoint.proceed(): ๋‹ค์Œ ๋ฉ”์†Œ๋“œ๋กœ ์ง„ํ–‰์ด ๋จ, ์ด ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ฆฌํ„ด
            return joinPoint.proceed();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");
        }
    }
}

๐Ÿ’ก ์ด๋•Œ ์Šคํ”„๋ง ๋นˆ์„ 2๊ฐ€์ง€ ๋ฐฉ์‹์œผ๋กœ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Œ
1) main/java/hello.hellospring/aop/TimeTraceAop.java ํŒŒ์ผ์—์„œ @Component ์‚ฌ์šฉ
2) main/java/hello.hellospring/SpringConfig.java ํŒŒ์ผ์— ์ง์ ‘ ๋“ฑ๋ก (๋งจ ์•„๋ž˜ ์ฃผ์„ ๋ถ€๋ถ„)


โœ”๏ธ ์ด์ œ ์‹คํ–‰์‹œ์ผœ๋ณด์ž !
๊น”๋”ํ•˜๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค๐Ÿ˜ƒ

์œ„์—์„œ ๋ฐœ์ƒํ–ˆ๋˜ ๋ฌธ์ œ๋ฅผ AOP ์‚ฌ์šฉ์œผ๋กœ ํ•ด๊ฒฐ๐Ÿ’ก

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

โœ”๏ธ์Šคํ”„๋ง์˜ AOP ๋™์ž‘ ๋ฐฉ์‹ ์„ค๋ช…


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

  • ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•  ๋•Œ ์ง„์งœ ์Šคํ”„๋ง ๋นˆ์ด ์•„๋‹Œ ๊ฐ€์งœ ์Šคํ”„๋ง ๋นˆ์„ ์„ธ์›€(ํ”„๋ก์‹œ)๋ผ๊ณ  ํ•จ
  • ์ด ๊ฐ€์งœ ์Šคํ”„๋ง๋นˆ์ด ๋™์ž‘์ด ๋๋‚˜๋ฉด, joinPoint.proceed() ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ด ๋•Œ ์ง„์งœ ์Šคํ”„๋ง ๋นˆ์„ ํ˜ธ์ถœํ•จ!

3) AOP ์ ์šฉ ์ „ ์ „์ฒด ๊ทธ๋ฆผ

4) AOP ์ ์šฉ ํ›„ ์ „์ฒด ๊ทธ๋ฆผ

  • ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์‹คํ–‰๋จ


๋“œ๋””์–ด ์ž…๋ฌธ์šฉ ๊ฐ•์˜๋ฅผ ... ๋งˆ์ณค๋‹ค .... !!!!!!!!!!!!!!!!!!!

์ฒซ ๋‹จ์ถ”๋ฅผ ๋‹จ๋‹จํžˆ ์ž˜ ๋ผ์›Œ๋ณด์ž! ๋ผ๋Š” ๋งˆ์Œ๊ฐ€์ง์œผ๋กœ ๋ณด๋‹ค ๋” ์ž์„ธํ•˜๊ณ  ๋น ์ง์—†์ด ๊ธฐ๋กํ•˜๋ ค๊ณ  ํ–ˆ๋”๋‹ˆ ์ƒ๊ฐ๋ณด๋‹ค ์‹œ๊ฐ„์ด ๋” ๋งŽ์ด ๊ฑธ๋ ธ๋˜ ๊ฑฐ ๊ฐ™๋‹ค๐Ÿ˜‚
๋‹ค์Œ ๋กœ๋“œ๋งต๋ถ€ํ„ฐ๋Š”, ํ•ต์‹ฌ๋งŒ ๊ฐ„๋‹จํžˆ ์ถ”๋ ค์„œ ๊ธฐ๋กํ•˜๊ณ  ์ฝ”๋“œ์— ๊ด€ํ•œ ์„ค๋ช…์€ ์ฃผ์„์œผ๋กœ ๋‹ฌ ์˜ˆ์ •์ด๋‹ค๐Ÿ˜ƒ (+ ๊ฒฐ๊ณผ ํ™”๋ฉด ์บก์ณ๋„ ์ตœ์†Œํ™”!)
์ด์ „ ํฌ์ŠคํŒ…์—์„œ ๋งํ–ˆ๋“ฏ, ๋กœ๋“œ๋งต1๋กœ ๋„˜์–ด๊ฐ€๊ธฐ ์ „ ์ž…๋ฌธ์šฉ ๊ฐ•์˜๋ฅผ ๋‹ค์‹œ ํ•œ ๋ฒˆ ์ •๋ฆฌํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค! ์ง€๊ธˆ์€ ๋จธ๋ฆฌ์†์ด ์กฐ๊ธˆ ๋’ค์ฃฝ๋ฐ•์ฃฝ์ด๋ผ์„œ ํ—คํ—ค
์•„๋ฌดํŠผ ํ™”์ดํŒ… ํ™”์ดํŒ… ๐ŸŒŸ๐ŸŒŸ

profile
Backend Developer

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