비동기 요청 시 AuditorAware 문제

2025. 2. 13. 20:20·트러블 슈팅

Entity의 updatedBy, deletedBy, createdBy 등이 자동으로 업데이트 될 수 있도록 AuditorAware를 구현하여 사용하였다.

 

 

이때 구현 방식은 Http 호출 시 gateway에서 request 객체에 넣어둔 값을 파싱해서 사용하는 방식이다.

조금 더 구체적으로 설명하면, http 호출 시 gateway에서는 accessToken이 존재하는지 검증을 거친다. 이때 accessToken이 존재할 경우 token에서 userId, username 등을 파싱해서 ServletHttpRequest 객체에 담아서 handler로 전달하도록 하였다.

이후 AuditorAware를 request에 담겨있는 userId를 반환하도록 구현하였다.


문제 발생

하지만 비동기 호출의 경우 HttpServletRequest에 값이 없기 때문에 에러가 발생하였다.

내가 진행한 부분에서는 Coupon 발급 처리를 messageQ 를 이용하여 비동기적으로 처리하도록 구현하였다. 이때 message를 받아서 처리할 때는 Http 요청이 발생하지 않기 때문에 HttpServletRequest와 같은 HTTP 요청 객체가 존재하지 않게 되었다.

따라서 이 부분을 해결해줄 필요가 있었다.


문제 해결

다음과 같은 순서로 위의 문제를 해결했다.

  1. Consumer에서 Header로 userId를 전달 받기
  2. ThreadLocal을 생성하여 userId 저장
  3. AuditorAware 사용 시 값이 없으면 ThreadLocal에 저장된 userId 가져와서 사용
  4. 이후 ThreadLocal 비우기

1. Consumer에서 Header로 UserId 전달 받기

위와 같이 consumer는 Header 정보를 넘겨 받도록 하였다.

2. ThreadLocal을 생성하여 userId 저장 및 적용

AuditorAwareImpl 에서 ThreadLocal을 생성해두고 만약 request 객체가 존재하지 않으면 ThreadLocal에 존재하는 값을 가져오도록 하였다.
이때 ThreadLocal에 값을 채우는 부분은 AOP 를 적용하여 진행하였다.

@Aspect
@Component
public class KafkaListenerAspect {

    @Around("@annotation(org.springframework.kafka.annotation.KafkaListener)")
    public Object setUserIdAroundKafkaListener(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        Method method = getMethodFromJoinPoint(joinPoint);
        if (method == null) {
            return joinPoint.proceed();
        }

        try {
            // 메서드 파라미터의 어노테이션을 검사하여 @Header로 마킹된 값을 찾음
            Parameter[] parameters = method.getParameters();
            for (int i = 0; i < parameters.length; i++) {
                Header headerAnnotation = parameters[i].getAnnotation(Header.class);
                if (headerAnnotation != null && "X-USER-ID".equals(headerAnnotation.value())) {
                    // @Header("X-USER-ID")에 해당하는 인자 값 추출
                    String userId = (String) args[i];
                    if (userId != null) {
                        // 사용자 ID를 ThreadLocal에 설정
                        AuditorAwareImpl.setAsyncUserId(userId);
                    }
                }
            }

            // 실제 KafkaListener 메서드 실행
            return joinPoint.proceed();
        } finally {
            // 작업이 완료된 후 ThreadLocal 초기화
            AuditorAwareImpl.clearAsyncUserId();
        }
    }

    // JoinPoint로부터 Method를 얻는 헬퍼 메서드
    private Method getMethodFromJoinPoint(ProceedingJoinPoint joinPoint) {
        try {
            String methodName = joinPoint.getSignature().getName();
            Class<?> targetClass = joinPoint.getTarget().getClass();
            Method[] methods = targetClass.getMethods();
            for (Method method : methods) {
                if (method.getName().equals(methodName) &&
                        method.getParameterCount() == joinPoint.getArgs().length) {
                    return method;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

@KafkaListener 달려있는 위치에서 위 코드가 작동하며, Consumer가 받은 파라미터를 순회하여 @Header의 X-USER-ID를 찾아 ThreadLocal에 저장하도록 하였다.

이를 통해 비동기 처리시 http 요청이 발생하지 않아 HttpServletRequest 객체가 존재하지 않아도 정상적으로 AuditorAware를 구현해서 사용할 수 있도록 했다.

'트러블 슈팅' 카테고리의 다른 글

Jpa 테스트 시 TransactionRequiredException 발생과 해결  (0) 2025.03.16
SpringBoot 버전 업에 따른 RestClient 에러 발생 해결  (0) 2025.02.16
AWS CodeDeploy 에러 해결, 권한 문제  (0) 2025.02.13
QueryDSL 동적 조회 조건 생성 시 조인 문제  (3) 2025.02.13
AWS Fargate에서 Eureka 사용 시 Eureka Client의 IP 추적 문제  (0) 2025.02.13
'트러블 슈팅' 카테고리의 다른 글
  • SpringBoot 버전 업에 따른 RestClient 에러 발생 해결
  • AWS CodeDeploy 에러 해결, 권한 문제
  • QueryDSL 동적 조회 조건 생성 시 조인 문제
  • AWS Fargate에서 Eureka 사용 시 Eureka Client의 IP 추적 문제
shoon95
shoon95
shoon95 님의 블로그 입니다.
  • shoon95
    shoon95 님의 블로그
    shoon95
  • 전체
    오늘
    어제
    • 분류 전체보기 (18)
      • 백엔드 (10)
      • 프로젝트 (1)
      • 트러블 슈팅 (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
    • 학습 정리
  • 공지사항

  • 인기 글

  • 태그

    동시성
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
shoon95
비동기 요청 시 AuditorAware 문제
상단으로

티스토리툴바