스프링 347

35. 검증로직 분리

사실 역할이 있는 컨트롤러에 떡하니 검증 로직이 있는것도 마음에 안들었다. 예를 들면 addUser면 addUser역할만 해야 하는데 검증로직이 상당한 양을 차지한다. 이번에는 그냥 따로 함수로 빼는 정도일 것 같지만, 나중에는 아예 Bean으로 분리할 것 같다. @Component public class ItemValidator implements Validator { @Override public boolean supports(Class clazz) { return Item.class.isAssignableFrom(clazz); } @Override public void validate(Object target, Errors errors) { Item item = (Item) target; //검증 ..

34. 오류메시지 4

우리가 타입미스매치의 오류 같은 경우는 컨트롤러에서 인자로 들어오는 단계에서 발생한다. @PostMapping("/add") public String addItemV4(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) { //검증 오류 보관 //검증 로직 if(!StringUtils.hasText(item.getItemName())){ bindingResult.rejectValue("itemName", "required"); } if(item.getPrice() == null || item.getPrice() 10..

33. 오류메시지 3

사실 그동안 resolve에 대해 익히 학습하였기 때문에 이 개념까지 자세히 파야 할 이유가 있나 싶긴 하다. 우리가 과거 bindingResult.rejectValue("itemName", "required"); 이렇게 하면 required라는 이름으로 템플릿이 렌더링 될 때 th:errors를 수행할 때 errors.properties에서 저 required 코드를 찾아 넣는다. 이 때, 우선순위가 있다. 더 자세한 순이다. 저 rejectValue를 해 놓으면, new FieldError("item", "itemName", item.getItemName(), false, new String[]{"required.item.itemName"}, null, null) 자동으로 이걸 생성해 주는거다. 근데..

32. 오류 메시지 2

bindingResult.rejectValue("itemName", "required"); rejectValue를 쓰면 훨씬 간단해진다. 필드, 오류메시지코드 사실 이미 bindingResult는 내가 어떤 객체를 참조하는지 알고 있다. 왜냐하면 컨트롤러의 인자로 bindingResult를 받을 때 우리가 에러관리를 하고자 하는 객체의 바로 다음 순서에 인자로 넣었기 때문. 그래서 bindingResult.getObjectName() bindingResult.getTarget() 이렇게 해 보면 item이라는 이름과, item의 toString이 나온다. 그러므로 우리가 기존 쓰던 대상 오브젝트이름, 등을 생략할 수 있다. errors에서 오류 메시지를 찾는것도 꽤나 단순해졌는데, required.ite..

31. 오류 메시지 처리

우리가 오류 메시지를 messages.properties 했던 것 처럼 처리도 가능. (그럼 마찬가지로 국제화 처리도 가능 하려나?) errors.properties 라고 만들고, 오류 메시지를 담아놓으면 됨. required.item.itemName=상품 이름은 필수입니다. range.item.price=가격은 {0} ~ {1} 까지 허용합니다. max.item.quantity=수량은 최대 {0} 까지 허용합니다. totalPriceMin=가격 * 수량의 합은 {0}원 이상이어야 합니다. 현재 값 = {1} 그리고 이제 default로 messages.properties만 들어가는데, 명시적으로 이것도 들어가서 접근할 수 있게 해 줘야 함. spring.messages.basename=messages,..

30. FieldError, ObjectError

@PostMapping("/add") public String addItemV2(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) { //검증 오류 보관 //검증 로직 if(!StringUtils.hasText(item.getItemName())){ bindingResult.addError(new FieldError("item", "itemName", item.getItemName(), false, null, null, "상품 이름은 필수입니다.")); } if(item.getPrice() == null || item.getPrice() < 1000 || item..

29. BindingResult2

BindingResult가 있으면 에러가 나도 오류 정보를 여기에 담아서 컨트롤러를 호출한다. 원래 에러나면 그냥 클라이언트한테 오류코드 뿌려주고 끝이다. BindingResult는 말 그대로 바인딩에 관련한 건데, 만약 Integer인데 문자를 담으면 바인딩에 문제가 있는거니, 그거에 관한 걸 BindingResult에 담고 컨트롤러 로직을 이어간다. 위 같은 경우는 어떤 필드에 담을 데이터의 형식이 안 맞는거니 필드오류이기 때문에, BindingResult가 자동으로 FieldError를 생성해서 담는다. BingResult 검증오류 3가지 타입오류 시 스프링이 자동을 FIeldError 생성해서 BindingResult에 넣음 개발자가 직접 Validator (이건 나중에) 그냥 바인딩과 관련한 타..

28. BindingResult

BindingResult는 스프링에서 제공해주는 에러관련 기능이다. @PostMapping("/add") public String addItemV1(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) { //검증 오류 보관 //검증 로직 if(!StringUtils.hasText(item.getItemName())){ bindingResult.addError(new FieldError("item", "itemName", "상품 이름은 필수입니다.")); } if(item.getPrice() == null || item.getPrice() < 1000 || item...

27. 검증 직접 구현

검증 실패시 검증 실패시, 고객의 불편을 최소화 하기 위해 고객이 보낸 데이터를 다 지워버리지 말고 그대로 담아서 상품등록 폼으로 다시 보여준다. 그리고 뭘 잘못했는지 알려줘서 고객의 불편을 최소화 한다. @PostMapping("/add") public String addItem(@ModelAttribute Item item, RedirectAttributes redirectAttributes, Model model) { //검증 오류 보관 Map errors = new HashMap(); //검증 로직 if(!StringUtils.hasText(item.getItemName())){ errors.put("itemName", "상품 이름은 필수입니다."); } if(item.getPrice() == n..

26. 검증

뭐 예를 들자면 가격이나 수량에 숫자만 들어갔는 지 등.. 근데 검증은 클라이언트에서 한번, 서버에서 한번 2차적으로 이루어져야 함. 클라이언트에서의 검증은 클라이언트의 사용성을 위한 검증이라고 보면 되고, 서버에서의 검증이 진짜 검증이라고 생각하면 됨. 왜냐하면 솔직히 포스트맨같은걸로 데이터 직접 보낸다든가 너무 쉬움. 그래서 최종적으로는 서버에서 검증이 이루어 져야 함. 예제의 요구사항은 타입, 필드 (텍스트 필드, 공백이 포함되어 있는지, 가격이나 수량의 최대 최소) 특정 필드 범위를 넘어서는 (가격 * 수량의 합은 최소 10000 이상이라던지) API 같은 경우 API 스펙을 잘 정의해서 검증 오류를 API 응답 결과에 잘 넘겨주어야 함.