λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ“– Java & Spring & Kotlin/🌱 Spring

[ Spring ] AOPλ₯Ό μ‚¬μš©ν•΄μ„œ μ½”λ“œ 가독성을 λ†’μ—¬λ³΄μž!

by carrot0911 2025. 1. 15.

κ³΅λΆ€ν•˜κ²Œ 된 계기

νŒ€ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λŠ” λ™μ•ˆ, νŒ€μ›μ΄ AOP(Aspect-Oriented Programming)λ₯Ό ν™œμš©ν•΄ κΆŒν•œ 검사λ₯Ό κ΅¬ν˜„ν•˜λŠ” λͺ¨μŠ΅μ„ 보게 λ˜μ—ˆλ‹€. μ²˜μŒμ—λŠ” AOPλ₯Ό μ΄μš©ν•΄ λ³΅μž‘ν•œ λ‘œμ§μ„ κ°„κ²°ν•˜κ²Œ μ²˜λ¦¬ν•˜λŠ” λͺ¨μŠ΅μ΄ 놀라웠고, λ™μ‹œμ— λ‚΄κ°€ 직접 κ΅¬ν˜„ν•˜κΈ°μ—” μ–΄λ ΅κ² λ‹€λŠ” 생각이 λ“€μ—ˆλ‹€. ν•˜μ§€λ§Œ νŒ€μ›μ˜ μ½”λ“œλ₯Ό ν•¨κ»˜ λΆ„μ„ν•˜λ©° μž‘λ™ 방식을 μ΄ν•΄ν•˜λŠ” κ³Όμ •μ—μ„œ, "λ‚˜λ„ λ…Έλ ₯ν•˜λ©΄ μΆ©λΆ„νžˆ AOPλ₯Ό ν™œμš©ν•  수 μžˆκ² λ‹€"λŠ” μžμ‹ κ°μ΄ 생겼닀.
이후, AOP의 κ°œλ…κ³Ό ν™œμš© 사둀λ₯Ό 더 깊이 μ΄ν•΄ν•˜κ³  μ‹Άλ‹€λŠ” 열정이 생겼고, κ΄€λ ¨ 자료λ₯Ό 찾아보며 ν•™μŠ΅μ„ μ‹œμž‘ν–ˆλ‹€. 이번 κ²½ν—˜μ€ λ‹¨μˆœνžˆ μƒˆλ‘œμš΄ κΈ°μˆ μ„ λ°°μš°λŠ” 것을 λ„˜μ–΄, λ‚΄κ°€ 기술적으둜 μ„±μž₯ν•  수 μžˆλ‹€λŠ” κ°€λŠ₯성을 ν™•μΈν•œ 계기가 λ˜μ—ˆλ‹€.


μ½”λ“œλ₯Ό μž‘μ„±ν•  λ•Œ κ°€μž₯ μ€‘μš”ν•œ μš”μ†Œ

λ°”λ‘œ 가독성이라고 μƒκ°ν•œλ‹€.

ν”„λ‘œμ νŠΈκ°€ 컀지면 컀질수둝, κ³ λ„ν™”λ μˆ˜λ‘ μ½”λ“œμ˜ λ³΅μž‘μ„±μœΌλ‘œ 인해 생산성이 떨어진닀. κ·Έλž˜μ„œ 처음 ν”„λ‘œμ νŠΈλ₯Ό μ‹œμž‘ν•  λ•Œ 이런 μš”μ†Œλ₯Ό κ³ λ €ν•˜λ©΄μ„œ 생산성이 λ–¨μ–΄μ§€λŠ” 상황을 경계해야 ν•œλ‹€.
그런 가독성을 μ¦κ°€μ‹œν‚€κ³  μ½”λ“œμ˜ λ³΅μž‘μ„±μ„ μ‰½κ²Œ μ€„μ—¬μ£ΌλŠ” 녀석이 λ°”λ‘œ AOP이닀.

μ˜ˆμ‹œ

μ–΄λ–€ μ½”λ“œκ°€ 가독성이 더 μ’‹μ€κ°€μš”?!

