느리더라도 꾸준히

회고록(29)-AOP 본문

(CodeStates)Daily memoir

회고록(29)-AOP

테디규 2022. 12. 14. 22:31

1. 데일리 일기

요즘 피곤하다는 핑계로 햇빛을 안봐서 그런가.. 저녁 이후로 우중충해지는 시간이 많아지는 것 같다.

성장이 잘되고는 있는건지, 학습 내용 정리도 그렇고, 운동도 안하구 있고 그래서 그런가 싶다.

근데 너무 추워서 나가기가 싫은걸..

5초룰 이라는게 있다는데, 생각과 행동사이에 5초에 텀이 있는데 이 사이에 행동하지 않으면 뇌가 왠만하면 자기 자신을 보호하는 쪽으로(아무래도 게으르거나 편한생활) 움직인다고 한다. 그러므로 뇌를 속이기 위해서 좋은 아이디어나 실행하기로 마음먹은건 5초안으로 카운트하고 그냥 하자.

만약 너무 몸과 마음이 지쳐있다면 10분도 못할 것이다. 그렇지 않다면 할 만한 것이다.

못했다고, 안했다고 나를 탓하지 말고 할 수 있는 시스템을 만들기 위해 노력해보자.

2. 오늘 배운 내용.

AOP

AOP 란?

AOP의 탄생배경

OOP는 객체를 단위로 모듈화한 프로그래밍 이다. 여기서 모듈화란 어떠한 로직이나 기능들을 하나의 단위로 묶어놓은 것을 말한다.

  • 우리가 흔히 쓰는 Java 패키지를 모아놓은 Java.base 나 Java.sql 등 처럼 기능들을 묶어놓은것을 말한다.

문제는 트랜잭션, 로깅, 보안등과 같은 부가기능들은 한 객체 속에만 사용되는 것이 아니라, 여러 객체들에서 사용될 수가 있다는 점이다. 이는 부가기느으이 코드 중복을 일으킬 뿐만아니라 코드 수정시 모든 클래스내에 있는 부가기능 코드를 손봐야할 것이다.

OOP가 궁극적으로 추구하는 관심사의 분리가 제대로 일어나지 않은 모습이여 변화와 확장에 유연한 프로그래밍이라고 볼 수도 없다.

AOP란?

AOP는 이러한 OOP의 관심사의 분리의 한계를 보완하는 프로그래밍 방법론이다. 코드를 핵심 관심사(업무 로직)와 횡단관심사(부가기능)을 관점으로 나누어, 한 지점에서 변경사항을 적용하면 어플리케이션 전반에 영향을 줄 수 있도록 모듈화시켜주는 프로그래밍 방법론이라고 할 수 있다.

AOP를 통해 핵심관심사와 횡단 관심사를 분리한다면 OOP를 보완할 수 있게 되는 것이다.

핵심 기능과 부가기능

핵심 기능은 업무 영역, 즉 객체가 제공하는 고유한 기능을 말한다.

부가 기능은 보안, 트랙잭션, 로그 추적등과 같이 핵심 기능(객체들에) 추가적으로 기능을 제공하는 기능들을 말한다.

AOP 에서는 핵심 기능에 부가기능들이 합쳐져서 기능을 처리하게 된다. 그리고 부가기능은 한 지점에서 관리시켜 여러 핵심 기능들에서 사용할 수 있도록 함으로써 완전한 관심사의 분리를 일으킬 수 있다.

AOP 용어정리

Aspect

애플리케이션을 바라보는 관점이 OOP가 클래스로 만든 객체의 기능을 사용하는 것 처럼 AOP는 횡단관심사를 모아놓은 Aspect 모듈을 사용한다.

Aspect는 Pointcut과 Advice를 합친 개념입니다. 아래 에서 하나하나 설명해 보도록 하겠습니다.

Advice

부가기능을 정의해 놓은 코드를 의미합니다.

Pointcut을 통해 접근한 JoinPoint의 핵심 코드에 언제 Aspect(부가기능)을 적용할지 설정 할 수 있습니다.

Spring에서는 Aspect속에 있는 메서드로 정의합니다.

특징

  • Advice간에는 기본적으로는 특별히 순서를 가지지 않습니다.
  • Advice를 가지고 있는 Aspect 모듈끼리는 @Order를 사용하면 순서를 정할 수 있습니다.(클래스단위)
  • Adivce는 조인포인트 전/후로 Aspect를 적용하도록 설정할수 있습니다.
    • Before : 조인 포인트 실행 전
    • After : 조인 포인트 실행 후
    • AfterReturning : 조인포인트가 메서드일때, 예외 없이 실행된 이후
    • AfterThrowing : 조인 포인트에서 예외가 발생했을 때
    • Around : 조인포인트 전/후에서 부가기능 적용 가능
      • 첫번째 파라미터는 ProceedingJoinPoint를 사용해야합니다.
      • ProceedingJoinPoint 가 제공하는 proceed() 를 통해 다음 조인포인트를 실행 시킬 수 있습니다.
      • 다른 Advice와 다르게 proceed()를 사용하여 조인 포인트를 실행시켜야만 합니다.
      • 가장 강력한 어드바이스로 우선순위가 높습니다.(다른 어드바이스보다 먼저 실행되긴함)
      • 조인포인트 실행 전후로 사용가능하므로 매우 강력하지만, 제약이 존재하는 존재하는 다른 어드바이스를 목적에 맞게 사용하여 실수를 미연에 방지하는 것이 좋습니다.(코드 가독성도 더 좋다)

