미니 프로젝트/게시판

[Java] 게시판 ③ DTO

웹개발자(진) 2024. 5. 21. 11:18
반응형

1. PageRequestDTO

Springboot에서 HTTP요청을 할 때 get방식과 post방식을 많이 쓴다는 것은 앞에서도 많이 다뤘는데요. servlet에서 request와 response에 데이터를 많이 담아서 요청을 했었는데 Springboot에는 Model이라는 개념이 있다고 했었습니다. 개념적으로는 아래글을 참조하시면 됩니다.

2024.05.09 - [Framework/Springboot] - [Springboot] Controller (get / post)

 

[Springboot] Controller (get / post)

잡담오늘은 Springboot에서 RestController를 이용해서 json처리하는 방법과 해당 결과를 출력하는 thymeleaf에 대한 예제와 get / post 방식에 대한 몇 가지 들어서 공부해 볼 예정입니다.   1. @GetMappingSpring

gustjr7532.tistory.com

매개변수를 받을때 model 말고도 다른 변수 또한 담을 수 있었습니다. 해당 기능을 이용해서 저희는 page의 정보를 담아서 pagenation을 진행해 볼 예정입니다.

우선 page에 대한 정보가 담겨있는 생성자를 만들기 위해 PageRquestDTO 클래스를 생성해주는데요 아래의 코드를 보겠습니다.

package org.zerock.b01.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class PageRequestDTO {
    @Builder.Default
    private int page = 1;
    @Builder.Default
    private int size = 10;
    private String type; //t, c, w, tc, tw, twc
    private String keyword;
    private String link;

    public String[] getTypes() {
        if (type == null || type.isEmpty()) {
            return null;
        }
        return type.split("");
    }

    public Pageable getPageable(String... props) {
        return PageRequest.of(this.page - 1, this.size, Sort.by(props).descending());
    }

    
}

이 코드는 페이지 요청과 관련된 정보를 담은 PageRequestDTO 클래스입니다. 이 클래스는 페이지 번호, 페이지 크기, 검색 유형(type), 검색어(keyword) 등을 포함합니다.

여기서 getPageable 메소드는메서드는 Spring Data의 Pageable 객체를 생성하여 반환합니다. 이 메서드는 페이지 번호(page), 페이지 크기(size), 그리고 정렬에 사용할 속성(props)을 전달받아 PageRequest 객체를 생성합니다. 정렬 속성은 descending()을 호출하여 내림차순으로 정렬합니다.

이러한 페이지 요청 정보는 주로 데이터베이스에서 페이징된 데이터를 검색하거나 조회할 때 사용됩니다. 예를 들어, 데이터베이스에서 특정 페이지에 해당하는 게시물을 검색하고자 할 때 이 정보를 사용하여 쿼리를 작성하고 실행할 수 있습니다.

getPageable 메소드를 사용하려면 해당 메서드를 호출하여 Pageable 객체를 생성하고, 이를 Spring Data 리포지토리의 메서드에 전달하면 됩니다. 이를 통해 페이지네이션된 결과를 얻을 수 있습니다.

 

