minlog
article thumbnail

새로고침 시 데이터 중복 저장 막기, 컨트롤러 구분

 

1. 문제점 확인

화면 단 작업 중 디자인이랑 페이지 동작을 확인하느라 새로고침을 여러번 하게 되었는데, 이때 원하지 않는 저장이 계속해서 발생하는 문제점을 확인하게 되었습니다.
실재 데이터 테이블을 확인해보면 이전 페이지에서 저장했던 내용이 중복으로 저장 되어 있는 것을 확인할수 있습니다.

 
 

2. 원인 확인

재 로딩 시 맵핑된 주소로 다시 POST 를 통해 접속하면서  저장로직이 한번 더 진행되는 것이었습니다.
 
📑TravelController.java

@Transactional
@PostMapping("/category")
public String categorySave(@ModelAttribute("category") CategoryDTO categoryDTO, Model model,
                           RedirectAttributes redirectAttributes) {

    log.info(" 아이템 생성 페이지 --------------------");
    log.info(categoryDTO);
    LocalDate localDate = LocalDate.parse(categoryDTO.getDateStart());
    int dayOfMonth = localDate.getDayOfMonth(); // 시작 날짜

    CategoryDTO result = categoryService.categorySave(categoryDTO);
    if (result == null){
        redirectAttributes.addFlashAttribute("msg","임시저장은 5개 까지 가능합니다.");
        return "redirect:/travel";
    }

    int days = categoryService.categoryDays(categoryDTO.getDateStart(), categoryDTO.getDateEnd());
    int[] arr = new int[days];

    model.addAttribute("category",result);
    model.addAttribute("days",arr);
    model.addAttribute("startDay",dayOfMonth); //시작 날짜

    return "travel/travelMap";
}

 
 

3. 문제해결 방법 

위 문제를 해결하기 위해서는 POST 요청이 두번 일어나지 않게 막아야합니다. 해결 방법으로 처음 접속 할때, 맵핑되는 POST 요청외에 새로고침 시 맵핑되는 컨트롤러를 따로 만들어주어 구분되게 했습니다.
 

3-1. POST 변경

기존에는 저장과 결과 값들을 화면에 전달하는 역할을 categorySave() 메서드에서 모두 진행하고 있었습니다.
변경 된 메서드에서는 카테고리를 저장하는 로직과 저장된 카테고리의 고유번호만 리다이렉트를 통해서 화면을 보여주는 컨트롤러로 전달 하고 있습니다. 
리프레쉬(새로고침) 시에도 해당 값을 계속해서 사용해야 하기 때문에 addAttribute를 사용하여 전달했습니다.
 

  • 리다이렉트 값을 전달하는 파라미터 객체 
    • RedirectAttributes redirectAttributes
  • RedirectAttributes 객체의 메소드
    • addAttribute("명칭",전달 값)  
    • addFlashAttribute("명칭",전달 값) 
  • addAttribute
    • 해당 메소드로 전달한 값은 URL 파라미터 값으로 전달되게 됩니다.
    • 때문에 String 타입으로 변환이 가능한 타입만 전달 가능합니다.
    • ex) http://localhost:8087/travel/category?no=22
  • addFlashAttribute
    • 결과값을 한번만 전달하며 재 로딩 시 값이 사라집니다.
    • Object 나 여러 개의 값을 Map 방식으로 전달 가능합니다.

 
📑TravelController.java

@PostMapping("/category")
public String categorySave(@ModelAttribute("category") CategoryDTO categoryDTO,
                           RedirectAttributes redirectAttributes) {
    log.info(" 아이템 생성 페이지 --------------------");
    CategoryDTO result = categoryService.categorySave(categoryDTO);
    if (result == null){
        redirectAttributes.addFlashAttribute("msg","임시저장은 5개 까지 가능합니다.");
        return "redirect:/travel";
    }
    redirectAttributes.addAttribute("no",result.getCategoryNo());
    return "redirect:/travel/category";
}

 
 

3-2.  Get 컨트롤러 생성

전달 받은 파라미터 형식의 데이터를 @RequestParam 어노테이션을 사용하여 파라미터의 값을 받아 카테고리 객체를 구하고 모델로 화면에 값을 넘겨주었습니다.
이렇게 구현하면, 리프레쉬 (새로고침) 했을 시, 데이터를 다시 저장 하지 않으며 전달 받았던 정보를 그대로 가지고 있을 수 있습니다.
📑TravelController.java

@GetMapping("/category")
public String categoryMap(
        @RequestParam(value = "no") long no,
        Model model
){
    log.info(no);
    CategoryDTO categoryDTO = categoryService.getCategory(no);

    int days = categoryService.categoryDays(categoryDTO.getDateStart(), categoryDTO.getDateEnd());
    int[] arr = new int[days];
    LocalDate localDate = LocalDate.parse(categoryDTO.getDateStart());
    int dayOfMonth = localDate.getDayOfMonth();

    model.addAttribute("category",categoryDTO);
    model.addAttribute("days",days);
    model.addAttribute("startDay",dayOfMonth);

    return "travel/travelMap";
}

 
 

profile

minlog

@jimin-log

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!