문제 상황

프로듀서 → 컨슈밍 아웃박스 상황에서 해당 메서드가 핵심 비즈니스 로직을 전부 수행하고 리턴할 때 에러 발생

    @KafkaListener(
        topics = {Topic.INCREASE_STOCK_EVENT},
        groupId = "on-ssgdeal-group-increase-stock",
        containerFactory = "kafkaListenerContainerFactory"
    )
    public void listenIncreaseStockEvent(
        @Payload String message,
        @Header(KafkaHeaders.RECEIVED_TOPIC) String topic,
        Acknowledgment ack
    ) {
        try {
            log.info("메시지를 소비합니다. Topic : {}, message :{}", topic, message);
            EventEnvelope<IncreaseStockEvent> envelope =
                EventEnvelope.fromJson(message, IncreaseStockEvent.class);
            IncreaseStockEvent payload = envelope.payload();
            productService.increaseStock(payload.toDto());
            ack.acknowledge();
        } catch (Exception e) {
            log.error("메시지 소비에 실패했습니다. => {}", e.getMessage());
            throw e;
        }
    }

핵심 에러 사항

no thread-bound request found: are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? if you are actually operating within a web request and still receive this message, your code is probably running outside of dispatcherservlet: in this case, use requestcontextlistener or requestcontextfilter to expose the current request.

원인

현재 JpaAuditingConfig 상황

→카프카의 전송은 Web이 아니라 httpServletRequest로 해당 요청이 들어오지 않아

UpdateAt을 수행하지 못하고 있었음

 @Bean
    public AuditorAware<Long> loginUserAuditorAware() {
        return () -> {
            String requestUri = httpServletRequest.getRequestURI();
            String requestMethod = httpServletRequest.getMethod();

            if (
                isCreateUserRequest(requestUri, requestMethod) ||
                    isSignupAuthRequest(requestUri, requestMethod) ||
                    isLoginAuthRequest(requestUri, requestMethod)
            ) {
                return Optional.empty();
            }

            Passport passport = passportUtil.getPassportBy(httpServletRequest);
            return Optional.of(passport.getUserId());
        };
    }

문제 해결 과정

MDC vs ThreadLocal

구분 MDC ThreadLocal
목적 로깅 시 컨텍스트 정보 추적 쓰레드별 변수 격리
사용 편의성 로깅에 최적화된 API 제공 Low-level API 직접 사용
내부 구현 ThreadLocal 기반 Java 언어 차원의 기능
스레드 풀 위험성 **MDC.clear()**로 정리 가능 수동 정리 필요 (메모리 누수 가능성)
사용 예시 로그에 사용자 ID, 요청 ID 추가 DB 연결 관리, 보안 컨텍스트