본문 바로가기
개발/게시판 만들기

[Vue] Vue.js 게시판 만들기 9 - 페이징

by onethejay 2022. 3. 3.
728x90

페이징 데이터 생성

먼저 백엔드에서 페이징 작업을 진행하겠습니다.

model 패키지를 생성하고 Header.java와 Pagination.java 클래스를 생성합니다.

/* Header.java */

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Header<T> {
    private LocalDateTime  transactionTime;
    private String resultCode;
    private String description;
    private T data;
    private Pagination pagination;

    public static <T> Header<T> OK() {
        return (Header<T>) Header.builder()
                .transactionTime(LocalDateTime.now())
                .resultCode("OK")
                .description("OK")
                .build();
    }

    //DATA OK
    public static <T> Header<T> OK(T data) {
        return (Header<T>) Header.builder()
                .transactionTime(LocalDateTime.now())
                .resultCode("OK")
                .description("OK")
                .data(data)
                .build();
    }

    public static <T> Header<T> OK(T data, Pagination pagination) {
        return (Header<T>) Header.builder()
                .transactionTime(LocalDateTime.now())
                .resultCode("OK")
                .description("OK")
                .data(data)
                .pagination(pagination)
                .build();
    }

    public static <T> Header<T> ERROR(String description) {
        return (Header<T>) Header.builder()
                .transactionTime(LocalDateTime.now())
                .resultCode("ERROR")
                .description(description)
                .build();
    }
}
/* Pagination.java */

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Pagination {
    //페이지당 보여지는 게시글 최대 개수
    private int pageSize;

    //현재 페이지
    int page;

    //현재 블럭
    int block;

    //총 게시글 수
    int totalListCnt;

    //총 페이지 수
    int totalPageCnt;

    //총 구간 수
    int totalBlockCnt;

    //시작 페이지
    int startPage;

    //마지막 페이지
    int endPage;

    // 이전 구간 마지막 페이지
    int prevBlock;

    // 다음 구간 시작 페이지
    int nextBlock;

    // 인덱스
    int startIndex;

    public Pagination(Integer totalListCnt, Integer page, Integer pageSize, Integer blockSize) {
        this.pageSize = pageSize;

        //현재 페이지
        this.page = page;

        //총 게시글 수
        this.totalListCnt = totalListCnt;

        //총 페이지 수
        totalPageCnt = (int) Math.ceil(totalListCnt * 1.0 / this.pageSize);

        //총 블럭 수
        totalBlockCnt = (int) Math.ceil(totalPageCnt * 1.0 / blockSize);

        //현재 블럭
        block = (int) Math.ceil((this.page * 1.0) / blockSize);

        //if(block < 1) block = 1

        //블럭 시작 페이지
        startPage = ((block - 1) * blockSize + 1);

        //블럭 마지막 페이지
        endPage = startPage + blockSize - 1;

        //블럭 마지막 페이지 validation
        if (endPage > totalPageCnt) endPage = totalPageCnt;

        // 이전 블럭 (클릭 시, 이전 블럭 마지막 페이지)
        prevBlock = (block * blockSize) - blockSize;

        // 이전 블럭 validation
        if (prevBlock < 1) prevBlock = 1;

        //다음 블럭 (클릭 시, 다음 블럭 첫번째 페이지)
        nextBlock = (block * blockSize + 1);

        // 다음 블럭 validation
        if (nextBlock > totalPageCnt) nextBlock = totalPageCnt;

        //if(this.page < 1) this.page = 1

        startIndex = (this.page - 1) * this.pageSize;
    }
}

이전에 게시글 목록을 화면으로 보낼때는 리스트에만 보냈으나 이번 작업부터는 객체 안에 담아서 보내게 됩니다.
데이터 정보와 페이징 정보가 담긴 객체를 Header 객체에 담아 보내도록 하겠습니다.

BoardRepository.java 안에 Page로 리턴하는 쿼리 메소드를 추가합니다.

/* BoardRepository.java */

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BoardRepository extends JpaRepository<BoardEntity, Long> {
    Page<BoardEntity> findAllByOrderByIdxDesc(Pageable pageable);
}

생성한 쿼리메소드를 사용하도록 BoardService의 getBoardList 내용을 수정합니다.
getBoardList를 호출할때 Pageable 객체를 통해 쿼리메소드를 호출하여 데이터를 가져옵니다.
JPA 에서 제공하는 페이징 처리를 통해 쉽게 페이징 데이터를 생성할 수 있습니다.

