웹 프로그래밍/[ Spring ]

[ Spring ] 10. AOP(Aspect Oriented Programming)

kim.svadoz 2021. 7. 7. 12:37
728x90
반응형

AOP


Aspect Oriented Programming
(측면/양상 지향적 프로그래밍)

" 공통의 관심사항을 적용해서 발생하는 의존 관계의 복잡성과 코드 중복을 해소 "

즉, 여러군데서 사용되는 중복되는 코드를 떼어내서 분리하고 각 메소드는 자신이 해야할 작업만 갖고 있자는 개념이다.

여기서 여러군데서 사용되는 중복되는 코드(부가 기능)가 AOP에서 말하는 Aspect이다.

각 클래스에서 공통 관심 사항을 구현한 모듈에 대한 의존관계를 갖기 보단, Aspect를 이용해 핵심 로직을 구현한 각 클래스에 공통 기능을 적용한다.

간단한 설정만으로도 공통 기능을 여러 클래스에 적용할 수 있는 장점이 있으며 핵심 로직 코드를 수정하지 않고도 웹 애플리케이션의 보안, 로깅, 트랜잭션과 같은 공통 관심사항을 AOP를 이용해 간단하게 적용가능하다.

image-20210610103947651

  • 핵심기능 : 업무 로직을 포함하는 기능
  • 부가기능 : 핵심 기능을 도와주는 부가적인 기능(로깅, 보안 등)
  • target : 핵심 기능을 담고 있는 모듈로 타겟은 부가기능을 부여한 대상
  • Advice : 타겟에 제공할 부가기능을 담고 있는 모듈
  • Joinpoint
    • Advice를 적용이 가능한 지점을 의미(before, after 등등)
    • 타겟 객체가 구현한 인터페이스의 모든 메서드는 Jointpoint가 된다.
  • Pointcut
    • Jointpoint의 부분집합으로, 실제로 Advice가 적용되는 Joinpoint를 나타냄.
    • Advice를 적용할 타겟의 메서드를 선별하는 정규표현식
    • 표현식은 execution으로 시작하고 메서드의 Signature를 비교하는 방법을 주로 이용한다.
  • Weaving
    • Pointcut에 의해서 결정된 타겟의 조인 포인트에 부가기능(Advice)를 삽입하는 과정
    • AOP가 핵심기능(Target)의 코드에 영향을 주지 않으면서 필요한 부가기능(Advice)을 추가할 수 있도록 해주는 핵심적인 처리과정
  • Aspect
    • 여러 객체에 공통으로 적용되는 공통 관심사항을 말함. 트랜잭션이나 보안 등이 Aspect의 좋은 예
    • AOP의 기본 모듈
    • Advice + Pointcut
    • Aspect는 싱글톤 형태의 객체로 존재한다.

AOP란?

객체지향의 기본원칙을 적용하여도 핵심기능에서 부가기능을 분리해서 모듈화하는 것은 매우 어렵다.

AOP는 애플리케이션에서의 관심사의 분리(기능의 분리), 핵심적인 기능에서 부가적인 기능을 분리한다.

분리한 부가기능을 Aspect라는 독특한 모듈형태로 만들어서 설계하고 개발하는 방법이다.

  • OOP를 적용하여도 핵심기능에서 부가기능을 쉽게 분리된 모듈로 작성하기 어려운 문제점을 AOP가 해결해준다고 볼 수 있다.

  • AOP는 부가기능을 Aspect로 정의하여 핵심기능에서 부가기능을 분리함으로써 핵심기능을 설계하고 구현할 때 객체지향적인 가치를 지킬 수 있도록 도와주는 개념이다.

Spring AOP 특징

  1. Spring은 프록시 기반 AOP를 지원한다.
    • Spring은 타겟(tartget) 객체에 대한 프록시를 만들어 제공한다.
    • 타겟을 감싸는 프록시는 실행시간(Runtime)에 생성된다.
    • 프록시는 어드바이스를 타겟 객체에 적용하면서 생성되는 객체이다.
  2. 프록시(Proxy)가 호출을 가로챈다.(Intercept)
    • 프록시는 타겟 객체에 대한 호출을 가로챈 다음 어드바이스의 부가기능 로직을 수행하고 난 후에 타겟의 핵심기능 로직을 호출한다.(전처리 Advice)
    • 또는 타겟의 핵심기능 로직 메서드를 호출한 후에 부가기능(어드바이스)을 수행하는 경우도 있다.(후처리 Advice)
  3. Spring AOP는 메서드 조인 포인트만 지원한다.
    • Spring은 동적 프록시를 기반으로 AOP를 구현하므로 메서드 조인포인트만 지원한다.
    • 핵심기능(타겟)의 메서드가 호출되는 런타임 시점에만 부가기능(어드바이스)을 적용할 수 있다.
    • 반면에 AspectJ같은 고급 AOP 프레임워크를 사용하면 객체의 생성, 필드값의 조회와 조작, static 메서드 호출 및 초기화 등 다양한 작업에 부가기능을 적용할 수 있다.