더보기
package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {

    public void viewProfile(String username, String role) {
        if (!"ADMIN".equals(role)) {
            System.out.println("Access Denied: Only ADMIN can view profiles.");
            return;
        }
        System.out.println("Profile of " + username + " viewed successfully.");
    }

    public void updateProfile(String username, String role) {
        if (!"ADMIN".equals(role)) {
            System.out.println("Access Denied: Only ADMIN can update profiles.");
            return;
        }
        System.out.println("Profile of " + username + " updated successfully.");
    }

    public void deleteProfile(String username, String role) {
        if (!"ADMIN".equals(role)) {
            System.out.println("Access Denied: Only ADMIN can delete profiles.");
            return;
        }
        System.out.println("Profile of " + username + " deleted successfully.");
    }

    public void listUsers(String role) {
        if (!"USER".equals(role) && !"ADMIN".equals(role)) {
            System.out.println("Access Denied: Only USER or ADMIN can view the user list.");
            return;
        }
        System.out.println("User list viewed successfully.");
    }

    public void viewDashboard(String role) {
        if (!"USER".equals(role) && !"ADMIN".equals(role)) {
            System.out.println("Access Denied: Only USER or ADMIN can view the dashboard.");
            return;
        }
        System.out.println("Dashboard viewed successfully.");
    }
}
package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {

    public void viewProfile(String username, String role) {
        System.out.println("Profile of " + username + " viewed successfully.");
    }

    public void updateProfile(String username, String role) {
        System.out.println("Profile of " + username + " updated successfully.");
    }

    public void deleteProfile(String username, String role) {
        System.out.println("Profile of " + username + " deleted successfully.");
    }

    public void listUsers(String role) {
        System.out.println("User list viewed successfully.");
    }

    public void viewDashboard(String role) {
        System.out.println("Dashboard viewed successfully.");
    }
}

κ·Έλ ‡λ‹€λ©΄ AOPλž€ λ¬΄μ—‡μΌκΉŒ??

AOP(Aspect-Oriental Programming)은 관점(Aspect) 지ν–₯ ν”„λ‘œκ·Έλž˜λ°μœΌλ‘œ, 관점을 κΈ°μ€€μœΌλ‘œ λ‹€μ–‘ν•œ κΈ°λŠ₯을 λΆ„λ¦¬ν•˜μ—¬ λ³΄λŠ” ν”„λ‘œκ·Έλž˜λ°μ΄λ‹€.

  • Aspect: λΆ€κ°€ κΈ°λŠ₯κ³Ό 그것을 μ μš©ν•˜λŠ” 곳을 μ •μ˜ν•˜κ³  ν•©μ³μ„œ λͺ¨λ“ˆλ‘œ λ§Œλ“  것이닀.

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 핡심 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직과 κ΄€λ ¨ μ—†λŠ” 뢀가적인 κΈ°λŠ₯듀을 λͺ¨λ“ˆν™” ν•˜μ—¬ μ½”λ“œμ˜ 쀑볡을 쀄이고 μœ μ§€λ³΄μˆ˜μ„±μ„ ν–₯μƒν•˜λŠ” 데에 주둜 ν™œμš©λœλ‹€.


AOPλ₯Ό μ‚¬μš©ν•˜λŠ” 이유

객체 지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ„ λ³΄μ™„ν•˜κΈ° μœ„ν•΄μ„œ μ‚¬μš©λœλ‹€.

뢀가적인 κ΄€μ‹¬μ‚¬μ˜ 뢄리

  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ 자주 λ°˜λ³΅λ˜λŠ” μž‘μ—…(λ‘œκΉ…, λ³΄μ•ˆ, νŠΈλžœμž­μ…˜ 관리 λ“±)을 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직과 λΆ„λ¦¬ν•˜μ—¬ μ½”λ“œ 쀑볡을 μ΅œμ†Œν™”ν•˜κ³  μž¬μ‚¬μš©μ„±μ„ 높인닀.

μœ μ§€λ³΄μˆ˜μ„± ν–₯상

  • 관심사λ₯Ό λΆ„λ¦¬ν•¨μœΌλ‘œμ¨ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 λ‹¨μˆœν•΄μ§€κ³ , 뢀가적인 관심사λ₯Ό λ…λ¦½μ μœΌλ‘œ 관리할 수 μžˆμ–΄ μœ μ§€ λ³΄μˆ˜κ°€ νŽΈλ¦¬ν•΄μ§„λ‹€.

μ½”λ“œ μž¬μ‚¬μš©μ„± 증가

  • κ³΅ν†΅μ μœΌλ‘œ μ‚¬μš©λ˜λŠ” κΈ°λŠ₯을 ν•˜λ‚˜μ˜ Aspect둜 μ •μ˜ν•˜κ³  μ—¬λŸ¬ κ³³μ—μ„œ μž¬μ‚¬μš©ν•  수 μžˆλ‹€.

