맞긴 합니다만, 꼭 checkbox이어야 문제가 되는 것은 아닙니다.
답은 "_"로 시작하는 파라메터는 가급적 피하거나, 주의해서 써야 한다는 것입니다. 뭐, 쓴다고 스프링이 잡아갈 것은 아니지만요.
SpringMVC의 내부 파라메터 바인딩을 담당하는 WebDataBinder에는 field marker라는 것이 있습니다. 디폴트로는
"_"로 지정되어있습니다. 이게 등장한 기본적인 배경은 checkbox때문인데, checkbox라는 것이 웃기게도 체크를 안하면 파라메터
자체가 아예 날라가지 않습니다. 있으면 가고, 없으면 빈 파라메터가 가는게 아니라, 아예 파라메터 자체가 안나타난다는 것입니다.
이게 문제가 되는 것은 자동 바인딩을 이용하는 SpringMVC에서 unchecked상태의 정보는 전달이 안되기 때문에 그렇습니다.
예를 들어, User 모델에 isAdmin이라는 필드가 있다고 해보죠. 이것을 checkbox로 폼에서 사용했을 경우에, 만약 초기에는
false이고 check가 되면 true로 바뀌는 것은 문제가 없습니다. 그런데 반대로 초기엔 true인데, 체크를 없애면
isAdmin이라는 파라메터가 전달이 안되기 때문에 그 값을 true->false로 바꾸지 않습니다. SpringMVC의 모델에 대한
바인딩은 HTML form에서 전달된 것만 사용하기 때문에 그렇죠. 그래서 이 field marker라는 것이 등장한 것입니다.
field marker는 그냥 빈 파라메터로 존재하면 됩니다. 값이 없어도 그만이죠. 다만 그 파라메터가 전달되게 함으로 해서, 만약
checkbox처럼 폼에는 존재하나 넘어오지 않는 파라메터가 존재하는 경우 그 파라메터 값을 자동으로 reset해주도록되어있습니다.
만약 _isAdmin 파라메터가 존재하는데 isAdmin이라는 파라메터가 아예 없다 그러면, 이것은 checkbox처럼 파라메터가
전달되지 않는 경우라고 생각하고 isAdmin 프로퍼티의 값을 reset(타입에 따라 false나 null 등으로)해줍니다.
isAdmin 파라메터 값이 넘어가면 field marker자체는 무시됩니다.
그렇다면 _isAdmin이라는 field marker로 시작된 파라메터는 못쓰냐? 그건 아니죠. 얼마든지 쓸 수 있습니다. 그 자체로
독립된 파라메터 이름으로 사용가능합니다. 프로퍼티 이름을 _isAdmin이라고 사용하지 않더라도, 직접
reequest.getParameter해서 값을 가져다 쓸 수 있죠.
문제는 이게 isAdmin이라는 프로퍼티를 가진 도메인 객체의 폼이 넘어가는 상황에서 검색조건용 파라메터로 사용될 경우에는 문제가 될
가능성이 있다는 겁니다.
예를 들어 isAdmin이라는 프로퍼티가 있는 User 모델의 값을 바꾸는 폼인데, 폼 자체에는 isAdmin을 사용하지 않는다고
가정해보죠. 그때는 submit시 isAdmin의 값은 절대 바뀌면 안됩니다. 근데, 검색 파라메터 필드의 prefix로 "_"를
사용했다면, 그것을 스프링은 일단 field marker로 생각하고 isAdmin이라는 파라메터가 넘어왔는지 체크하고 없으면 그
프로퍼티를 reset해버립니다. 그러면 원치않게 검색용 파라메터가 field marker로 엉뚱하게 적용되서 모델의 값을 바꿔버릴 위험이
존재한다는 것이죠. 대체로 "_"를 붙이는 이유는 폼의 모델 파라메터와 검색용 파라메터를 구분하기 위함인데, 이게 스프링MVC에서는 큰
혼란을 줄 수 있기 때문에 문제가 됩니다.
따라서 SpringMVC에서는 "_"를 파라메터 이름의 충돌을 피하기 위한 용도로 사용하는 것은 위험하고 피해야 할 것입니다.
레퍼런스에도 안나오는 정보이지요... 이때문에 한번 고생해보면 알게되긴 합니다만.. -_-;;;
그럼 어찌해야 하나?
첫번째 방법은 field marker의 값을 바꾸는 겁니다. MVC내부엔진을 건드려야 하니 별로 좋은 생각이 아닙니다.
두번째 방법은 "_"외의 것을 사용하면 됩니다. 간단하게도 저는 "__"(두개)를 씁니다. MVC가 field marker를 적용할 때는
field marker만큼을 떼고 나머지 것을 가지고 파라메터를 비교합니다. 즉 __isAdmin을 검색파라메터 이름으로 쓰면 일단
필드마커인가 하고 의심은 하지만 _를 뗀, _isAdmin이라는 이름이 있나 보고 없으면 무시합니다. 그래서 안전하죠. 하지만 매번
필드마커로 체크가 들어간다는 성능상의 아주 미미하지만 영향을 주는 단점이 있긴합니다. 다른 적절한 검색용 prefix를 선택하는게 더
나은 방법일겁니다.
##################### 추가 내용 #####################
참 비슷한 개념으로 feild_default prefix도 있습니다. !인데, field marker가 값을 reset(false,
null)한다면 이것은 반대로 해당 필드가 넘어오지 않으면 field default prefix에 설정해놓은 값을 디폴트 값으로
사용한다는 것입니다.
참고로 두개 다 쓰면 어쩌냐 하면, default가 먼저 marker가 나중이니 marker로 reset되버립니다.
그리고 꼭 checkbox의 경우에만 적용할 이유는 없습니다. form에서 javascript등을 이용해서 다이나믹하게 필드를 추가하는
경우에도 유용하게 쓸 수 있습니다. 아무튼 SpringMVC의 잘 안알려진 좋은 기능의 하나입니다.
##################### 추가 내용 1 #####################