λ°±μ—”λ“œ(Back-End) 개발/SpringBoot

[SpringBoot] 7_AOP(관점 μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°)

rabo93 2025. 2. 27. 02:14
AOPκ°€ ν•„μš”ν•œ 상황

- λͺ¨λ“  λ©”μ†Œλ“œμ˜ 호좜 μ‹œκ°„μ„ μΈ‘μ •ν•˜κ³  μ‹Άλ‹€λ©΄? 

- '곡톡' 관심 사항 vs '핡심' 관심 사항

- νšŒμ› κ°€μž… μ‹œκ°„, νšŒμ› 쑰회 μ‹œκ°„μ„ μΈ‘μ •ν•˜κ³  μ‹Άλ‹€λ©΄?

package hello.hello_spring.service;

import hello.hello_spring.domain.Member;
import hello.hello_spring.repository.MemberRepository;
import hello.hello_spring.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();
    // DI (μ˜μ‘΄μ„± μ£Όμž…) νŒ¨ν„΄μœΌλ‘œ λ°”κΎΈκΈ°
    private final MemberRepository memberRepository;

    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    /*
    * νšŒμ›κ°€μž…
    * */
    public long join(Member member) {
        // AOP
        // ** 곡톡 관심 둜직 (각 λ©”μ„œλ“œλ§ˆλ‹€ μ‹œκ°„μ„ μΈ‘μ •ν•˜λŠ” μ½”λ“œ μΆ”κ°€.. μ–Έμ œ λ‹€ν•˜λƒ)
        long start = System.currentTimeMillis();

        try {
            //--------------------------------------
            // ** 핡심 관심 둜직
            //같은 이름이 μžˆλŠ” 쀑볡 νšŒμ› X
            validateDuplicateMember(member); // 쀑볡 νšŒμ› 검증
            memberRepository.save(member);
            return member.getId(); //longνƒ€μž…μ˜ idκ°€ 리턴됨
            //--------------------------------------

        } 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() {
        return memberRepository.findAll();
    }

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


}

 

* μ—¬κΈ°μ„œ 문제점!!

- νšŒμ›κ°€μž…, νšŒμ› μ‘°νšŒμ— μ‹œκ°„을 μΈ‘μ •ν•˜λŠ” κΈ°λŠ₯은 ν•΅μ‹¬ κ΄€μ‹¬ μ‚¬ν•­μ΄ μ•„λ‹ˆλ‹€.

- μ‹œκ°„μ„ μΈ‘μ •ν•˜λŠ” λ‘œμ§μ€ κ³΅ν†΅ κ΄€μ‹¬ μ‚¬ν•­μ΄λ‹€.

- μ‹œκ°„μ„ μΈ‘μ •ν•˜λŠ” 둜직과 핡심 λΉ„μ¦ˆλ‹ˆμŠ€μ˜ 둜직이 μ„žμ—¬μ„œ μœ μ§€λ³΄μˆ˜κ°€ μ–΄λ ΅λ‹€.

- μ‹œκ°„μ„ μΈ‘μ •ν•˜λŠ” λ‘œμ§μ„ λ³€κ²½ν•  λ•Œ λͺ¨λ“  λ‘œμ§μ„ μ°Ύμ•„κ°€λ©΄μ„œ λ³€κ²½ν•΄μ•Ό ν•œλ‹€.

 

 


AOP 적용 (AOP: Aspect Oriented Programming)

: 곡톡 관심 사항 vs 핡심 관심 사항 뢄리!!

 

  • 곡톡 관심 λ‘œμ§μ„ TimeTraceAop.java ν΄λž˜μŠ€μ— λ”°λ‘œ μž‘μ„±ν•˜μ—¬ 뢄리 (MemberService.java ν΄λž˜μŠ€μ—λŠ” 핡심 관심 둜직만 μž‘μ„±)
package hello.hello_spring.aop;

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

@Aspect
@Component
public class TimeTraceAop {

    @Around("execution(* hello.hello_spring..*(..))") //AOP μ„€μ •ν•  경둜
    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" );
        }

    }

}

 

 

  • ν…ŒμŠ€νŠΈ μ‹€ν–‰ μ‹œ μ•„λž˜μ™€ 같이 μ½˜μ†”μ°½μ— 좜λ ₯됨

 

* ν•΄κ²°

- νšŒμ›κ°€μž…, νšŒμ› μ‘°νšŒλ“± 핡심 관심사항과 μ‹œκ°„μ„ μΈ‘μ •ν•˜λŠ” 곡톡 관심 사항을 λΆ„λ¦¬ν•œλ‹€.
- μ‹œκ°„μ„ μΈ‘μ •ν•˜λŠ” λ‘œμ§μ„ λ³„λ„μ˜ 곡톡 둜직으둜 λ§Œλ“€μ—ˆλ‹€.
- 핡심 관심 사항을 κΉ”λ”ν•˜κ²Œ μœ μ§€ν•  수 μžˆλ‹€.
- 변경이 ν•„μš”ν•˜λ©΄ 이 둜직만 λ³€κ²½ν•˜λ©΄ λœλ‹€.
- μ›ν•˜λŠ” 적용 λŒ€μƒμ„ 선택할 수 μžˆλ‹€.