Kotlin

AOP (Aspect-Oriented Programming) - 관점 지향 프로그래밍

빈코더 2024. 12. 23. 11:09
728x90

AOP (Aspect-Oriented Programming) - 관점 지향 프로그래밍

AOP란?

AOP는 소프트웨어 설계 원칙 중 하나로, 애플리케이션 전반에 걸쳐 반복적으로 나타나는 공통 관심사(Cross-Cutting Concerns)를 핵심 비즈니스 로직과 분리하여 관리하는 프로그래밍 기법입니다.

스프링 프레임워크는 AOP를 활용해 로깅, 트랜잭션 관리, 보안과 같은 공통 작업을 모듈화하여 코드의 중복을 줄이고 유지보수를 용이하게 합니다.

AOP의 필요성

비즈니스 로직에 다음과 같은 공통 작업이 섞여 있다면 코드가 복잡해지고 중복이 늘어납니다.

  • 메시드 실행 전/후 로깅
  • 데이터 검증
  • 보안 인증/인가
  • 트랜잭션 처리

AOP 적용 전

  class UserService {
      fun createUser(user: User) {
          println("Start transaction") // 공통 로직
          // 비즈니스 로직
          println("User created: $user")
          println("Commit transaction") // 공통 로직
      }
  }


AOP 적용 후
AOP를 사용하면 공통 작업을 별도로 분리해 비즈니스 로직과 독립적으로 관리할 수 있습니다.

  class UserService {
      fun createUser(user: User) {
          // 핵심 비즈니스 로직만 남음
          println("User created: $user")
      }
  }

  // 공통 로직은 AOP로 분리
  @Aspect
  @Component
  class TransactionAspect {
      @Before("execution(* com.example.service.*.*(..))")
      fun beginTransaction() {
          println("Start transaction")
      }

      @After("execution(* com.example.service.*.*(..))")
      fun commitTransaction() {
          println("Commit transaction")
      }
  }

AOP의 핵심 개념

AOP는 다음과 같은 주요 구성 요소로 이루어져 있습니다.

  1. Aspect
    • 공통 관심사를 정의하는 모듈입니다.
    • 클래스 형태로 작성하며, @Aspect로 선언합니다.
  2. JoinPoint
    • AOP가 적용될 수 있는 지점(메서드 호출, 객체 생성 등)을 의미합니다.
    • 예: 특정 클래스의 메서드 실행 시점
  3. Advice
    • Aspect에서 실행되는 실제 작업(로직)
    • 메서드 실행 전, 실행 후, 예외 발생 시 등 다양한 시점에서 동작
    • 종류
      • @Before: 메서드 실행 전에 동작
      • @After: 메서드 실행 후에 동작
      • @AfterReturning: 메서드가 정상적으로 실행된 후 동작
      • @AfterThrowing: 메서드 실행 중 예외가 발생했을 때 동작
      • @Around: 메서드 실행 전후를 둘 다 제어
  4. Pointcut
    • AOP가 적용될 지점을 지정하는 표현식
    • 예: 특정 패키지, 클래스, 메서드에만 적용
  5. Weaving
    • Aspect를 실제 코드에 적용하는 과정
    • 컴파일 타임, 런타임, 로드 타임에 이루어질 수 있음

AOP 동작원리

스프링 AOP는 프록시 패턴을 사용하여 동작합니다.

  • 프록시 패턴: 실제 객체 앞에 대리 객체를 두고, 대리 객체가 실제 객체를 호출하기 전후로 추가 작업을 수행  

AOP 프록시 구조

  1. 클라이언트가 서비스 객체의 메서드를 호출
  2. 프록시 객체가 먼저 호출을 가로챔
  3. 프록시 객체에서 Advice(공통로직)를 실행
  4. 실제 서비스 객체의 메서드를 호출
  5. 다시 프록시 객체가 결과를 처리 후 클라이언트로 반환

스프링 AOP 예제

1. 비즈니스 클래스

  @Service
  class UserService {
      fun createUser(user: String) {
          println("User created: $user")
      }
  }    

2. Aspect 정의

  @Aspect
  @Component
  class LoggingAspect {
      // Pointcut: UserService의 모든 메서드에 적용
          @Before("execution(* com.example.service.UserService.*(..))")
      fun logBefore(joinPoint: JoinPoint) {
          println("Before Method: ${joinPoint.signature.name}")
      }

      @After("execution(* com.example.service.UserService.*(..))")
      fun logAfter(joinPoint: JoinPoint) {
          println("After Method: ${joinPoint.signature.name}")
      }

  }


Pointcut 표현식

  • execution: 메서드 실행을 기준으로 Pointcut 지정
    • execution(* com.example.service..(..)): 특정 패키지의 모든 클래스와 메서드.
    • execution(public void com.example.service.UserService.createUser(..)): 특정 클래스의 특정 메서드.
  • within: 특정 클래스나 패키지 내부의 모든 메서드.
    • within(com.example.service.UserService): UserService 클래스의 모든 메서드.
  • @annotation
    • @annotation(org.springframework.transaction.annotation.Transactional): @Transactional이 붙은 메서드.

AOP의 장점

  1. 코드 중복 감소
    • 공통 관심사를 분리해 코드 재사용성 및 가독성을 높임
  2. 관심사 분리
    • 비즈니스 로직과 공통 로직을 분리하여 코드의 응집도를 높임
  3. 유지보수성 향상
    • 공통 로직이 한 곳에 모여 있어 수정이 쉽고 영향 범위를 줄임
  4. 확장성 증가
    • 새로운 공통 관심사를 추가할 때 기존 코드를 수정하지 않아도 됨

AOP 사용 시 주의사항

  1. 복잡성 증가
    • 과도한 AOP 사용은 코드의 흐름을 이해하기 어렵게 만들 수 있음
  2. 오버헤드
    • 프록시 객체를 사용하는 방식이므로 성능에 약간 영향을 줄 수 있음
  3. Pointcut 관리
    • Pointcut 표현식이 많아지면 유지보수가 어려워질 수 있음

스프링 AOP와 트랙잭션 예제

1. 트랜잭션 관리 Aspect

  @Aspect
  @Component
  class TransactionAspect {

      @Before("execution(* com.example.service.*.*(..))")
      fun beginTransaction() {
          println("Transaction Started")
      }

      @After("execution(* com.example.service.*.*(..))")
      fun commitTransaction() {
          println("Transaction Committed")
      }
  }

2. 적용 결과

  val userService = UserService()
  userService.createUser("John")

3. 출력

  Transaction Started
  User created: John
  Transaction Committed

요약

  • AOP란 공통 관심사를 비즈니스 로직과 분리해 모듈화 하는 프로그래밍 기법
  • 구성 요소
    • Asepect: 공통 관심사를 정의하는 클래스
    • JoinPoint: AOP가 적용될 수 있는 지점
    • Advice: 실행할 실제 로직
    • Pointcut: AOP가 적용될 조건
  • 장점
    • 코드 중복 감소, 유지보수성 향상, 관심사 분리
  • 활용 사례
    • 로깅, 트랜잭션 관리, 보안 인증/인가
728x90