본문 바로가기

[스프링부트/업무일지 만들기] 업무일지 화면을 보여주는 컨트롤러를 만들기-최신 순서로 정렬하기

ironwhale 2024. 6. 4.

앞서 API 기능을 구현하게 위한 RestController를 만들었습니다. 이번에는 화면을 보여주는 뷰 컨트롤러를 만들어보겠습니다. 여기서 가장 애먹었던 부분은 최신 글을 제일 상단에 오는 방법, 즉 자바 리스트 정렬에 관한 로직과 업무일지를 수정하는데 리스트를 스트링으로 바꾸는 부분이었습니다. 


최신글을 제일 위로 정렬하기

몬가 쉬워 보이면서도 제일 어려웠던 부분이었습니다. 일단 단순한 리스트가 아니라 객체가 저장된 리스트에서 객체의 각 ID값을 기준으로 정렬하는 방법을 찾아야 했습니다. 

Immutable object is modified 오류 해결

일단 기본적으로 아래 스샷과 같이 코드를 만들었는데 오류가 계속 났습니다. 불변 객체를 바꾸려 했기 때문이죠. 하지만 친절한 인텔리제이가 해결 방법을 알려주어서 잘 넘어 갈수 있습니다. 

 

정렬 하기위한 Comparator 만들기

리스트 안에 단순히 스트링 값이나 숫자가 아닌 객체가 있기 때문에 객체의 값을 기준으로 정렬하기 위해서는 Comparator를 만들어서 정렬을 해야 했습니다. 1, -1, 0의 의미는 1(양수)은 순서를 바꿔라, -1(음수)과 0은 순서를 그대로 해라로 정리할 수 있습니다.

 

만약 첫번째 객체(o1)의 id가 5이고 두번째 객체(o2)의 id가 6이라면 제가 의도한 내림차순 정렬이 되려면 둘의 순서가 바뀌어야 합니다. 따라서 o1.getId()<o2.getId()의 등식이 성립하기 때문에 순서가 바뀌어야 하여 양수(1)이 리턴됩니다. 만약 오른 차순 정렬을 하고자하면 첫번째 조건문을 음수로 두번째 조건문을 양수로 바꾸시면 됩니다. 

 

public class WorkLogsViewResponseComparator implements Comparator<WorkLogsViewResponse> {
    @Override
    public int compare(WorkLogsViewResponse o1, WorkLogsViewResponse o2) {

        if (o1.getId() < o2.getId()) {
            return 1;
        } else if (o1.getId() > o2.getId()) {
            return -1;
        }
        return 0;
    }
}

 


리스트를 스트링으로 바꾸기(최대한 컨트롤러에서 처리해서 넘기자)

태그에는 ["사과", "당근", "양파"]와 같이 저장되어 있었습니다. 문제는 이걸 그대로 타임리프 문법으로 해결하려고 하는 어리석은 생각을 하여 시간을 많이 잡아 먹었습니다. 구지 그렇게 하지 말고 컨트롤러에서 처리할 수 있는 부분은 최대한 처리해서 넘겨주는것이 현명한 방법이라는것을 알게되 계기가 되었습니다. 

 

아래 코드가 리스트를 스트링으로 바꾸는 방법입니다. 

String.join(",", findWorkLog.getTags())

 

반대로 스트링을 리스트로 바꾸는 코드는 챗GPT에게 물어보니 아래와 같이 친절하게 설명과 함께 코드를 보여줘서 가지고 와봤습니다. split("구분자")를 사용하면 리스트로 변환할 수 있습니다. 

import java.util.Arrays;
import java.util.List;

public class StringToListExample {
    public static void main(String[] args) {
        // 쉼표로 구분된 문자열 선언
        String tags = "tag1,tag2,tag3";
        
        // 문자열을 쉼표를 기준으로 분리하여 배열로 변환
        String[] tagsArray = tags.split(",");
        
        // 배열을 리스트로 변환
        List<String> tagsList = Arrays.asList(tagsArray);
        
        // 리스트 출력
        System.out.println(tagsList);  // 출력: [tag1, tag2, tag3]
    }
}

전체코드

@RequestMapping("/worklog")
@RequiredArgsConstructor
@Controller
public class WorkLogViewController {
    final private WorkLogService workLogService;

    @GetMapping("")
    public String getWorkLog(Model model, Principal principal) {
        System.out.println("principal = " + principal.getName());
        List<WorkLogsViewResponse> workLogs = new java.util.ArrayList<>(workLogService.findAll(principal.getName()).stream().map(WorkLogsViewResponse::new).toList());

        workLogs.sort(new WorkLogsViewResponseComparator());

        model.addAttribute("workLogs", workLogs);
        return "work_log";
    }


// id가 null 이면 새로운 업무일지 입력, 아니면 수정하는 페이지로 이동
    @PreAuthorize("isAuthenticated()")
    @GetMapping("/create")
    public String createWorkLog(@RequestParam(required = false) Long id, Model model, Principal principal) {


        if (id == null) {
            model.addAttribute("workLog", new WorkLogsViewResponse());
        } else {
            WorkLog findWorkLog = workLogService.findById(id);

            if (findWorkLog.getUserName().equals(principal.getName())) {
                model.addAttribute("workLog", new WorkLogsViewResponse(findWorkLog));
                if (findWorkLog.getTags() != null) {
                    model.addAttribute("tagToString", String.join(",", findWorkLog.getTags()));
                }
            } else {
                throw new SecurityException("You are not allowed to update this log");
            }
        }
        return "log_form";

    }

}

 


이제 여기 까지 기본적인 내용은 정리가 된거 같습니다. 다음은 중간 중간에 보이는 SecurityException와 같은 예외처리 부분과 데이터 베이스에 List<Sting> tags 가 어떻게 저장되고 불러와지게 하는지에 대해 알아보겠습니다. 

댓글