2 분 소요

 인프런 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술편을 학습하고 정리한 내용 입니다.

Form 전송 객체 분리 - 개발

Item 도메인 클래스 검증 코드 제거

이제 Item에서 검증은 사용하지 않을 것이기 때문에 검증 코드 제거.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data  
public class Item {  
  
    private Long id;  
    private String itemName;  
    private Integer price;  
    private Integer quantity;  
    
    public Item() {}  
  
	public Item(String itemName, Integer price, Integer quantity) {  
	    this.itemName = itemName;  
	    this.price = price;  
	    this.quantity = quantity;  
	}
}

검증 객체 만들기

먼저 패키지를

다음과 같이 hello.itemservice.web.validation.form으로 만들었고

거기에 dto인 ItemSaveForm, ItemUpdateForm을 만들었다.

ItemSaveForm

저장할 때 사용할 dto, 그러므로 id는 필요 없다 (자동 생성)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Data  
public class ItemSaveForm {  
  
    @NotBlank  
    private String itemName;  
  
    @NotNull  
    @Range(min = 1000, max = 1000000)  
    private Integer price;  
  
    @NotNull  
    @Max(9999)  
    private Integer quantity;  
  
}

ItemUpdateForm

여기선 id가 중요하다. 그리고 수량 (quantity)에 제한이 없어진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Data  
public class ItemUpdateForm {  
  
    @NotNull  
    private Long id;  
  
    @NotBlank  
    private String itemName;  
  
    @NotNull  
    @Range(min = 1000, max = 1000000)  
    private Integer price;  
  
    // 수정에서는 수량은 자유롭게 변경 가능  
    private Integer quantity;  
  
}

이제 이 두 dto를 사용하도록 컨트롤러 코드를 수정하자.

ValidationItemControllerV4

등록

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@PostMapping("/add")  
public String addItem(@Validated @ModelAttribute("item") ItemSaveForm form, BindingResult bindingResult, RedirectAttributes redirectAttributes) {  
  
    //특정 필드 예외가 아닌 전체 예외  
    if (form.getPrice() != null && form.getQuantity() != null) {  
        int resultPrice = form.getPrice() * form.getQuantity();  
        if (resultPrice < 10000) {  
            bindingResult.reject("totalPriceMin", new Object[]{10000,  
                    resultPrice}, null);  
        }  
    }  
  
    // 검증에 실패하면 다시 입력 폼으로 가야함.  
    if (bindingResult.hasErrors()) {  
        log.info("errors: {}", bindingResult);  
        return "validation/v4/addForm";  
    }  
  
    // 성공 로직 (setter는 지양하자..)  
    Item item = new Item();  
    item.setItemName(form.getItemName());  
    item.setPrice(form.getPrice());  
    item.setQuantity(form.getQuantity());  
  
    Item savedItem = itemRepository.save(item);  
    redirectAttributes.addAttribute("itemId", savedItem.getId());  
    redirectAttributes.addAttribute("status", true);  
    return "redirect:/validation/v4/items/{itemId}";  
}

@Validated @ModelAttribute("item") ItemSaveForm form 이렇게 바꿨고,

이제 리포지토리에 넘길 객체를 따로 만들어 줬다.. 근데 setter말고 생성자나 builder 패턴을 사용 하는게 좋을 듯 하다.

수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@PostMapping("/{itemId}/edit")  
public String edit(@PathVariable Long itemId, @Validated @ModelAttribute("item")ItemUpdateForm form, BindingResult bindingResult) {  
  
    //특정 필드 예외가 아닌 전체 예외  
    if (form.getPrice() != null && form.getQuantity() != null) {  
        int resultPrice = form.getPrice() * form.getQuantity();  
        if (resultPrice < 10000) {  
            bindingResult.reject("totalPriceMin", new Object[]{10000,  
                    resultPrice}, null);  
        }  
    }  
  
    if (bindingResult.hasErrors()) {  
        log.info("errors: {}", bindingResult);  
        return "validation/v4/editForm";  
    }  
  
    // 성공 로직 (setter는 지양하자..)  
    Item item = new Item();  
    item.setItemName(form.getItemName());  
    item.setPrice(form.getPrice());  
    item.setQuantity(form.getQuantity());  
  
    itemRepository.update(itemId, item);  
    return "redirect:/validation/v4/items/{itemId}";  
}

수정도 등록과 똑같다.

주의

@ModelAttribute("item")item이름을 넣어준 부분을 주의하자. 이것을 넣지 않으면 ItemSaveForm의 경우 규칙에 의해 itemSaveForm이라는 이름으로 MVC Model에 담기게 된다..

이렇게 되면 뷰 템플릿에 이름을 다 바꿔줘야 한다.

댓글남기기