λ‹€μ–‘ν•œ AOP 적용 방식

컴파일 μ‹œμ  적용

  • Aspect μ»΄νŒŒμΌλŸ¬κ°€ 일반 .java νŒŒμΌμ„ μ»΄νŒŒμΌν•  λ•Œ λΆ€κ°€ κΈ°λŠ₯을 λ„£μ–΄μ„œ .class 파일둜 μ»΄νŒŒμΌν•΄ μ£ΌλŠ” 것을 μ˜λ―Έν•œλ‹€.

클래슀 λ‘œλ”© μ‹œμ  적용

  • JVM λ‚΄ 클래슀 λ‘œλ”μ— .class νŒŒμΌμ„ μ˜¬λ¦¬λŠ” μ‹œμ μ— λ°”μ΄νŠΈ μ½”λ“œλ₯Ό μ‘°μž‘ν•΄μ„œ λΆ€κ°€ κΈ°λŠ₯ λ‘œμ§μ„ μΆ”κ°€ν•˜λŠ” 방식이닀.

λŸ°νƒ€μž„ μ‹œμ  적용

  • 컴파일, ν΄λž˜μŠ€λ‘œλ”©, main( ) λ©”μ„œλ“œμ˜ μ‹€ν–‰ 이후에 μžλ°”κ°€ μ œκ³΅ν•˜λŠ” λ²”μœ„ 내에 λΆ€κ°€ κΈ°λŠ₯을 μ μš©ν•˜λŠ” 방식이닀.
  • 이미 λŸ°νƒ€μž„ 쀑이라 μ½”λ“œλ₯Ό μ‘°μž‘ν•˜κΈ° μ–΄λ €μ›Œ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ, DI, 빈 λ“± μ—¬λŸ¬ κ°œλ…κ³Ό κΈ°λŠ₯을 μ΄λ™μ›ν•˜μ—¬ Proxyλ₯Ό 톡해 λΆ€κ°€ κΈ°λŠ₯을 μ μš©ν•˜λŠ” 방식이닀.
    • ProxyλŠ” λ©”μ„œλ“œ μ‹€ν–‰ μ‹œμ μ—μ„œλ§Œ λ‹€μŒ 타깃을 ν˜ΈμΆœν•  수 있기 λ•Œλ¬Έμ—, λŸ°νƒ€μž„ μ‹œμ μ— λΆ€κ°€ κΈ°λŠ₯을 μ μš©ν•˜λŠ” 방식은 λ©”μ„œλ“œμ˜ μ‹€ν–‰ μ§€μ μœΌλ‘œ μ œν•œλœλ‹€.

Spring AOP

Spring AOP ꡬ쑰

주둜 λŸ°νƒ€μž„ μ‹œμ μ— μ μš©ν•˜λŠ” 방식을 μ‚¬μš©ν•œλ‹€.
컴파일 μ‹œμ κ³Ό 클래슀 λ‘œλ”© μ‹œμ μ— μ μš©ν•˜λ €λ©΄ λ³„λ„μ˜ μ»΄νŒŒμΌλŸ¬μ™€ ν΄λž˜μŠ€λ‘œλ” μ‘°μž‘κΈ°λ₯Ό 써야 ν•˜λŠ”λ°, 이것을 μ •ν•˜κ³  μ‚¬μš© 및 μœ μ§€ν•˜λŠ” 과정이 맀우 μ–΄λ ΅κ³  λ³΅μž‘ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

Spring AOPλ₯Ό μ μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” build.gradle에 μ˜μ‘΄μ„±μ„ μΆ”κ°€ν•΄μ€˜μ•Ό ν•œλ‹€.

implementation 'org.springframework.boot:spring-boot-starter-aop' // μŠ€ν”„λ§ aop μΆ”κ°€

AOPκ°€ ν™œμš©λ˜λŠ” λŒ€ν‘œμ μΈ μ˜ˆμ‹œ

  • νŠΈλžœμž­μ…˜ 관리
  • λ‘œκΉ…
  • λ³΄μ•ˆ / κΆŒν•œ 확인
  • μ„±λŠ₯ λͺ¨λ‹ˆν„°

AOP μš©μ–΄

Aspect (Advice + Pointcut)

  • AOPλ₯Ό μ •μ˜ν•  클래슀 μœ„μ— λΆ™μ—¬μ€˜μ•Ό ν•œλ‹€. ex) @Service, @RestController
  • @Aspect와 @Component둜 μ„ μ–Έν•΄μ€€λ‹€.