public String getLink() {
        if (link == null) {
            StringBuilder builder = new StringBuilder();
            builder.append("page=" + this.page);
            builder.append("&size=" + this.size);
            if (type != null && type.length() > 0) {
                builder.append("&type=" + type);
            }
            if (keyword != null) {
                try {
                    builder.append("&keyword=" + URLEncoder.encode(keyword, "UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            link = builder.toString();
        }
        return link;
    }

 


 

2. PageResponseDTO

PageResponseDTO 클래스는 페이징 처리를 위한 데이터 전송 객체입니다. 이 클래스는 페이지 요청 정보와 해당 페이지의 데이터 리스트를 포함하며, 페이지 내비게이션에 필요한 정보를 제공합니다.

package org.zerock.b01.dto;

import lombok.Builder;
import lombok.Getter;
import lombok.ToString;

import java.util.List;

@Getter
@ToString
public class PageResponseDTO<E> {
    private int page;
    private int size;
    private int total;

    //시작,끝페이지번호
    private int start;
    private int end;

    private boolean prev;
    private boolean next;
    private List<E> dtoList;

    @Builder(builderMethodName = "withAll")
    public PageResponseDTO(PageRequestDTO pageRequestDTO,List<E> dtoList, int total){
        if(total <=0){
            return;
        }
        this.page = pageRequestDTO.getPage();
        this.size = pageRequestDTO.getSize();
        this.total = total;
        this.dtoList = dtoList;

        this.end = (int)(Math.ceil(this.page/10.0)) *10; //????????
        this.start = this.end - 9;

        int last = (int)(Math.ceil(total/(double)size));
        this.end = end>last? last : end;

        this.prev = this.start > 1;
        this.next = total > this.end*this.size;
    }
}

 


    private int page;
    private int size;
    private int total;
    private int start;
    private int end;
    private boolean prev;
    private boolean next;
    private List<E> dtoList;

 

  • page: 현재 페이지 번호.
  • size: 한 페이지에 표시될 데이터의 수.
  • total: 전체 데이터의 수.
  • start: 현재 페이지 블록의 시작 페이지 번호.
  • end: 현재 페이지 블록의 끝 페이지 번호.
  • prev: 이전 페이지 블록이 있는지 여부.
  • next: 다음 페이지 블록이 있는지 여부.
  • dtoList: 현재 페이지에 표시될 데이터 리스트.

 


@Builder(builderMethodName = "withAll")
public PageResponseDTO(PageRequestDTO pageRequestDTO, List<E> dtoList, int total){
    if(total <=0){
        return;
    }
    this.page = pageRequestDTO.getPage();
    this.size = pageRequestDTO.getSize();
    this.total = total;
    this.dtoList = dtoList;

}

 

 

 

builderMethodName 은 Lombok 애노테이션으로, PageResponseDTO 객체를 생성할 때 빌더 패턴을 사용할 수 있게 합니다. builderMethodName 속성은 빌더 메서드의 이름을 withAll로 지정합니다.

total <=0 은 검색결과가 없을때 종료함을 의미합니다.

pagesize는 pageRequestDTO 에 있는 값들을 get() 해온다.

 


    this.end = (int)(Math.ceil(this.page / 10.0)) * 10;
    this.start = this.end - 9;

    int last = (int)(Math.ceil(total / (double) size));
    this.end = end > last ? last : end;

    this.prev = this.start > 1;
    this.next = total > this.end * this.size;

 

  • this.end = (int)(Math.ceil(this.page / 10.0)) * 10;: 현재 페이지 번호를 기준으로 끝 페이지 번호를 계산합니다. 예를 들어, 현재 페이지가 15라면 Math.ceil(15 / 10.0)는 2가 되고, 이 값을 10으로 곱하면 끝 페이지 번호는 20이 됩니다.
  • this.start = this.end - 9;: 끝 페이지 번호에서 9를 빼서 시작 페이지 번호를 계산합니다. 예를 들어, 끝 페이지가 20이라면 시작 페이지 번호는 11이 됩니다.
  • int last = (int)(Math.ceil(total / (double) size));: 전체 페이지 수를 계산합니다. 예를 들어, total이 105이고 size가 10이라면 전체 페이지 수는 11이 됩니다.
  • this.end = end > last? last : end;: 계산된 끝 페이지 번호가 전체 페이지 수보다 크면 끝 페이지 번호를 전체 페이지 수로 설정합니다.
  • this.prev = this.start > 1;: 시작 페이지 번호가 1보다 크면 이전 페이지 블록이 존재합니다.
  • this.next = total > this.end * this.size;: 전체 데이터 수가 끝 페이지 번호에 표시될 수 있는 데이터 수보다 크면 다음 페이지 블록이 존재합니다.


 

글을 마치며

 

 

어떤 데이터를 주고받을지에 따라서 DTO(Data transfer Object)는 수정해 나가면 됩니다. 마지막에 작성한 페이지에 대한 end, start 등등의 값은 크게 변화하지 않고 거의 대부분의 페이지 데이터에 사용되기 때문에 외우거나 하지 마시고 그냥 이런 공식이구나 이해만 하고 나중에 필요할 일 있으면 참고해서 사용하시면 될 거 같습니다.

반응형