/* BoardService.java */

public Header<List<BoardDto>> getBoardList(Pageable pageable) {
    List<BoardDto> dtos = new ArrayList<>();

    Page<BoardEntity> boardEntities = boardRepository.findAllByOrderByIdxDesc(pageable);
    for (BoardEntity entity : boardEntities) {
        BoardDto dto = BoardDto.builder()
                .idx(entity.getIdx())
                .author(entity.getAuthor())
                .title(entity.getTitle())
                .contents(entity.getContents())
                .createdAt(entity.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss")))
                .build();

        dtos.add(dto);
    }

    Pagination pagination = new Pagination(
            (int) boardEntities.getTotalElements()
            , pageable.getPageNumber() + 1
            , pageable.getPageSize()
            , 10
    );

    return Header.OK(dtos, pagination);
}

BoardController.java 의 boardList 메서드도 수정합니다.

@GetMapping("/board/list")
public Header<List<BoardDto>> boardList(
        @PageableDefault(sort = {"idx"}) Pageable pageable
) {
    return boardService.getBoardList(pageable);
}

Pageable 에서 리스트 인덱싱을 할때 0부터 시작하게 됩니다. 우리는 1페이지를 눌렀지만 Pageable에는 0으로 입력되어야 합니다.
그러나 매번 처리하기에는 복잡하므로 Config 클래스를 생성해서 작업하겠습니다.

config 패키지를 생성하고 WebMvcConfig.java 클래스를 생성합니다.

import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.data.web.SortHandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        SortHandlerMethodArgumentResolver sortArgumentResolver = new SortHandlerMethodArgumentResolver();
        sortArgumentResolver.setSortParameter("sortBy");
        sortArgumentResolver.setPropertyDelimiter("-");

        PageableHandlerMethodArgumentResolver pageableArgumentResolver = new PageableHandlerMethodArgumentResolver(sortArgumentResolver);
        pageableArgumentResolver.setOneIndexedParameters(true);
        pageableArgumentResolver.setMaxPageSize(500);
        pageableArgumentResolver.setFallbackPageable(PageRequest.of(0, 10));
        argumentResolvers.add(pageableArgumentResolver);
    }
}

마지막으로 import.sql 파일에 데이터를 많이 생성해주세요.
테스트코드를 실행하실 수 있다면 아래 코드를 활용하셔도 좋습니다.

@Test
void createImportSql() {
    String sql = "INSERT INTO BOARD (IDX, TITLE, CONTENTS, AUTHOR, CREATED_AT) VALUES (1, '게시글 제목1', '게시글 내용1', '작성자1', '2022-02-18 23:24:00');";
    for (int i = 1; i <= 101; i++) {
        String sql1 = "INSERT INTO BOARD (IDX, TITLE, CONTENTS, AUTHOR, CREATED_AT) VALUES (" + i;
        String sql2 = ", '게시글 제목" + i;
        String sql3 = "', '게시글 내용" + i;
        String sql4 = "', '작성자" + i;
        String sql5 = "', '2022-03-03 23:24:00');";
        System.out.println(sql1 + sql2 + sql3 + sql4 + sql5);
    }
}

백엔드 서버에서 생성한 데이터를 출력하도록 프론트화면에서 이어서 작업을 진행하겠습니다.

페이징 데이터 출력

백엔드 서버에서 생성한 데이터를 받아 표시할 수 있게 BoardList.vue 파일을 수정하겠습니다.

methods 안의 fnGetList를 수정합니다.

/* BoardList.vue */

<script>
export default {
.....

methods: {

fnGetList() {
  this.requestBody = { // 데이터 전송        
    keyword: this.keyword,
    page: this.page,
    size: this.size
  }

  this.$axios.get(this.$serverUrl + "/board/list", {
    params: this.requestBody,
    headers: {}
  }).then((res) => {      

    if (res.data.result_code === "OK") {
      this.list = res.data.data
      this.paging = res.data.pagination
      this.no = this.paging.total_list_cnt - ((this.paging.page - 1) * this.paging.page_size)
    }

  }).catch((err) => {
    if (err.message.indexOf('Network Error') > -1) {
      alert('네트워크가 원활하지 않습니다.\n잠시 후 다시 시도해주세요.')
    }
  })
},

}

.....

화면 스크립트를 수정하고 프론트와 백엔드 서버를 모두 시작하여 확인합니다.
img.png

728x90

댓글