[SEB BE]Section 2. AOP(Aspect-Oriented Programming) 정리

박두팔이·2023년 2월 8일
0

스프링프레임워크

목록 보기
7/18

AOP(Aspect-Oriented Programming)?

  • AOP는 스프링의 도움으로 구현하는 방법론이다.
  • 우리는 지금까지 OOP(사용자가 원하는 업무기반의 로직)에만 관심을 가지고 있었다.
  • 그러나 사실 사용자요구사항을 수반하기 위해서는 주 업무 로직 외개발자나 관리자가 프로그램을 테스트하는 테스트코드(부가적인 코드)가 존재하게 된다.
  • 사용자 입장에서 바라보는 주 업무로직을 Object Oriented Programming:OOP라고 했다면 개발자나 운영자 관점에서 부가적인 로직과 주 업무 로직(비즈니스 로직)을 나누는 것을 관점 지향 프로그래밍, 즉 AOP라고 한다.
  • 사용자입장에서는 보이지 않지만 개발자가 log테스트를 통해 성능을 확인하고 싶거나, 보안, 트랜잭션 등 불특정 다수의 클래스에 코드를 입력하게 된다. 이를 횡단 관심사(Cross-cutting Concerns: 부가 기능)라고 한다.

1. OOP의 한계?

  • 비즈니스 클래스에 횡단 관심사와 핵심관심사가 공존하게 된다.
  • 메소드의 복잡도가 증가한다.
  • 비즈니스로직을 파악하기 어렵다.
  • 여러 클래스에 횡단 관심사(부가기능) 메서드가 반복적으로 구현되어 있다.
  • 모듈화가 어렵다.

2. AOP의 등장❗️

OOP만으로는 횡단 관심사의 코드분리가 어려웠다. 따라서 OOP의 한계를 해결하기 위해,

비즈니스 로직과 부가적인 로직을 관점(사용자, 개발자)에 따라 모듈화하는 AOP가 등장하게 된 것이다.

3. AOP의 핵심기능과 부가기능

기능내용
핵심기능(Core Concerns)객체가 제공하는 고유의 기능(업무 로직 등)
--------------------
부가기능(CROSS-CUTTING CONCERNS)- 핵심기능을 보조하기 위한 기능
- 로그 추적 로직, 보안, 트랜잭션 기능
- 단독사용x, 핵심 기능과 함께 사용

4. AOP 구현방식

함수 호출 방식

함수의 호출 방식은 이렇다.
과거에는 핵심기능(Core Concern)에 부가기능(CROSS-CUTTING CONCERNS)을 직접 넣고 주석처리를 하며 사용하였지만,

AOP는 클라이언트가 요청을 해오면 프락시(Proxy,중개인)를 통해 부가기능(CROSS-CUTTING CONCERNS)이 실행되고 cross-cutting이 핵심기능(core concern)을 호출하게된다. coreConcern의 코드가 끝난 뒤 부가기능이 있다면 실행, 없다면 실행을 마무리한다.

따라서 흐름상으로 볼 때는 핵심기능(coreConcern)과 부가기능(cross-cutting)의 로직이 분리되어 있음에도 이전의 OOP방식이었던 주석처리를 통한 코드구현과 같은형태(코드의 실행순서가 위에서 아래로 흐르는 형태)로 코드가 실행된다.

5. 어드바이스(Advice)

부가기능을 재사용 하기 위해서는 다음과 같은 의문점이 생긴다.
❓ 어떤 부가기능을? 언제? 어디에 재사용해야 할까?

Advice란, 어떤 부가기능을 언제 사용할지에 대한 정의이다.

  • Advice는 기본적으로 순서를 보장하지 않는다. 따라서 순서를 지정하고 싶다면 @Aspect 적용 단위로 org.springframework.core.annotation.@Order 애너테이션을 적용해야한다.
  • Aspect를 별도의 클래스로 분리하여 어드바이스 단위가 아닌 클래스 단위로 적용할 수 있다.

Advice의 종류 5가지

  1. @Before
  2. @AfterReturning
  3. @AfterThrowing
  4. @After
  5. @Around

1️⃣ @Before

  • 메서드가 실행되기 전에 사용되는 어드바이스이다.
  • 타겟메서드의 조인포인트가 실행되기 전에 부가기능이 실행된다.
  • 리턴타입이 void이다.
  • 작업의 흐름을 변경할 수 없으며 메서드가 종료되면 자동으로 다음 타겟이 호출된다. 그러나 예외가 발생하면 다음코드는 호출되지 않는다.