@Aspect
@Component
public class AOP μ •μ˜ν•œ 클래슀 {

}

Pointcut

  • Join Point μ€‘μ—μ„œ Adviceλ₯Ό 어디에 μ μš©ν• μ§€, μ μš©ν•˜μ§€ μ•Šμ„μ§€ μœ„μΉ˜λ₯Ό νŒλ‹¨ν•˜λŠ” ν•„ν„°λ§ν•˜λŠ” κΈ°λŠ₯이닀. μ‹€μ œ Adviceκ°€ μ μš©λ˜λŠ” 뢀뢄이닀.
  • AOPλ₯Ό μ μš©ν•  λ©”μ„œλ“œλ₯Ό μ •μ˜ν•˜λŠ” ν‘œν˜„μ‹μ„ μ‚¬μš©ν•œλ‹€.
    • 예: 특적 νŒ¨ν‚€μ§€μ˜ λͺ¨λ“  λ©”μ„œλ“œ, νŠΉμ • μ–΄λ…Έν…Œμ΄μ…˜μ΄ 뢙은 λ©”μ„œλ“œ λ“±.
  • μ–΄λ–€ λŒ€μƒμ— AOPλ₯Ό μ μš©ν•  것인지 지정해 μ£ΌλŠ” 것이닀.
@Aspect
@Component
public class AOP μ •μ˜ν•œ 클래슀 {

    // Pointcut: com.example.service νŒ¨ν‚€μ§€ λ‚΄μ˜ λͺ¨λ“  λ©”μ„œλ“œμ— AOP 적용
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}
    
}

Pointcut ν‘œν˜„μ‹ → λͺ°λΌλ„ λœλ‹€! μš°λ¦¬κ°€ μ •κ·œμ‹μ„ μ™ΈμšΈ ν•„μš”κ°€ μ—†μ—ˆλ˜ κ²ƒμ²˜λŸΌ μ™ΈμšΈ ν•„μš”κ°€ μ—†λ‹€!

Advice

  • Join Pointμ—μ„œ μ μš©ν•  λΆ€κ°€ 둜직의 μ’…λ₯˜λ₯Ό μ •μ˜ν•œλ‹€. μ‹€ν–‰ μ‹œμ μ— 따라 μ—¬λŸ¬ μœ ν˜•μ΄ μžˆλ‹€.
    • @Before: λ©”μ„œλ“œκ°€ μ‹€ν–‰λ˜κΈ° 전에 μ‹€ν–‰ν•œλ‹€.
    • @After: λ©”μ„œλ“œκ°€ μ‹€ν–‰λœ 후에 μ‹€ν–‰ν•œλ‹€.
    • @AfterReturning: λ©”μ„œλ“œκ°€ μ •μƒμ μœΌλ‘œ μ‹€ν–‰λœ 후에 μ‹€ν–‰ν•œλ‹€.
    • @AfterThrowing: λ©”μ„œλ“œκ°€ μ‹€ν–‰ 쀑 μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμ„ λ•Œ μ‹€ν–‰ν•œλ‹€.
    • @Around: λ©”μ„œλ“œ μ‹€ν–‰ 전후에 μ‹€ν–‰ν•œλ‹€.
@Aspect
@Component
public class AOP μ •μ˜ν•œ 클래슀 {

    // Pointcut: com.example.service νŒ¨ν‚€μ§€ λ‚΄μ˜ λͺ¨λ“  λ©”μ„œλ“œ(*)에 AOP 적용
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}

    // Before Advice: λ©”μ„œλ“œ μ‹€ν–‰ 전에 둜그 좜λ ₯
    @Before("serviceMethods()")
    public void logBefore() {
        System.out.println("[Before] Method execution started.");
    }

    // After Advice: λ©”μ„œλ“œ μ‹€ν–‰ ν›„ 둜그 좜λ ₯
    @After("serviceMethods()")
    public void logAfter() {
        System.out.println("[After] Method execution finished.");
    }

}

Join Point

  • AOPκ°€ μ μš©λ˜λŠ” μ‹€ν–‰ μ‹œμ μ˜ 정보λ₯Ό λ‹΄κ³  μžˆλ‹€. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ νλ¦„μ—μ„œμ˜ νŠΉμ • ν¬μΈνŠΈμ΄λ‹€.
  • Spring AOPλŠ” Proxy 방식을 μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— Join PointλŠ” 항상 λ©”μ„œλ“œ μ‹€ν–‰ μ§€μ μœΌλ‘œ μ œν•œλœλ‹€.
  • λ©”μ„œλ“œ 이름, λ§€κ°œλ³€μˆ˜ λ“± μ‹€ν–‰ 정보λ₯Ό 쑰회 κ°€λŠ₯ν•˜λ‹€.
