오늘은 참 어이없는 문제로 반나절을 헤메었던 바
이 내용을 꼭 잊지 않기 위해..(바보같았던 스스로를 반성하기 위해)
작성해두려 한다.
회사 업무중에
자주 발생하는 DB오류들을 DB로 넘어가기 전 서버단에서
유효성 검사하도록 처리하는 업무가 있다.
기본적으로는 개발당시에 이런 처리들이 다 되어 있었어야 하는 것 같은데..
우리나라 회사 개발이 다 그렇듯... 빠른 처리와 일단 오픈+_+! 이 목적인지라.. 기본적인 것도 되어 있지 않다.ㅠㅠ
아무튼 오늘의 목적은 유효성 검사를 잘 해서
DB 오류를 뱉어내지 않도록 처리하면 되는 것이었다.
오류 메시지를(열에 대한 값이 너무 큼(실제: 114, 최대값: 100))
보고 원인을 열심히 분석해본 결과
데이터가 컬럼에 정의된 Byte 보다 큰 값이 들어갈 경우에 발생하는 문제였다.
기준은 100Byte 였는데, 이보다 큰 값이 들어왔던 것으로 추정된다.
public void setUrl(String url) throws Exception{
validateLength(url);
this.url = url;
}
private void validateLength(String targetLength) throws Exception{
int length = targetLength.getBytes("MS949").length;
if (length > 100) {
throw new Exception("path 길이가 너무 깁니다. 바이트 제한 : 100");
}
}
도메인 로직에 대략 이런 값으로 셋팅을 했다.
setter를 쓰는건 객체지향적이지 않지만, 컨트롤러의 RequestParam으로 들어올 때 유효성 검사를 하기 위해서는
setter를 재정의해서 유효성 검사를 하는 방법뿐이라고 생각했다.
그렇게 문제없이 개발을 완료했다고 생각하고
테스트를 진행한 결과?!
로그상 오류는 발생하지 않았는데,
클라이언트에선 반응이 없었다...
혹시나 싶어 콘솔창을 열어보니 400 Bad Request가 뙇-!!
난 서버쪽 코드만 만졌는데 클라이언트쪽 오류인 400대 오류가 난다?!
뭐지?!!
라는 생각과 함께 전송된 데이터를 보고자 form data쪽을 비교해봤다.
그런데 전송된 내용은 동일했다.
결국 내가 적용한 서버쪽 소스코드로 인해
발생한 문제인 셈인데,
도무지 알 방법이 없었다.
서버쪽 코드와 클라이언트 오류라... 도저히 매칭이 되질 않았다.
그렇게 반나절에 가까운 시간을 디버깅해보고 뻘짓을 하다가
문득, 컨트롤러의 RequestParam에 값이 들어오는 원리에 대해서 다시금 찾아보았다.
@RequestParam 어노테이션이 적용된 파라미터는 기본적으로 필수 파라미터이다.
(출처: https://devbox.tistory.com/entry/Spring-컨트롤러-메서드의-파라미터-타입 [장인개발자를 꿈꾸는 :: 기록하는 공간])
아아.. 그렇다.
내가 위에 작성한 setUrl 검증 로직은 Vo객체 내에 만들어서 작성하였었다.
그 객체는 다음과 같이 컨트롤러에서 RequestParam 이 적용된(생략해도 기본 적용) 파라미터로 넘어오고 있었다.
@RequestMapping(value = "/insertAjax")
public String insertAjax(HttpServletRequest req, HttpServletResponse res, Vo vo) throws Exception{
...
}
그랬던 것을..
public void setUrl(String url) throws Exception{
validateLength(url); //--> 이부분에서 예외 발생시
this.url = url; //--> 이부분은 실행되지 않음
}
private void validateLength(String targetLength) throws Exception{
int length = targetLength.getBytes("MS949").length;
if (length > 100) {
throw new Exception("path 길이가 너무 깁니다. 바이트 제한 : 100");
}
}
이렇게 유효성 처리를 했으니, 예외가 발생하면서
this.url = url 부분이 애초에 호출이 되지 않아서 setter를 통한 개체 내 값이 정의되지 않고 null 처리가 되었던 것이다.
한참만에 발견한 것이지만,
Bad Request 발생했을 때,
개발자도구 -> Network 탭의 해당 호출 선택 후 Preview 탭을 보면
다음과 같이 null 예외가 발생하고 있었다.
@RequestParam 어노테이션이 적용된 HTTP 요청 파라미터가 존재하지 않으면, 스프링이 잘못된 요청을 의미하는 400 (Bad Request) 응답 코드를 웹 브라우저에 전송하는데 이 경우가 바로 그랬다.
기본적인 건데
생각이 다른쪽에 꽂히니까 바보짓을 했던 하루였다.
기록해두고 잊지 말아야 겠다