[ Whitelabel Error Page ]
애니 상세 페이지에서 ‘수정’ 버튼을 눌렀는데
수정 페이지로 이동하지 않고 404가 발생했다.
브라우저
: 'Whitelabel Error Page'
서버 로그
: 'No mapping for GET /animeEditPage/3'
: 또는 핸들러를 찾지 못했다는 형태의 메시지
핵심은 요청은 들어오는데 스프링이 해당 요청을 처리할
컨트롤러 메서드를 찾지 못해 매핑이 실패한 케이스다.
원인 후보(의심 지점) 포착)
이 상황에서 제일 먼저 의심할 지점은 2가지다.
- URL 경로가 컨트롤러 매핑과 다름(주소 불일치)
- URL 패턴은 같아 보이는데 PathVariable 방식과
RequestParam 방식이 서로 섞여 있음(패턴 불일치)
이 중에서 이번 케이스는 2번이었다.
- PathVariable
: URL 경로 자체에 값이 들어감.
: 예) /animeEditPage/3 - RequestParam
: 쿼리스트링으로 값이 들어감.
: 예) /animeEditPage?animeId=3
[ 가설 수립: jsp의 '요청 URL'이 잘못됐다 ]
‘JSP에서 보내는 요청 형태’와
‘컨트롤러가 받으려는 형태’가 다르면
스프링은 아예 다른 URL로 인식한다.
즉,
- JSP 요청: /animeEditPage/3
- 컨트롤러 기대: /animeEditPage?animeId=3
이 상태면 스프링 입장에서는
‘매핑된 핸들러가 없음’이 되어 404가 발생한다.
[ 확인 : animeEdit 컨트롤러 매핑 검증 ]
확인 방법은 단순하다.
- 브라우저 주소창에서 실제 호출 URL 확인
- 컨트롤러의 @GetMapping 패턴 확인
- 둘이 완전히 같은 형태인지 비교
이 비교에서 딱 어긋나면 ‘핸들러 매핑 실패’가 난다.
오류를 야기한 코드(혼용 케이스)
JSP는 PathVariable 형식으로 보냈는데
<a href="${cp}/animeEditPage/${animeData.animeId}">수정</a>
컨트롤러는 RequestParam 형식으로 받으려고 함
@GetMapping("/animeEditPage")
public String animeEditPage(
@RequestParam("animeId") int animeId,
HttpSession session,
Model model
) {
// ...
}
실제 요청 URL vs 기대 URL 불일치 문제
- JSP 요청: /animeEditPage/3
- 컨트롤러 기대: /animeEditPage?animeId=3
→ 결과: Handler Mapping 실패(404 / No mapping)
[ 해결 : 요청과 기대 URL 방식 통일 ]
해결은 ‘한 방식으로 통일’이다.
아래 2가지 중 하나로만 고정하면 정상 동작한다.
1) 정상 동작 패턴 A: PathVariable 방식으로 통일
(정상) JSP 요청 코드
<c:if test="${sessionScope.memberRole eq 'ADMIN'}">
<a href="${cp}/animeEditPage/${animeData.animeId}">수정</a>
</c:if>
(정상) 컨트롤러 매핑 코드
@GetMapping("/animeEditPage/{animeId}")
public String animeEditPage(
@PathVariable("animeId") int animeId,
HttpSession session,
Model model
) {
// ...
return "animeedit";
}
(정상) 실제 요청 URL 형태
/animeEditPage/3
@PathVariable은 'URL 경로에 포함된 값'을
컨트롤러 파라미터에 바인딩하는 방식이다.
2) 정상 동작 패턴 B: RequestParam 방식으로 통일
(정상) JSP 요청 코드
<c:if test="${sessionScope.memberRole eq 'ADMIN'}">
<a href="${cp}/animeEditPage?animeId=${animeData.animeId}">수정</a>
</c:if>
(정상) 컨트롤러 매핑 코드
@GetMapping("/animeEditPage")
public String animeEditPage(
@RequestParam("animeId") int animeId,
HttpSession session,
Model model
) {
// ...
return "animeedit";
}
(정상) 실제 요청 URL 형태
/animeEditPage?animeId=3
@RequestParam은 'URL의 쿼리 파라미터(요청 파라미터) 값'을
컨트롤러 파라미터에 바인딩하는 방식이다.
이번 케이스는 이 방식으로 통일해서 해결했다.
[ 결론 ]
이번 오류의 이름을 한 줄로 정리하면
요청 매핑 불일치 오류
- URL 패턴 불일치로 인한 핸들러 매핑 실패
- PathVariable/RequestParam 혼용으로 발생한
URL 매핑 불일치(Handler Mapping 실패)
추가로, 비슷하게 404가 나는 케이스로는
‘HTTP 메서드 불일치’도 자주 있으니
(= GET으로 호출했는데 컨트롤러는 POST만 열어둔 경우)
404가 뜨면, URL 패턴 + HTTP 메서드까지
같이 확인하는 게 정석이다.