티스토리 뷰

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

스프링 애플리케이션은 대부분 특별한 제외를 경우하고는 MVC 웹 어플리케이션에서는 Web Layer, Business Layer, Data Layer 로 정의.

관점 지향은 쉽게 말해 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화 하겠다는 것이다.

여기서 핵심적인 관점은 결국 우리가 적용하고자 하는 핵심 비즈니스 로직이 된다. 또한 부가적인 관점은 핵심 로직을 실행하기위해서 행해지는 데이터베이스 연결, 로깅, 파일 입출력 등을 예로 들 수 있다.

소스 코드상에서 다른 부분에 계속 반복해서 쓰는 코드들을 발견할 수 있는데 이것을 흩어진 관심사 (Crosscutting Concerns)라고 부른다.

흩어진 관심사를 Aspect 로 모듈화하고 핵심적인 비즈니스 로직에서 분리하여 재사용하겠다는 것이 AOP의 취지이다.

그렇다면 AOP 의 사례로는 뭐가 있을까? 정말 간단한 예시를 통해 알아보도록 하자.

AOP 실무 사례 알아보기

1. Logging

일반적으로 간단한 서버 애플리케이션을 구성할 때 아래와 같이 라우팅하는 부분에다가 로그를 찍는다.

@RestController
@RequestMapping("/api")
public class RestApiController {

    @GetMapping("/get/{id}")
    public String get(@PathVariable Long id, @RequestParam String name){
        System.out.printf("id : %s, name : %s", id, name);
        return id + " " + name;
    }

    @PostMapping("/post")
    public User post(@RequestBody User user){
        System.out.println(user);
        return user;
    }

}

하지만 엔드포인트 수가 증가함에 따라 저렇게 일일히 로그를 찍어주는 것은 상당히 불편한 일이다.
똑같이 찍어주는 반복적인 작업은 aop 를 통해 분리할 수 있다.

package com.example.aop.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

@Aspect
@Component
public class ParameterAop {

    @Pointcut("execution(* com.example.aop.controller..*.*(..))")
    private void cut(){}

    @Before("cut()")
    public void before(JoinPoint joinPoint){
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println(method.getName());
        Object[] args = joinPoint.getArgs();
        for (Object obj : args){
            System.out.println(obj.getClass().getSimpleName());
        }
    }

    @AfterReturning(value = "cut()", returning = "returnObj")
    public void afterReturn(JoinPoint joinPoint, Object returnObj){
        System.out.println(returnObj);
    }

}

위와 같이 하면 모든 요청에 로그를 남겨 쉽게 확인할 수 있다.

2. 커스텀 Annotation 을 만들고 특정 요청에서만 로그를 남길 수 있도록 해보자.

@Bean 어노테이션은 method 에만 붙일 수 있고, @Component 어노테이션은 class 에 붙일 수 있다.

댓글