// Around Advice: μ‹€ν–‰ μ „ν›„λ₯Ό κ°μ‹Έμ„œ 둜직 μˆ˜ν–‰
@Around("serviceMethods()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {

    System.out.println("[Around] Before method: " + joinPoint.getSignature().getName());
    Object result = joinPoint.proceed(); // λ©”μ„œλ“œ μ‹€ν–‰
    System.out.println("[Around] After method: " + joinPoint.getSignature().getName());
    return result;
    
}

μ»€μŠ€ν…€ μ–΄λ…Έν…Œμ΄μ…˜μ„ ν™œμš©ν•œ AOP

μ»€μŠ€ν…€ μ–΄λ…Έν…Œμ΄μ…˜ @AuthCheck

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {
    String[] value()
}

μ»€μŠ€ν…€ μ–΄λ…Έν…Œμ΄μ…˜μ„ μ΄μš©ν•΄ κΆŒν•œ κ²€μ‚¬ν•˜λŠ” AOP

@Slf4j
@Component
@RequiredArgsConstructor
@Aspect
public class CheckRoleStoreAspect {

    private final HttpServletRequest request;

    @Around("@annotation(team11.team11project.common.aspect.AuthCheck)")
    public Object checkRole(ProceedingJoinPoint joinPoint) throws Throwable{

        //κΆŒν•œ κ°€μ Έμ˜€κΈ°
        String role = (String) request.getAttribute("role");
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        AuthCheck authCheck = method.getAnnotation(AuthCheck.class);

        //κΆŒν•œ 정보가 μ—†λŠ” 경우 μ˜ˆμ™Έ 처리
        if (role == null) {
            throw new UserRoleNotFoundException("μ‚¬μš©μž κΆŒν•œ 정보가 μ—†μŠ΅λ‹ˆλ‹€.");
        }

        //μ• λ…Έν…Œμ΄μ…˜ κΆŒν•œ κ°’κ³Ό μš”μ²­ 받은 κΆŒν•œ 값을 확인. λ§Œμ•½ λ‹€λ₯΄λ©΄ μ˜ˆμ™Έμ²˜λ¦¬.
        if (Arrays.stream(authCheck.value()).noneMatch(role::equals)) {
            throw new UnauthorizedAccessException(String.format(" %s κΆŒν•œλ§Œ μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.",
                    Arrays.toString(authCheck.value())));
        }

        log.info("κΆŒν•œ 확인 μ™„λ£Œ. μš”μ²­ κΆŒν•œ : {}, ν•„μš” κΆŒν•œ : {}", role, authCheck.value() );
        return joinPoint.proceed();
    }
}

μ»€μŠ€ν…€ μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•  경우 μž₯점

  • μœ μ§€λ³΄μˆ˜ 용이
  • μ½”λ“œ κ°„κ²°μ„± → 가독성 κ°œμ„ 
  • ν™•μž₯μ„± 증가

AOP와 κ΄€λ ¨λœ Proxy

ProxyλŠ” μžλ°” 및 μŠ€ν”„λ§μ—μ„œ μ„±λŠ₯ ν–₯상을 μœ„ν•΄μ„œ μ‚¬μš©ν•˜λŠ” μˆ˜λ§Žμ€ λ””μžμΈ νŒ¨ν„΄ 쀑 ν•˜λ‚˜μ΄λ‹€.
객체 지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ "λŒ€λ¦¬μΈ" 역할을 ν•˜λŠ” λ””μžμΈ νŒ¨ν„΄μ΄λ‹€.
μ‹€μ œ 객체에 λŒ€ν•œ 접근을 μ œμ–΄ν•˜κ±°λ‚˜ 뢀가적인 μž‘μ—…μ„ μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λœλ‹€.

