웹 개발

AOP, Custom Annotation 활용기

ultramancode 2023. 11. 7. 19:46

 

https://tw-dev.tistory.com/151

 

Schema 여정기 Multi-Tenancy(feat. PostgreSQL)

* PostgreSQL에는 Schema라는게 존재한다. MySQL에서는 Schema가 테이블을 의미하지만, PostgreSQL에서는 테이블의 집합을 의미, 하나의 데이터베이스를 논리적으로 나누는 개념이다. -> MySQL의 논리 데이터

tw-dev.tistory.com

앞전 멀티테넌시 관련해서 추가 요청 사항이 생겼다. 필터 단계에서 처리하는 것 외에도 컨트롤러에서 파라미터를 통해서 스키마를 바꿔줘야하는 경우가 생겼다. 

 

처음에는 컨트롤러에서 해당 부분을 따로 처리했는데 그러다 보니까 너무 반복되는 코드가 많아진다는 걸 느꼈다.

 

마침 전에 공부했던 AOP와 커스텀 어노테이션이 떠올라서 이 기회에 활용하면 좋겠다 싶어서 바로 써먹게 됐다!! 

 

 


1. 먼저 커스텀 어노테이션을 런타임 시점에도 작동하고, 파라미터와 메소드를 대상으로 작동하도록 만들었다.

@Retention(value = RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD})
public @interface ExampleAnnotation {

}

 

 

2. @Aspect를 활용하여 AOP 구현

   - 처음에 파라미터를 어떻게 추출하는 몰라서 애를 먹었다.

   - 먼저 해당 조인 포인트에서 인자들을 전부 받는 args 변수 생성

   - 조인 포인트에서 메소드를 가져오고, 여러 어노테이션을 반복문 돌면서 내가 원하는 커스텀 어노테이션이 존재한다면

   - 해당 순번의 인자를 받아서 멀티 테넌시를 활용해서 스키마를 변경하도록 했다.

 

@Aspect
@Slf4j
@Component
@RequiredArgsConstructor
public class ExampleAspect {
    private final TenantIdentifierResolver tenantIdentifierResolver;

    @Around("execution(* exmaple1.api1..*.*(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        for (int i = 0; i < parameterAnnotations.length; i++) {
            for (Annotation annotation : parameterAnnotations[i]) {
                if (annotation instanceof ExampleAnnotation) {
                    log.info("{} : 스키마 변경", args[i]);
                    tenantIdentifierResolver.setCurrentTenant((String) args[i]);
                }
            }
        }
        try {
            // 원래 메서드 실행
            return joinPoint.proceed();
        } finally {
            // 메서드 실행 후 스키마 제거
            tenantIdentifierResolver.removeCurrentTenant();
        }
    }
}