Pointcut

Advice가 적용될 위치를 선별하는 기능을 합니다.

Spring AOP에 서는 메서드 실행 지점만 Pointcut을 선별할 수 있습니다.

특징

Pointcut은 표현식(expression)과 지시자(Designator)로 이루어져 있습니다.

AspectJ은 포인트컷을 편리하게 표현하기 위한 표현식을 제공합니다.

@Pointcut("execution(* transfer(..))") // 포인트컷 표현식(지시자를 담고있다)
private void anyOldTransfer() {} // 포인트컷 서명
  • ..은 하위 패키지를 의미합니다.
  • *은 상위 패키지가 무엇이든 상관 없다는 의미입니다. 특정 패키지를 가기 위해서는 패키지명을 이용해 경로를 작성하면 됩니다.

지시자는 조인포인트를 어떻게 매칭할 것인지를 지시합니다. 프록시를 이용하는 Spring AOP 에서는 메서드 실행시에만 조인포인트를 적용시킬수 있으므로 주로 execution을 사용합니다.

JoinPoint

추상적인 개념으로 AOP를 적용할 수 있는 모든 지점이라고 생각하면 됩니다.

클래스 초기화, 객체의 인스턴스화, 메서드 호출, 필드 접근, 예외 발생과 같은 애플리케이션 실행흐름에서의 각각의 특정 포인트를 의미합니다.

스프링 AOP는 프록시 방식을 사용하므로 메서드 실행 지점의 조인포인트만 선별될 수 있습니다.

JoinPoint 인스턴스는 메서드를 통해 여러 어드바이스와 관련된 기능을 제공해줍니다.

Advisor

Spring에만 있는 AOP용어로 하나의 Advice와 하나의 Pointcut을 의미합니다.

타겟

핵심 기능을 담고 있는 모듈로 부가기능을 부여할 대상이 됩니다.

Advice를 받는 객체로 포인트 컷으로 지정되었을때 부가기능을 받을 수 있습니다.

위빙

포인트 컷으로 결정한 타겟에 부가기능을 적용하는 과정을 말합니다.

이때 핵심기능 코드에는 아무런 영향을 주지않고 Aspect모듈을 연결시켜 부가기능을 추가할 수 있습니다.

이 위빙이 진행될 수 있는 시간대는 아래 세가지 가 존재합니다.

  • 컴파일 타임
  • 로드 타임
  • 런타임 ( Spring AOP)

컴파일 타임과 로드 타임은 AspectJ라는 다른 framework로 동작할때 위빙하도록 지정할 수 있습니다.

반면 Spring AOP는 런타임에 위빙하도록 하고 있습니다.

애노테이션 기반의 Spring AOP

AOP는 다른 AspectJ Framework 와 Spring에서 제공하는 AOP를 사용하여 구현할 수 있습니다. 여기서는 애노테이션을 이용해 Spring AOP를 구현해 봅시다.

Spring AOP는 AspectJ만큼 강력하게 모든 조인포인트에 부가기능을 적용 할 수는 없지만, 메서드 실행시에 부가기능을 적용 할 수 있습니다. 이는 Spring Container의 IOC를 보완해 주므로 SPring을 더 완벽한 OOP를 구현할 수 있는 미들웨어로 만들어 주고 있습니다.

무엇보다 Spring Container가 제공하는 AOP를 사용하면 AspectJ 프레임워크의 AspectJ 컴파일러나 위버 라이브러리에 의존하지 않아도 됩니다. 즉 Spring Container만 사용하더라도 매우 간편하게 AOP를 구현할 수 있다는 의미입니다.

AOP 프록시

스프링 컨테이너가 객체를 빈으로 생성할때 프록시 객체를 같이 생성하게 됩니다. 또한 이때 생성자(메서드)가 호출 실행되므로 Aspect 가 프록시 객체에 적용되게 됩니다.

왜 프록시를 사용할까?

프록시를 사용하게 되면 횡단 관심 객체와 핵심 관심 객체를 느슨한 결합으로 만들어 부가기능을 탈부착 하기 용이하게 만들어 주기 때문입니다.

스프링은 아래 두가지 방식으로 프록시를 구현하고 있습니다.

  • JDK Dynamic Proxy
  • CGLIB Proxy
    해당 내용은 제대로 공부하지 않아 넘어가도록 하겠습니다.ㅠ

애노테이션

@Aspect : 해당 애노테이션을 선언한 클래스는 Aspect 모듈임을 알립니다.
@Pointcut: AspectJ 표현식을 통해 포인트컷을 선별할 수 있습니다.
@Around, @Before, ... : Advice의 종류를 애노테이션을 붙어 사용할수 있습니다. 매개변수 안으로는 @Pointcut을 선언한 메서드가 들어갑니다.

정리후 모르겠는 내용

스프링 프록시 구현방식

  • JDK Dynamic Proxy
  • CGLIB Proxy
Comments