From f76e060694fe73a9099e15daddefa0147e995056 Mon Sep 17 00:00:00 2001 From: Roy Date: Tue, 8 Sep 2026 20:20:26 +0900 Subject: [PATCH] =?UTF-8?q?#441=20[Fix]=20=ED=95=84=EC=88=98=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EB=88=84?= =?UTF-8?q?=EB=9D=BD=20=EC=8B=9C=20500=20=EB=8C=80=EC=8B=A0=20400=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MissingServletRequestParameterException 이 전역 핸들러의 400 목록에 없어 마지막 Exception 핸들러로 떨어졌다. 필수 파라미터를 빠뜨리면 클라이언트 잘못인데도 COMMON_500 이 나갔다. - 광고 전용 문제가 아니다. 필수 쿼리 파라미터를 쓰는 모든 API 가 함께 영향을 받는다. - 스웨거에서 파라미터를 채우지 않고 Execute 하면 바로 재현된다. --- .../global/common/exception/GlobalExceptionHandler.java | 2 ++ .../picke/domain/ad/controller/AdApiIntegrationTest.java | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/com/swyp/picke/global/common/exception/GlobalExceptionHandler.java b/src/main/java/com/swyp/picke/global/common/exception/GlobalExceptionHandler.java index aab34389..f636a717 100644 --- a/src/main/java/com/swyp/picke/global/common/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/swyp/picke/global/common/exception/GlobalExceptionHandler.java @@ -8,6 +8,7 @@ import org.springframework.security.access.AccessDeniedException; // 추가 import org.springframework.security.authorization.AuthorizationDeniedException; // 추가 import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; @@ -40,6 +41,7 @@ public ResponseEntity> handleValidation(MethodArgumentNotValid @ExceptionHandler({ HttpMessageNotReadableException.class, MethodArgumentTypeMismatchException.class, + MissingServletRequestParameterException.class, ConstraintViolationException.class, IllegalArgumentException.class }) diff --git a/src/test/java/com/swyp/picke/domain/ad/controller/AdApiIntegrationTest.java b/src/test/java/com/swyp/picke/domain/ad/controller/AdApiIntegrationTest.java index 7cc71318..63a27239 100644 --- a/src/test/java/com/swyp/picke/domain/ad/controller/AdApiIntegrationTest.java +++ b/src/test/java/com/swyp/picke/domain/ad/controller/AdApiIntegrationTest.java @@ -119,6 +119,15 @@ void recordImpressions_accumulatesIntoSameDailyRow() throws Exception { .isEqualTo(2L); } + @Test + @DisplayName("필수 파라미터가 빠지면 500이 아니라 400을 준다") + void findAds_missingRequiredParamIsBadRequest() throws Exception { + // 전역 핸들러가 MissingServletRequestParameterException 을 잡지 못해 500 으로 새던 자리다. + // 광고 전용 문제가 아니라 필수 쿼리 파라미터를 쓰는 모든 API 가 같이 영향을 받는다. + mockMvc.perform(get("/api/v1/ads")) + .andExpect(status().isBadRequest()); + } + @Test @DisplayName("노출 집계는 한 번에 밀어 넣을 수 있는 소재 수를 제한한다") void recordImpressions_rejectsOversizedBatch() throws Exception {