Proxy의 μ—­ν• 

  • μ ‘κ·Ό μ œμ–΄: μ‹€μ œ 객체에 λŒ€ν•œ 접근을 μ œν•œν•˜κ±°λ‚˜ 쑰건을 κ²€μ¦ν•œλ‹€.
  • λΆ€κ°€ μž‘μ—… μˆ˜ν–‰: μš”μ²­ μ „/후에 좔가적인 μž‘μ—… μˆ˜ν–‰ (λ‘œκΉ…, νŠΈλžœμž­μ…˜ 관리 λ“±)
  • 지연 μ΄ˆκΈ°ν™”: μ‹€μ œ 객체λ₯Ό ν•„μš”ν•  λ•ŒκΉŒμ§€ μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€. (지연 λ‘œλ”©)

Proxyλ₯Ό μ‚¬μš©ν•˜λŠ” 이유

  • μ ‘κ·Ό μ œμ–΄: ProxyλŠ” 객체에 λŒ€ν•œ λ³΄μ•ˆ κ²€μ‚¬λ‚˜ κΆŒν•œ 확인 같은 μž‘μ—…μ„ μ‰½κ²Œ μ²˜λ¦¬ν•  수 μžˆλ‹€.
  • λΆ€κ°€ μž‘μ—… μˆ˜ν–‰: ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œμ— 영ν–₯을 주지 μ•Šκ³  뢀가적인 κΈ°λŠ₯(λ‘œκΉ…, νŠΈλžœμž­μ…˜)을 μΆ”κ°€ν•  수 μžˆλ‹€.
  • μ„±λŠ₯ μ΅œμ ν™”: μ‹€μ œ 객체의 μƒμ„±μ΄λ‚˜ μ΄ˆκΈ°ν™”κ°€ λΉ„μš©μ΄ 많이 λ“€ 경우, Proxyλ₯Ό μ‚¬μš©ν•΄ 지연 λ‘œλ”©μ„ κ΅¬ν˜„ν•  수 μžˆλ‹€.

References

슀파λ₯΄νƒ€ 내일배움캠프 μˆ˜μ€€λ³„ ν•™μŠ΅λ°˜ μŠ€νƒ λ‹€λ“œλ°˜ μ„Έμ…˜
https://sharonprogress.tistory.com/195

 

AOP(Aspect-Oriented Programming)λž€? μ˜ˆμ‹œ 포함

1. AOP(Aspect-Oriented Programming)λž€? AOP(Aspect-Oriented Programming)λŠ” ν”„λ‘œκ·Έλž˜λ° νŒ¨λŸ¬λ‹€μž„ 쀑 ν•˜λ‚˜λ‘œ, κ΄€μ‹¬μ‚¬μ˜ 뢄리(Concern Separation)λ₯Ό μœ„ν•΄ μ‚¬μš©λ˜λŠ” κΈ°μˆ μ΄λ‹€. AOPλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 핡심 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직과

sharonprogress.tistory.com

https://velog.io/@kai6666/Spring-Spring-AOP-κ°œλ…

 

[Spring] Spring AOP κ°œλ…

AOPλŠ” 관점(Aspect)지ν–₯ ν”„λ‘œκ·Έλž˜λ°μœΌλ‘œ, 관점을 κΈ°μ€€μœΌλ‘œ λ‹€μ–‘ν•œ κΈ°λŠ₯을 λΆ„λ¦¬ν•˜μ—¬ λ³΄λŠ” ν”„λ‘œκ·Έλž˜λ°μ΄λ‹€. 관점(Aspect)μ΄λž€, λΆ€κ°€ κΈ°λŠ₯κ³Ό κ·Έ 적용처λ₯Ό μ •μ˜ν•˜κ³  ν•©μ³μ„œ λͺ¨λ“ˆλ‘œ λ§Œλ“  것이닀.OOP와 이름

velog.io

https://hstory0208.tistory.com/entry/Spring-μŠ€ν”„λ§-AOPAspect-Oriented-Programmingλž€-Aspect

 

[Spring] μŠ€ν”„λ§ AOP(Aspect Oriented Programming)λž€? - @Aspect

AOPλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ ?AOP에 λŒ€ν•΄ μ„€λͺ…ν•˜κΈ° 전에 AOPλ₯Ό μ‚¬μš©ν•˜λŠ” μ΄μœ μ— λŒ€ν•΄ λ¨Όμ € μ•Œμ•„ λ΄…μ‹œλ‹€. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ‘œμ§μ€ 크게 핡심 κΈ°λŠ₯κ³Ό λΆ€κ°€ κΈ°λŠ₯으둜 λ‚˜λˆŒ 수 μžˆμŠ΅λ‹ˆλ‹€.핡심 κΈ°λŠ₯ : ν•΄λ‹Ή 객

hstory0208.tistory.com