게시글 리스트에 페이징 기능 추가하기
라이브러리 준비
웹 브라우저는 화면에서 벗어나는 내용을 스크롤을 통해 보여주기 때문에 게시판 내에서 게시글의 리스트가 너무 많으면 사용자가 불편함을 호소한다.
그래서 웹에서는 페이징이라는 개념을 통해 한 페이지 당 보여줄 게시글 리스트를 조절할 수 있다.
페이징 기능을 사용하기 위해 라이브러리가 준비되어야 한다.
https://github.com/josecebe/twbs-pagination
여기에서 jquery.twbsPagination.min.js
라는 파일이 필요하며 전체적인 화면단을 보여주는 프로젝트의 구성은 다음과 같다.
front
|_ index.html
|_ img
|_ arrow.png
|_ auth
|_ account.html
|_ login.html
|_ board
|_ bbs-answer.html
|_ bbs-update.html
|_ board-detail.html
|_ boardwrite.html
|_ boards.html
|_ paging
|_ jquery.twbsPagination.min.js
페이징을 구현하기 전 고민해야 할 사항
페이징을 하기 위해서는 한 페이지 당 보여줄 게시글의 수를 조절해야 하며, 검색했을 때 리스트에 보이는 글의 개수에 따라 페이지 번호가 갱신되어야 한다.
BbsParam에 변수 추가하기
import lombok.Getter;
@Getter
public class BbsParam {
private String choice;
private String search;
private int page; // 페이징을 갱신하기 위해 필요함.
private int start;
private int end;
public BbsParam() {
}
public BbsParam(String choice, String search, int page, int start, int end) {
this.choice = choice;
this.search = search;
this.page = page;
this.start = start;
this.end = end;
}
public void setChoice(String choice) {
this.choice = choice;
}
public void setSearch(String search) {
this.search = search;
}
public void setPage(int page) {
this.page = page;
}
public void setStart(int start) {
this.start = start;
}
public void setEnd(int end) {
this.end = end;
}
}
Mapper 파일 작성
페이징에 필요한 매퍼 작성하기
글의 총 개수에 따라 페이징이 갱신되어야 하므로 다음과 같이 매퍼를 추가해주었다.
<!-- 검색 결과에 따라 글의 총 개수를 반환해주기 위한 코드 -->
<select id="getBbsListSearchPage"
parameterType="com.hwangduil.springbootbackend.dto.BbsParam"
resultType="com.hwangduil.springbootbackend.dto.BbsDto"
>
SELECT SEQ, ID, REF, STEP, DEPTH, TITLE, CONTENT, WDATE, DEL, READCOUNT
FROM
(SELECT ROW_NUMBER()OVER(ORDER BY REF DESC, STEP ASC) AS RNUM,
SEQ, ID, REF, STEP, DEPTH, TITLE, CONTENT, WDATE, DEL, READCOUNT FROM BBS
WHERE 1 = 1
<if test="choice != null and choice != '' and search != null and search !=''">
<if test="choice == 'title'">
AND TITLE LIKE CONCAT('%', #{search}, '%')
</if>
<if test="choice == 'content'">
AND CONTENT LIKE CONCAT('%', #{search}, '%')
</if>
<if test="choice == 'writer'">
AND ID=${search}
</if>
</if>
ORDER BY REF DESC, STEP ASC) AS N
WHERE RNUM BETWEEN #{start} AND #{end}
</select>
<!-- 글의 총 개수 -->
<select id="getBbsCount" parameterType="com.hwangduil.springbootbackend.dto.BbsParam" resultType="Integer">
SELECT IFNULL(COUNT(*), 0) AS CNT FROM BBS
WHERE 1 = 1
<if test="choice != null and choice != '' and search != null and search !=''">
<if test="choice == 'title'">
AND TITLE LIKE CONCAT('%', #{search}, '%')
</if>
<if test="choice == 'content'">
AND CONTENT LIKE CONCAT('%', #{search}, '%')
</if>
<if test="choice == 'writer'">
AND ID=${search}
</if>
</if>
</select>
DAO 작성
별도로 주석을 달아준 메서드가 추가된다.
import com.hwangduil.springbootbackend.dto.BbsDto;
import com.hwangduil.springbootbackend.dto.BbsParam;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface BbsDao {
List<BbsDto> getBbsList();
void insertBbs(BbsDto dto);
BbsDto getBbsDetail(int seq);
void readcount(int seq);
List<BbsDto> getBbsListSearch(BbsParam param);
List<BbsDto> getBbsListSearchPage(BbsParam param); // 추가됨
int getBbsCount(BbsParam param); // 추가됨
}
Service 구현
import com.hwangduil.springbootbackend.dao.BbsDao;
import com.hwangduil.springbootbackend.dto.BbsDto;
import com.hwangduil.springbootbackend.dto.BbsParam;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
@RequiredArgsConstructor
public class BbsService {
private final BbsDao dao;
public List<BbsDto> getBbsList() {
return dao.getBbsList();
}
public void insertBbs(BbsDto dto) {
dao.insertBbs(dto);
}
public BbsDto getBbsDetail(int seq) {
return dao.getBbsDetail(seq);
}
public void readcount(int seq) {
dao.readcount(seq);
}
public List<BbsDto> getBbsListSearch(BbsParam param) {
return dao.getBbsListSearch(param);
}
public List<BbsDto> getBbsListSearchPage(BbsParam param) { // 추가
return dao.getBbsListSearchPage(param);
}
public int getBbsCount(BbsParam param) { // 추가
return dao.getBbsCount(param);
}
}
Controller 작성
import com.hwangduil.springbootbackend.dto.BbsDto;
import com.hwangduil.springbootbackend.dto.BbsParam;
import com.hwangduil.springbootbackend.service.BbsService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequiredArgsConstructor
public class BbsController {
public final Logger logger = LoggerFactory.getLogger(BbsController.class);
private final BbsService service;
@GetMapping("/getBbsList")
public List<BbsDto> getBbsList() {
logger.info("BbsController getBbsList");
return service.getBbsList();
}
@GetMapping("/insertBbs")
public void insertBbs(BbsDto dto) {
logger.info("BbsController insertBbs() ");
service.insertBbs(dto);
}
@GetMapping("/getBbsDetail")
public BbsDto getBbsDetail(int seq) {
logger.info("BbsController getBbsDetail()");
service.readcount(seq);
return service.getBbsDetail(seq);
}
@GetMapping("getBbsListSearch")
public List<BbsDto> getBbsListSearch(BbsParam param) {
logger.info("BbsController getBbsListSearch");
return service.getBbsListSearch(param);
}
@GetMapping("/getBbsListSearchPage")
public List<BbsDto> getBbsListSearchPage(BbsParam param) { // 추가
logger.info("BbsController getBbsListSearchPage");
// 페이지 설정
int sn = param.getPage(); // 현재 페이지
int start = sn * 10 + 1;
int end = (sn + 1) * 10;
param.setStart(start);
param.setEnd(end);
return service.getBbsListSearchPage(param);
}
@GetMapping("/getBbsCount")
public int getBbsCount(BbsParam param) { // 추가
logger.info("BbsController getBbsCount");
return service.getBbsCount(param);
}
}
프론트엔드 구성
검색 결과를 보여주는 코드
// 검색결과를 보여줄 코드
function getBbsList(page) {
let choice = $("#_choice").val();
let search = $("#_search").val();
$("#tbody").text("");
$.ajax({
url: "http://localhost:3000/getBbsListSearchPage",
type: "GET",
data: { choice: choice, search: search, page: page },
success: function(list) {
console.log(list);
$.each(list, function(index, list) { // index = 배열의 index
let str;
str = `<tr>
<th>${index+1}</th>
<td>$<a href="board-detail.html?seq=${list.seq}">${list.title}</a></td>
<td>${list.id}</td>
<td>${list.seq}</td>
</tr>`;
$("#tbody").append(str);
})
},
error: function() {
console.log("error");
}
})
}
컨트롤러의 getBbsListSearchPage
패턴에 검색구분, 검색어, 페이지 번호를 넘겨주면 페이지 번호에 의해 start
와 end
가 세팅된다.
컨트롤러로부터 넘겨받은 값을 테이블 형태로 뿌려준다.
글의 총 수를 취득하기 위한 함수
// 글의 총 수를 취득
function getBbsCount() {
let choice = $("#_choice").val();
let search = $("#_search").val();
$.ajax({
url: "http://localhost:3000/getBbsCount",
type: "GET",
data: { choice: choice, search: search, page: 0 },
success: function(count) {
loadPage(count);
},
error: function() {
console.log('getBbsCount error');
}
});
}
getBbsCount
패턴의 컨트롤러에 choice
, search
그리고 page
값을 0으로 넘겨준다.
컨트롤러에서 넘겨받은 값을 loadPage
함수에 넣어준다.
function loadPage(totalCount) {
let pageSize = 10;
let _totalPages = totalCount / 10 // 한 페이지에 보여줄 글 수
if (totalCount % 10 > 0) {
_totalPages++;
}
$('#pagination').twbsPagination('destroy'); // 페이지 갱신
$('#pagination').twbsPagination({
totalPages: _totalPages,
visiblePages: 10,
first: '<span sris-hidden="true">«</span>',
last: '<span sris-hidden="true">»</span>',
prev: '이전',
next: '다음',
initiateStartPageClick:false, // 자동호출 방지
onPageClick: function (event, page) {
// console.log(`page number : ${page}`);
getBbsList(page - 1);
}
});
}
이 함수를 통해 페이지를 로드해준다. 한 페이지에 최대 10개의 글이 보이도록 pageSize
로 선언해주었다.
매개변수로 받은 totalCount
을 10으로 나눈 값을 _totalPages
에 저장해주었다.
10으로 나눈 나머지가 0보다 클 때 _totalPages
에 1씩 더해준다.
twbsPagination
은 제시된 내용과 같이 사용한다.
'Study > Spring & Spring Boot' 카테고리의 다른 글
@Autowired 대신 @RequiredArgsConstructor (0) | 2022.03.11 |
---|---|
[Spring Boot] 게시판 기능 구현하기(3) (0) | 2022.02.24 |
[Spring Boot] 게시판 기능 구현하기(1) (0) | 2022.02.23 |
[Spring Boot] AJAX를 사용한 비동기 통신 (0) | 2022.02.22 |
[Spring Boot] DTO, DAO, Service, Controller (0) | 2022.02.21 |