Spring 관점지향 프로그래밍 (AOP)

정종일·2023년 3월 15일
0

Spring

목록 보기
4/18

(Aspect Oriented Programming)관점지향 프로그래밍이란?

정의

객체 지향 프로그래밍과 완전하게 다른 프로그래밍이 아니라 객체 지향 프로그래밍을 돕는 보조 기법이다. 로직을 핵심적인 관점, 부가적인 관점으로 나누어 보고 그 관점을 기준으로 모듈화하는 것이다. (흩어진 관심사(Crosscutting Concerns)를 모듈화)

*모듈화: 공통된 기능이나 로직을 하나의 단위로 묶는 것

왜 필요할까?

우리가 프로그래밍을 할 때 불가피하게 중복 코드가 자주 발생하는 경우가 있다. (로깅, 트랜잭션 등등) 예를 들어 모든 비즈니스 로직이 실행될 때마다 로그를 남긴다고 해보자. 일일이 로그를 남기는 코드를 작성한다면 가독성도 떨어지고 추후 유지보수 시 다시 일일이 수정해주어야 하는 단점이 있다. 이러한 문제를 해결하기 위해 등장한 것이 관점 지향 프로그래밍이다.

장점

  • 로직 중 공통된 부분을 분리시켜 핵심 로직을 클린하게 유지할 수 있다.
  • 코드의 가독성이 높아지고 유지보수가 편리해진다.
  • 모듈을 수정해도 다른 로직에 영향이 가지 않는다.
  • 모듈 적용 대상을 정할 수 있다.

AOP 관련 용어

Aspect: 흩어진 관심사를 모듈화 한 것

Target: Aspect(모듈)를 적용하는 곳. 클래스, 메서드 등

Advice: 실질적으로 어떤 일을 해야 할 지에 대한 것, 실질적인 부가기능을 담은 구현체

Join Point: Advide가 적용될 위치 혹은 끼어들 시점. 스프링에서 Join Point는 언제나 메서드 실행 시점을 의미

Point Cut: Join Point를 구체화. “A라는 메서드의 진입 시점에 호출할 것”처럼 구체적으로 Advice가 실행될 시점을 의미

AOP Annotation

@Around("${pattern}")

지정된 패턴에 해당하는 메서드 실행 전, 후 모두에서 동작한다. Around 어노테이션이 붙은 메서드의 반환 값은 Object여야 한다.

@Before("${pattern}")

지정된 패턴에 해당하는 메서드 실행 전 동작한다. Before 어노테이션이 붙은 메서드의 반환 값은 void여야 한다. (지정 메서드 실행 전에 동작해 반환값이 없기 때문)

@After("${pattern}")

지정된 패턴에 해당하는 메서드가 실행된 후 동작한다. After 어노테이션이 붙은 메서드의 반환 값은 void여야 한다. (지정 메서드 실행 후에 동작해 반환값이 없기 때문)

@AfterRunning("${pattern}")

지정된 패턴에 해당하는 메서드가 성공적으로 결과값을 반환한 후 동작한다.

@AfterThrowing("${pattern}")

지정된 패턴에 해당하는 메서드가 수행 중 예외를 던지면 동작한다.

Spring AOP 와 AspectJ

Spring AOP

  • Spring에서 제공하는 스프링 AOP는 프록시 기반의 AOP 구현체이다.
  • 프록시 객체를 사용하는 것은 접근 제어 및 부가 기능 추가를 위해서이다.
  • Spring AOP는 Spring Bean에만 적용할 수 있다.
  • 모든 AOP기능을 제공하는 것이 아니라 중복 코드, 프록시 클래스 작성의 번거로움 등의 문제를 해결하기 위한 솔루션을 제공하는 것이 목적
  • Spring AOP는 순수 Java로 구현되었기 때문에 특별한 컴파일 과정이 필요없다.

AspectJ

AspectJ는 CGlib이라는 바이트 조작 라이브러리를 사용해 타깃 오브젝트의 바이트를 고쳐 부가기능을 직접 넣어주는 바이트 조작을 사용한다. 그래서 우리가 만든 코드에서는 부가기능이 분리되어 있지만 바이트 코드에서는 핵심 기능과 부가 기능이 섞여있는 구조이다. 장점으로는

  • Spring 컨테이너에 종속되지 않는다.
  • 프록시 방식보다 유연하고 강력한 AOP 제공이 가능하다.

Spring AOP 구현

개발 환경

  • SpringBoot 2.6.0
  • gradle 7.5
  • Java 11

build.gradle

// AOP 의존성 추가
	implementation 'org.springframework.boot:spring-boot-starter-aop'

실행 결과

TimeLogAspect.java

@Component
@Slf4j
@Aspect
public class TimeLogAspect {

    @Around("execution(* com.ssafy.greenEarth.controller.*.*(..))")
    public Object logAsp(ProceedingJoinPoint pjp) throws Throwable {
        log.info("Start Aspect");
        Object reVal = pjp.proceed();
        log.info("End Aspect");
        return reVal;
    }
}

마무리

관점지향 프로그래밍을 공부하며 볼륨이 큰 프로젝트 및 다수의 중복이 발생하는 클래스 구현 시 유용할 것이라는 생각이 들긴 했지만 볼륨이 작은 프로젝트나 중복이 발생하되 내부 로직이 조금씩 다른 경우 관점지향 프로그래밍을 사용하면 배보다 배꼽이 더 큰 상황이 발생할 수 있을 것 같다는 생각이 든다. 역시 무작정 사용하기보다 상황에 따른 유연한 사용이 필요해보인다.

profile
제어할 수 없는 것에 의지하지 말자

0개의 댓글