Spring AOP 구현방식

  1. XML 기반의 POJO 클래스를 이용한 AOP 구현
    • 부가기능을 제공하는 Advice 클래스를 작성한다.
    • XML 설정 파일에 <aop:config>를 이용해서 Aspect를 설정한다.
      (즉, Advice와 Pointcut을 설정하는 것)
  2. @Aspect 어노테이션을 이용한 AOP 구현
    • @Aspect 어노테이션을 이용해서 부가기능을 제공하는 Aspect 클래스를 작성한다.
    • 이 떄 Aspect 클래스는 어드바이스를 구현하는 메서드와 Pointcut을 포함한다.
    • XML 설정 파일에 <aop:aspectj-autoproxy/>를 설정한다.

Advice의 종류

  • Around 어드바이스
    • 타겟의 메서드가 호출되기 이전(before) 시점과 이후(after) 시점에 모두 처리해야 할 필요가 있는 부가기능을 정의
    • Jointpoint 앞과 뒤에서 실행되는 Advice
  • Before 어드바이스
    • 타겟의 메서드가 실행되기 이전(before) 시점에 처리해야 할 필요가 있는 부가기능을 정의
    • Jointpoint앞에서 실행되는 Advice
  • After Returning 어드바이스
    • 타겟의 메서드가 정상적으로 실행된 이후(after) 시점에 처리해야 할 필요가 있는 부가기능을 정의
    • Jointpoint 메서드 호출이 정상적으로 종료된 뒤에 실행되는 Advice
  • After Throwing 어드바이스
    • 타겟의 메서드가 예외를 발생한 이후(after) 시점에 처리해야 할 필요가 있는 부가기능을 정의
    • 예외가 던져질때 실행되는 Advice

Advice 태그

  • <aop:before>
    • 메서드 실행전에 적용되는 어드바이스 정의
  • <aop:after-returning>
    • 메서드가 정상적으로 실행된 후에 적용되는 어드바이스 정의
  • <aop:after-throwing>
    • 메서드가 예외를 발생시킬 때 적용되는 어드바이스 정의
    • try-catch 블록에서의 catch와 비슷하다.
  • <aop:after>
    • 메서드가 정상적으로 실행되는지 또는 예외를 발생시키는지 여부에 상관없이 어드바이스를 저으이
    • try-catch-finally 블록에서 finally와 비슷하다.
  • <aop:around>
    • 메서드 호출 이전, 이후 예외발생 등 모든 시점에 적용 가능한 어드바이스 정의

프록시 패턴

String AOP는 프록시 패턴이라는 디자인 패턴을 사용해서 AOP의 효과를 낸다.

프록시 패턴을 사용하면 어떤 기능을 추가하려 할 때 기존 코드를 변경하지 않고 기능을 추가할 수 있다.

어떤 클래스가 Spring AOP의 대상이라면 그 기존 클래스의 빈이 만들어질 때 Spring AOP가 프록시(기능이 추가된 클래스)를 자동으로 만들고 원본 클래스 대신 프록시를 빈으로 등록한다.

그리고 원본 클래스가 사용되는 지점에서 프록시를 대신 사용한다.

아래 예제의 @Transactional 어노테이션이 이에 해당한다.

image-20210610112017582

@Transactional 어노테이션이 붙어있으면 OwnerRepository 타입의 프록시가 새로 만들어지고 Spring AOP에 의해 자동으로 생성되는 OwnerRepository의 프록시에는 @Transactional 어노테이션이 지시하는 코드가 삽입된다.

@Transactional에 의해 추가되는 기능은 다음과 같다.

JDBC에서 트랜잭션 처리를 하려면 SQL 실행문 앞뒤에 setAutoCommit()commit() / rollback() 코드가 항상 붙는데 @Transactional 어노테이션은 프록시에 자동으로 그 코드를 넣어서 반복, 중복되는 코드를 생략할 수 있게 한다.

이로 인해 개발자는 비즈니스 로직에만 집중할 수 있게 되는 것이다.

참조

https://atoz-develop.tistory.com/entry/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-AOP-%EA%B0%9C%EB%85%90-%EC%9D%B4%ED%95%B4-%EB%B0%8F-%EC%A0%81%EC%9A%A9-%EB%B0%A9%EB%B2%95

https://shlee0882.tistory.com/206

728x90
반응형