자바 프레임 워크 11일차 springex_web 검색 및 데이터 보존 페이징처리

2026. 4. 1. 19:23대우개발원 수업 내용/spring boot, framework

반응형

1. 검색 파라미터 추출 및 URL 자동 조립 기능 구현 (PageRequestDTO.java)

사용자가 설정한 5가지 검색 조건이 이동 시마다 유실되지 않도록 getLink() 메서드 내부에 조건부 결합 로직을 구축함.

  • 완료 여부(finished) 유지: 체크박스가 선택된 상태(true)라면 URL 뒤에 &finished=on을 강제로 붙여 필터링 상태 유지.
  • 다중 검색 조건(types) 반복 결합: 제목(t), 작성자(w) 등 배열로 들어오는 검색 타입을 반복문을 통해 &types=t&types=w 형태로 빠짐없이 이어 붙임.
  • 검색어(keyword) 인코딩 처리: 한글 검색어가 URL에서 깨지지 않도록 URLEncoder를 사용해 UTF-8 형식으로 안전하게 변환하여 결합.
  • 날짜 구간(from, to) 데이터 보존: 시작 날짜와 종료 날짜가 존재할 경우 문자열로 변환하여 URL 파라미터에 포함시켜 구간 검색 결과 유지.

2. 자바스크립트 폼 제출 방식을 통한 페이징 개선 (list.jsp)

단순한 링크 이동 방식에서 기존 검색 조건을 포함하여 전송하는 방식으로 로직을 변경함.

  • 히든 필드를 활용한 데이터 전송: 페이지 번호 클릭 시 기존 form 태그 안에 input type='hidden'으로 페이지 번호를 동적으로 삽입.
  • 상태 유지 제출(Submit): formObj.submit()을 호출하여 사용자가 입력한 모든 검색 조건과 클릭한 페이지 번호를 서버로 한꺼번에 전송.

3. 삭제 작업 후 검색 상태 유지 로직 적용 (modify.jsp & TodoController.java)

게시글 삭제 시 모든 검색 조건이 초기화되는 현상을 방지하기 위해 경로 제어 코드를 수정함.

  • 삭제 폼 액션 수정: formObj.action 경로 뒤에 ${pageRequestDTO.link}를 결합하여 삭제 요청 시에도 현재의 검색/페이징 상태를 서버로 전달.
  • 컨트롤러 리다이렉트 최적화: remove 메서드에서 작업 완료 후 redirect:/todo/list? 뒤에 pageRequestDTO.getLink()를 붙여 리턴함으로써, 삭제 직전의 검색 결과 화면으로 정확히 복귀하도록 구현.

4. 수정 작업 후 경로 제어 및 파라미터 최적화 (TodoController.java)

수정(Modify) 작업 완료 후의 흐름을 사용자 경험에 맞춰 재설계함.

  • 상세 페이지(Read) 복귀 설정: 수정 완료 후 단순 목록 이동이 아닌, 방금 수정한 글을 확인할 수 있도록 redirect:/todo/read 경로에 tno와 기존 link 정보를 실어서 보냄.
  • 불필요한 중복 코드 제거: page와 size를 별도로 addAttribute하던 방식을 지우고, 모든 정보가 포함된 getLink() 메서드 하나로 파라미터 전달 과정을 간소화함.

 

아래 사진 부분에

완료 여부(finished) 체크박스가 선택(true)된 상태라면 URL 주소 뒤에 '&finished=on' 파라미터를 덧붙여주는 조건부 결합 코드. 목록 페이지를 넘기거나 상세 글을 읽고 돌아와도 '완료된 항목만 보기' 검색 필터가 풀리지 않고 그대로 유지되게 만드는 필수 수정.

if(finished){
    builder.append("&finished=on");
}

이 구문을 추가


제목이나 작성자 같은 검색 조건(types)이 선택되어 배열에 값이 존재하면,

URL 주소 뒤에 '&types=t'나 '&types=w' 처럼 선택한 개수만큼 파라미터를 계속 이어 붙여주는 반복문 코드.

여러 개의 체크박스를 동시에 선택하고 페이지를 넘기더라도,

내가 체크했던 다중 검색 조건들이 중간에 유실되지 않고 끝까지 유지되도록 만들어주는 필수 수정.

if(types != null && types.length > 0){
    for (int i = 0; i < types.length ; i++) {
        builder.append("&types=" + types[i]);
    }
}

추가


검색어(keyword)가 입력되었을 때, 한글이나 띄어쓰기 같은 문자가 URL 주소창에서 깨지지 않도록

UTF-8 형식으로 안전하게 변환(인코딩)하여 파라미터에 붙여주는 필수 코드.

검색창에 한글을 치고 다음 페이지로 넘어갔을 때, 글자가 외계어로 변질되어

애써 찾은 검색 결과가 날아가는 현상을 완벽하게 막아주는 꼼꼼한 수정.