2️⃣ @AfterReturning

  • 메서드가 정상적으로 실행되었을 때 사용되는 어드바이스이다.

3️⃣ @ArterThrowing

  • 메서드가 예외를 발생시켰을 때 사용되는 어드바이스이다.

4️⃣ @After

  • 메서드의 동작(정상 또는 예외)과는 상관없이 실행한다.
  • @AfterReturning + @ArterThrowing
  • 일반적으로 리소스를 해제하는데 사용한다.

5️⃣ @Around

  • 메서드 비즈니스 로직(핵심기능) 전, 후 모두 사용되는 어드바이스이다.
  • 조인포인트 실행 여부선택, 반환 값 변환, 예외 변환 등이 가능하다.
  • 어드바이스의 첫 번째 파라미터는 ProceedingJointPoint를 사용해야 한다.
  • proceed()를 통해 대상을 실행하며 여러번 실행할 수 있다.
  • Around는 대부분의 기능을 제공하지만 제약이 없기 때문에 문제발생과 역할의 모호함이 있다. 따라서 @Before, @After와 같은 어드바이스를 사용하여 제약을 두면 문제자체가 발생하지 않을 뿐 아니라 역할도 명확히 구분할 수 있는 이점이 있다.
  • @Around 디바이스는 메서드 비즈니스 로직의 전,후 모두 사용이 된다. 이 때 필요한 개념이 JoinPointPointcut이다.

💡 JoinPoint

명칭개념설명
JoinPoint어드바이스가 적용될 수 있는 위치애플리케이션 실행 흐름에서의 특정 포인트를 의미함
기본적으로 어드바이스 메소드에 매개변수로 선언하여 사용한다.

Join포인트가 적용되는 4가지 위치이다.

- 메서드를 호출할 때
- 변수에 접근할 때
- 객체를 초기화할 때
- 객체에 접근할 때

하지만 스프링에서는 메서드를 호출할 때만 JoinPoint라고 한다. 왜냐하면 스프링 AOP는 프록시 방식을 사용하기때문에 스프링 컨테이너가 관리할 수 있는 스프링 빈에만 AOP를 적용할 수 있다. 따라서 조인포인트는 항상 메소드 실행지점으로 제한된다.

📖 JoinPoint 인터페이스의 주요 기능

JoinPoint 인터페이스 메서드기능설명
JoinPoint.getArgs()JoinPoint에 전달된 인자를 배열로 반환합니다.
JoinPoint.getThis()AOP 프록시 객체를 반환합니다.
JoinPoint.getTarget()AOP가 적용된 대상 객체를 반환합니다.
클라이언트가 호출한 비즈니스 메소드를 포함하는 비즈니스 객체를 반환합니다.
JoinPoint.getSignature()조언되는 메서드에 대한 설명을 반환합니다.
클라이언트가 호출한 메소드의 시그니처(리턴타입, 이름, 매개변수) 정보가 저장된 Signature 객체를 반환합니다
Signature? 객체가 선언하는 모든 연산은 연산의 이름, 매개변수로 받아들이는 객체들을 시그니처라고 합니다.
Signature가 제공하는 메서드?
String getName() : 클라이언트가 호출한 메소드의 이름을 반환합니다.
String toLongString() : 클라리언트가 호출한 메소드의 리턴타입, 이름, 매개변수를 패키지 경로까지 포함해서 반환합니다.
String toShortString() : 클라이언트가 호출한 메소드 시그니처를 축약한 문자열로 반환합니다.
JoinPoint.toString()조언되는 방법에 대한 유용한 설명을 인쇄합니다.

📖 ProceedingJoinPoint 인터페이스의 주요 기능

  • proceed() : 다음 어드바이스나 타켓을 호출합니다.

💡 Pointcut

명칭개념설명
Pointcut조인 포인트 중에서 Advice를 적용할 위치를 선별하는 기능부가기능을 사용하고자 하는 메서드 실행지점만 포인트컷으로 선별가능하다.

원하는 곳에만 부가기능을 정의하고자 할 때 Pointcut을 사용한다.


💡 Target

명칭개념사용위치
Target부가기능이 적용될 모듈부가기능을 부여할 핵심기능을 담고있는 모듈이다.
profile
기억을 위한 기록 :>

0개의 댓글