From dcf66acfb185dd0a089792c42ce91bd508db09b1 Mon Sep 17 00:00:00 2001 From: Sumin Hwang <163857590+tnals0924@users.noreply.github.com> Date: Tue, 22 Sep 2026 16:44:13 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20401=20=EC=9D=B8=EC=A6=9D=20=EC=8B=A4?= =?UTF-8?q?=ED=8C=A8=20=EB=A1=9C=EA=B7=B8=20=EB=A0=88=EB=B2=A8=EC=9D=84=20?= =?UTF-8?q?DEBUG=EB=A1=9C=20=EB=82=AE=EC=B6=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stream/api/common/GlobalExceptionHandler.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/api/common-api/src/main/java/kr/ac/kookmin/stream/api/common/GlobalExceptionHandler.java b/api/common-api/src/main/java/kr/ac/kookmin/stream/api/common/GlobalExceptionHandler.java index 3d364ca3..276fb937 100644 --- a/api/common-api/src/main/java/kr/ac/kookmin/stream/api/common/GlobalExceptionHandler.java +++ b/api/common-api/src/main/java/kr/ac/kookmin/stream/api/common/GlobalExceptionHandler.java @@ -23,8 +23,14 @@ public class GlobalExceptionHandler { @ExceptionHandler(BusinessException.class) public ResponseEntity> handleBusiness(BusinessException e) { - log.warn("[requestId={}, userId={}] ({}) {}", - MDC.get(REQUEST_ID), MDC.get(USER_ID), e.getErrorCode().name(), e.getMessage()); + // 인증 실패(401)는 인터넷에 노출된 서버에서 스캐너·봇으로 인해 상시 발생하는 정상 트래픽이므로 DEBUG로 낮춘다 + if (e.getErrorCode().status() == ErrorStatus.UNAUTHORIZED) { + log.debug("[requestId={}, userId={}] ({}) {}", + MDC.get(REQUEST_ID), MDC.get(USER_ID), e.getErrorCode().name(), e.getMessage()); + } else { + log.warn("[requestId={}, userId={}] ({}) {}", + MDC.get(REQUEST_ID), MDC.get(USER_ID), e.getErrorCode().name(), e.getMessage()); + } return ResponseEntity.status(e.getErrorCode().status()).body(ApiResponse.error(e)); } From 624d6fc5c4dd6115280479487b361da53e5547c7 Mon Sep 17 00:00:00 2001 From: Sumin Hwang <163857590+tnals0924@users.noreply.github.com> Date: Tue, 22 Sep 2026 16:44:13 +0900 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20=EC=8A=A4=EC=BA=90=EB=84=88=20?= =?UTF-8?q?=EB=85=B8=EC=9D=B4=EC=A6=88=20=EA=B2=BD=EB=A1=9C=EB=A5=BC=20?= =?UTF-8?q?=EC=95=A1=EC=84=B8=EC=8A=A4=20=EB=A1=9C=EA=B7=B8=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=A0=9C=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/ac/kookmin/stream/logging/LoggingExclusions.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gateway/logging/src/main/java/kr/ac/kookmin/stream/logging/LoggingExclusions.java b/gateway/logging/src/main/java/kr/ac/kookmin/stream/logging/LoggingExclusions.java index 115a5dba..1425fb1b 100644 --- a/gateway/logging/src/main/java/kr/ac/kookmin/stream/logging/LoggingExclusions.java +++ b/gateway/logging/src/main/java/kr/ac/kookmin/stream/logging/LoggingExclusions.java @@ -1,20 +1,26 @@ package kr.ac.kookmin.stream.logging; import jakarta.servlet.http.HttpServletRequest; +import java.util.Set; import lombok.AccessLevel; import lombok.NoArgsConstructor; /** * 로깅 필터가 건너뛸 요청 판별. 헬스체크는 빈번히 폴링되므로 MDC·액세스 로그 대상에서 제외한다. * 경로는 액추에이터 기본값이자 security 모듈 {@code PublicEndpoints.HEALTH_CHECK}와 같은 값이다. + * 또한 브라우저·크롤러·스캐너가 상시 찔러보는 노이즈 경로도 제외한다. */ @NoArgsConstructor(access = AccessLevel.PRIVATE) final class LoggingExclusions { private static final String HEALTH_CHECK_PATH = "/actuator/health"; + // 실존 엔드포인트가 아니지만 브라우저·크롤러·봇 스캐너가 상시 요청해 401 노이즈만 남기는 경로 + private static final Set NOISE_PATHS = Set.of("/", "/robots.txt", "/favicon.ico"); + static boolean isExcluded(HttpServletRequest request) { String path = request.getRequestURI(); - return path.equals(HEALTH_CHECK_PATH) || path.startsWith(HEALTH_CHECK_PATH + "/"); + return path.equals(HEALTH_CHECK_PATH) || path.startsWith(HEALTH_CHECK_PATH + "/") + || NOISE_PATHS.contains(path); } }