if(keyword != null){
    try {
        builder.append("&keyword=" + URLEncoder.encode(keyword,"UTF-8"));
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}

 

추가


시작 날짜(from)가 선택되어 값이 존재할 경우, URL 주소 뒤에 '&from=2026-05-01' 같은 형식으로

날짜 데이터를 문자열로 변환해 덧붙여주는 코드. 날짜 구간으로 검색을 하고 페이지를 넘기거나

상세 글을 보고 돌아와도, 처음에 설정했던 시작 날짜 필터가 초기화되지 않도록 꽉 잡아주는 필수 수정.

if(from != null){
    builder.append("&from=" + from.toString());
}

 

추가


종료 날짜(to)가 선택되어 값이 존재할 경우, URL 주소 뒤에 '&to=2026-05-31' 같은 형식으로

날짜 데이터를 문자열로 변환해 덧붙여주는 코드. 날짜 구간으로 검색을 하고 페이지를 넘기거나

상세 글을 보고 돌아와도, 처음에 설정했던 종료 날짜 필터가 초기화되지 않도록 끝까지 유지시켜주는 필수 수정.

if(to != null){
    builder.append("&to=" + to.toString());
}

 

 

요약

사용자가 입력한 5가지 검색 조건들을 모두 모아 하나의 URL 파라미터로 길게 이어 붙여주는 코드.
페이지를 이동하거나 상세 글을 보고 돌아와도 내가 설정한 검색 필터가 절대 초기화되지 않도록 하는 코드들 이다.

 

총 코드

더보기
더보기
package com.example.springex_web.dto;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Positive;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.Arrays;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PageRequestDTO {
    @Builder.Default   //기본값 세팅
    @Min(value = 1)
    @Positive  // 무조건 양수값을 가져야함 ,음수 x
    private int page = 1;

    @Builder.Default
    @Min(value = 10)
    @Max(value = 100)
    @Positive
    private  int size = 10;

    private String link;
    private String[] types;
    private String keyword;
    private boolean finished;
    private LocalDate from;
    private LocalDate to;

    public int getSkip(){
        return (page -1) * 10;
    }

    public String getLink(){
        if(link == null){
            StringBuilder builder = new StringBuilder();
            builder.append("page=" +this.page);
            builder.append("&size=" + this.size);
            if(finished){
                builder.append("&finished=on");
            }
            if(types != null && types.length > 0){
                for (int i = 0; i < types.length ; i++) {
                    builder.append("&types=" + types[i]);
                }
            }
            if(keyword != null){
                try {
                    builder.append("&keyword=" + URLEncoder.encode(keyword,"UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            if(from != null){
                builder.append("&from=" + from.toString());
            }
            if(to != null){
                builder.append("&to=" + to.toString());
            }
            link = builder.toString();

        }
        return link;
    }

    public boolean checkType(String type){
        if(types == null || types.length == 0){
            return false;
        }
        return Arrays.stream(types).allMatch(type::equals); //타입 equals와 일치하는게 하나라도 있으면 true를 반환
    }
}

 


list.jsp에서

// self.location = `/todo/list?page=\${num}` //백틱(` `)을 이용해서 템플릿 처리

이부분을 주석처리 후

 

코드는 브라우저에서 현재 화면의 데이터를 서버로 보낼 때, 눈에 보이지 않는 데이터를 추가해서 제출(Submit)하는  코드

페이징 처리(Pagination)**를 할 때 사용하며, 사용자가 특정 페이지 번호를 클릭했을 때 그 번호를 서버에 전달하기 위한 용도

const formObj = document.querySelector("form")
formObj.innerHTML += `<input type='hidden' name='page' value='\${num}'>`
formObj.submit();

구문 추가

 

실행하게 되면

그대로 유지된다


list는 링크가 그대로 유지 되는 코드가 있지만 

링크가 그대로 유지되는 코드가 remove에는 없어서 유지가 되지 않기 때문에 추가

formObj.action=`/todo/remove?${pageRequestDTO.link}`

 

TodoController.java에도 remove메서드 구간에 링크를 포함한 이동을 할 수 있게  해줘야함

//        redirectAttributes.addAttribute("page",1);
//        redirectAttributes.addAttribute("size",pageRequestDTO.getSize());
//        return "redirect:/todo/list";

이부분을 주석처리 후

return "recirect:/todo/list?" + pageRequestDTO.getLink();

을 추가

 

링크가 그대로 유지되는 코드가 modify에도 없어서 유지가 되지 않기 때문에 추가

modify에서는 검색 필터링에 대한 내용을 없애고 list로 돌아오도록 한다

(이전에 검색했던 내용을 수정했을 때 그대로 나오면 꼬이기 때문)

 

 

우선 link메서드에 page와 size정보가 다 담겨 있고

modify에서는 쓰지 않아서 주석처리를 한다

 

이걸로 자바 프레임워크는 끝나고 이제 spring boot를 한다