얼쑤의 연습 통계 API는 시작일과 종료일을 받아 해당 기간의 연습 시간과 횟수를 돌려줍니다. 요약 API는 바로 앞 기간의 통계도 함께 제공합니다. 두 날짜를 Spring의 @DateTimeFormat(iso = ISO.DATE)로 받아 LocalDate로 변환했습니다. 그러면 2026/10/01처럼 형식이 어긋난 날짜는 컨트롤러가 실행되기 전에 400으로 거절됩니다.
리뷰에서 날짜 형식 검사를 통과하는 값이 500을 냈습니다. 요약 API에 시작일과 종료일을 모두 **-999999999-01-01**로 보내면 두 값은 LocalDate로 변환됐습니다. 길이도 하루여서 기존 기간 제한을 통과했습니다. 직전 기간을 구하려고 시작일에서 하루를 빼는 순간 LocalDate의 범위를 벗어났고, DateTimeException이 500으로 이어졌습니다.
파싱 후 연도와 기간 검사
컨트롤러에서 날짜의 순서와 연도를 먼저 검사하도록 바꿨습니다. 시작일과 종료일을 모두 포함한 기간은 최대 366일이고, 허용 연도는 1001년부터 9998년까지입니다. 요청으로 받은 날짜에서 앞 기간을 구하거나 마지막 날의 다음 날을 구할 때 MySQL의 DATETIME 연도 끝값을 피하려고 잡은 범위입니다.
private fun rangeOf(from: LocalDate, to: LocalDate): DateRange? =
if (from > to || from.year < 1001 || to.year > 9998) null
else DateRange(from, to).takeIf { it.length <= 366 }
요약과 날짜별 조회는 이 함수를 공유합니다. 범위 검사를 통과하지 못하면 서비스 호출 전에 400과 INVALID_REQUEST를 반환합니다. 필수 날짜가 빠지거나 날짜 변환에 실패하는 경우에도 같은 오류 코드를 돌려줍니다. 화면은 하나의 응답 형식으로 입력을 다시 확인하도록 안내할 수 있습니다.
366일 허용, 367일 거절
컨트롤러 검사에서는 처음 500을 냈던 극단값과 1000년, 9999년, 367일 요청을 두 API에 각각 보내 400과 오류 코드를 확인했습니다. 날짜별 조회에 2028년 1월 1일부터 12월 31일까지를 보내는 366일 검사에서는 200을 확인했습니다. 저장소 대역의 연습 시간 조회도 허용 요청의 한 번으로 확인했습니다. 회원 ID만 기록할 때는 같은 회원의 거절 요청이 실수로 조회를 호출해도 잡을 수 없어서, 호출 횟수까지 보도록 바꿨습니다.
조회 하한이 0999년인 요청 검증
OpenAPI의 설명은 1000~9999년, 컨트롤러의 허용 범위는 1001~9998년으로 적혀 있습니다. 입력 단계의 실제 동작은 컨트롤러와 위 검사에서 확인한 범위를 따릅니다.
1001-01-01부터 1002-01-01까지의 366일 요청은 입력 검사를 통과합니다. 이때 직전 기간은 한국 시간 0999-12-31 00:00부터 시작합니다. 계산값이 DB에 넘어갈 때 오류가 나는지 확인하려고, 실제 Spring 앱을 폐기용 MySQL 8.4.9에 연결하고 HTTP로 요청했습니다. MySQL 로그에서 요약 쿼리의 시작 하한이 UTC **0999-12-30 15:00:00**으로 전달된 것을 확인했습니다.
기간을 구분하는지도 보려고 네 행을 준비했습니다. 직전 기간에 20초와 10초, 현재 기간의 첫 시각에 60초, 현재 기간이 끝난 직후에 40초를 넣었습니다. 직전 기간의 두 번째 행과 현재 기간의 첫 행은 1초 차이입니다.
| 요청 | 실제 응답 |
|---|---|
| 366일 요약 | HTTP 200. 현재 기간 60초, 직전 기간 30초 |
| 같은 366일의 날짜별 조회 | HTTP 200. 366개 날짜, 첫날 60초·마지막 날 0초 |
| 같은 시작일에서 하루 늘린 367일 요약 | HTTP 400 INVALID_REQUEST |
시작일과 종료일이 모두 1000-12-31인 요약 | HTTP 400 INVALID_REQUEST |
요약 조회에 0999년 하한이 들어갔지만, 이 환경에서는 DB가 조회를 받아 두 기간의 합계를 각각 계산했습니다. 이 결과는 0999년 값을 조회 하한으로 넘긴 경우에 한정됩니다. OpenAPI의 허용 연도 표기와 실제 입력 검사의 차이는 이 재현에서 그대로 확인할 수 있는 문서 문제입니다.

댓글
댓글과 반응은 GitHub 계정으로 로그인해 남길 수 있어요.