AOP(Aspect-Oriented Programming)란?

Jeonghyeon Park·2025년 3월 19일

SKALA

목록 보기
6/13

AOP 또는 관점 지향 프로그래밍은 비즈니스 로직과 관계없이 반복적으로 발생하는 공통 기능(로깅, 트랜잭션, 보안 등)을 별도로 분리하여 관리하는 프로그래밍 기법이다.

AOP의 필요성

  1. 반복되는 코드 제거
    • 서비스 로직마다 중복되는 코드(로그, 보안, 트랜잭션 등)를 계속 추가해야 하는 문제를 해결한다.
  2. 비즈니스 로직과 부가 기능을 분리
    • 핵심 로직과 보조 기능(로깅, 보안, 트랜잭션 등)을 분리하면 코드 가독성이 좋아지고 유지보수가 쉬워진다.
  3. OOP(객체 지향 프로그래밍)의 한계를 보완
    • OOP는 코드의 모듈화를 지원하지만, 횡단 관심사(Cross-Cutting Concern, 공통 기능)를 해결하기 어렵다.
    • AOP를 사용하면 중복 없이 여러 클래스에 공통 기능을 적용할 수 있다.

AOP 주요 개념

개념설명
Aspect (관점, 단면)공통 기능(로깅, 트랜잭션 등)이 담긴 모듈
Advice (부가 기능, 실행 코드)Aspect에서 실행할 코드 (Before, After, Around 등)
Pointcut (대상 지정)AOP가 적용될 메서드나 클래스를 지정
JoinPoint (실제 실행 지점)AOP가 적용될 수 있는 시점 (메서드 실행 등)
Weaving (위빙, 적용 과정)Advice가 Pointcut에 적용되는 과정

AOP 사용 예시

  1. 로깅(logging)
    • 모든 서비스 메서드 실행 전에 로그를 남길 때
  2. 보안(Security)
    • 특정 메서드 호출 전에 권한 체크
  3. 트랜잭션 관리(Transaction)
    • 서비스 메서드가 실행되면 자동으로 트랜잭션 시작/종료
  4. 성능 모니터링(Performance Monitoring)
    • 메서드 실행 시간을 측정하여 성능 분석

Spring에서 AOP 적용 방법

Spring AOP는 IoC 컨테이너에서 관리하는 빈(Bean)Advice(부가 기능 코드)를 적용할 수 있다.

프록시(Proxy) 객체란?

AOP는 원래 객체를 감싸는 "프록시 객체"를 생성하여 원래 객체 대신 실행하도록 한다.
즉, Advice(부가 기능 코드)가 포함된 가짜 객체를 만들어 원래 객체를 대체하는 방식이다.

AOP 없이 동작하는 서비스 클래스

@Service
public class UserService {
    public String getUser() {
        System.out.println("getUser 실행 중...");
        return "User";
    }
}

실행 결과

getUser 실행 중...

이 경우, getUser()가 단순히 실행되며 부가 기능(로깅, 트랜잭션 등)이 없다.

AOP 적용 후 (프록시 사용)

AOP 설정 코드

@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println("[Before] 실행하는 메서드: " + joinPoint.getSignature());
    }
}

실행 결과

[Before] 실행하는 메서드: String com.example.service.UserService.getUser()
getUser 실행 중...

AOP를 적용하면 getUser()가 실행되기 전에 @Before 어드바이스가 실행된다.

프록시(Proxy) 객체의 동작 방식

AOP 적용 후, UserService 객체를 호출하면 프록시 객체가 실행된다.
1. UserService 호출 시, 프록시 객체가 대신 실행됨
2. @Before 등의 AOP 코드가 먼저 실행됨
3. 이후, 원래의 UserService.getUser() 메서드가 실행됨

JoinPoint vs ProceedingJoinPoint

JoinPoint

  • 실행 중인 조인 포인트(메서드 호출) 정보를 제공하는 객체
  • 주로 @Before, @After에서 사용됨
  • 메서드 실행을 제어할 수 없음 (단순 정보 제공)

사용 예시

@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
    System.out.println("[Before] 실행되는 메서드: " + joinPoint.getSignature());
}

주요 메서드

  • joinPoint.getSignature() → 현재 실행되는 메서드 이름 가져오기
  • joinPoint.getArgs() → 메서드의 매개변수 값 가져오기

ProceedingJoinPoint

  • JoinPoint를 상속받은 객체로, 원래 메서드를 실행할 수 있음
  • @Around에서만 사용됨
  • 메서드 실행을 제어할 수 있음 (proceed()를 호출해야 원래 메서드 실행됨)

사용 예시

@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("[Around] 메서드 실행 전");
    Object result = joinPoint.proceed();  // 원래 메서드 실행
    System.out.println("[Around] 메서드 실행 후");
    return result;
}

주요 메서드

  • joinPoint.proceed() → 원래의 메서드 실행
  • 실행 전/후 로직 추가 가능 (로깅, 성능 측정, 트랜잭션 관리 등)

AOP 실행 흐름 예제

public String getUser() {
    System.out.println("getUser 실행 중...");
    return "User";
}

실행 로그 (@Before, @After, @Around 조합)

[Around] 메서드 실행 전
[Before] 실행되는 메서드: String com.example.service.UserService.getUser()
getUser 실행 중...
[After] 실행되는 메서드: String com.example.service.UserService.getUser()
[Around] 메서드 실행 후

요약

AOP를 사용하면 핵심 비즈니스 로직과 공통 기능을 분리하여 유지보수성을 향상
Spring AOP는 프록시 객체를 사용하여 부가 기능을 추가
JoinPoint는 단순 관찰용, ProceedingJoinPoint는 실행 제어 가능

profile
안녕하세요

0개의 댓글