본문으로 바로가기

이전에 만든 CRUD 게시판은 100개의 게시글이 있다면 한번에 100개의 게시글이 모두 보여진다. 정말 비효율적인 게시판이다..(ㅎ) 그래서 게시판 목록 페이징 처리를 하려고 한다. 그러면 좀 더 게시판 스럽지 않을까 싶다! 나는 만들어 놓은 CURD 게시판을 수정해서 작업을 하는 것이기 때문에 본인의 게시판에 맞게 적절히 섞어(?)주면 된다.


1. 페이징 규칙

먼저 페이징이 어떤식으로 처리되는 지 이해해보자. 페이지당 게시글을 10개씩 보여주고 페이징 버튼은 최대 10개까지만 보인다고 하자.


  • 총 게시글 수 77개
[1] [2] [3] [4] [5] [6] [7] [8]
총 게시글 수가 77이면 페이지 번호의 끝 번호가 8이여야 한다.
페이지의 끝 번호를 알기 위해서는 총 게시글의 수가 필요하다.

  • 총 게시글 수 135개
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [다음]
[이전] [11] [12] [13]
화면에 보여줄 페이지 버튼의 수가 10개 이상이라면 다음 버튼을 이용해 다음 페이지를 이용할 수 있어야 한다.
시작 페이지의 번호가 1이 아니라면 이전 버튼을 이용해 이전 페이지를 이용할 수 있어야 한다.

  • 총 게시글 수 215개

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [다음]

[이전] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [다음]

[21] [22]

현재 페이지의 번호가 1~10 사이라면 시작 번호는 1이여야 한다.

현재 페이지의 번호가 11~20 사이라면 시작 번호는 11이여야 한다.



2. 페이징 원칙

페이징 처리를 함에 있어서 원칙들이 있다. 

  • 페이징 처리는 반드시 GET 방식만을 이용해야 한다.
  • 게시글 목록 페이지의 하단에 페이지들의 번호를 보여주고 원하는 번호를 선택하면 해당 페이지로 이동해서 목록을 보여줘야 한다.
  • 페이징은 반드시 필요한 페이지 번호만 출력해야 한다. 만약 페이지당 10개의 게시글을 출력하는데 전체 게시글의 수가 42개라면 페이지의 번호는 5페이지까지여야 한다.
  • 이전과 다음 버튼이 존재해야 한다. 게시글이 1000개인데 1페이지당 10개의 게시글을 볼 수 있게 했다면 페이징 버튼은 100개가 필요하다. 그런데 이전과 다음 버튼이 존재하지 않는다면 100개의 버튼을 한번에 보여줘야 한다. 그렇기때문에 하단 페이지에 보여줄 버튼의 갯수를 정하고 더 많은 데이터가 있다면 이전과 다음 버튼으로 표시해줘야 한다.
  • 게시글을 조회하거나 수정, 삭제를 하고 난 뒤, 다시 원래의 목록 페이지로 이동해야 한다. 예를 들면 게시판에 5페이지에 있는 어떠한 게시물을 조회하거나 수정, 삭제를 했다고 한다면, '목록으로'버튼을 이용해 목록으로 돌아갈 땐 5페이지로 이동해야 한다.



3. SQL : LIMIT

페이징 처리를 확인하기 위해서 DB에 100개의 데이터를 넣어뒀다. 그럼 게시판 목록을 조회하는 쿼리를 실행하게 되면 어떻게 될까?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mysql> SELECT ...
    -> FROM board
    -> WHERE DEL_CHK = 'N'
    -> ORDER BY IDX DESC;
+-----+--------------+---------+------------+-------------+
| IDX | TITLE        | HIT_CNT | CREA_DATE  | CREA_ID     |
+-----+--------------+---------+------------+-------------+
| 100 | 타이틀100    |       0 | 2018.11.26 | 테스트100    |
|  99 | 타이틀99A    |       0 | 2018.11.26 | 테스트99     |
|  98 | 타이틀98     |       0 | 2018.11.26 | 테스트98     |
|                      . . . .                            |
|   4 | 타이틀4      |       0 | 2018.11.26 | 테스트4      |
|   3 | 타이틀3      |       0 | 2018.11.26 | 테스트3      |
|   2 | 타이틀2      |       0 | 2018.11.26 | 테스트2      |
|   1 | 타이틀1      |       0 | 2018.11.26 | 테스트1      |
+-----+--------------+---------+------------+-------------+
100 rows in set (0.01 sec)
cs


100개의 게시글이 한번에 나올 것이다. 한 페이지(화면)에 100개 혹은 1000개의 게시글을 한번에 보여주기엔 벅차다. 그렇기에 게시글 목록에는 페이징 처리가 반드시 필요하다. DB에 따라 페이징 처리를 할 수 있는 쿼리가 존재한다고 한다. 그렇기에 각자 사용하는 DB를 확인해서 쿼리를 사용하면 된다. 나는 MySQL을 사용하기 때문에 LIMIT을 이용해서 페이징 처리를 할 것이다.


1
2
3
4
SELECT *
FROM 테이블명
ORDER BY 게시글 번호 DESC
LIMIT 시작 행, 출력할 갯수
cs


LIMIT을 위와 같이 사용하게 되면 특정 페이지의 게시글을 보여줄 수 있다. 게시글 번호로 내림차순 정렬한 데이터를 출력할 행부터 출력할 갯수까지 조회해주는 쿼리이다. 데이터의 행은 0부터 시작한다. 따라서 LIMIT 0, 10 이라고 설정하면 0행부터 10개까지의 게시글이 조회될 것이다. 그러면 페이징 처리를 하기 위해선 어떻게 조회를 해야 할까?


1페이지 -> 00행 ~ 09행 (10개) : LIMIT 0, 10

2페이지 -> 10행 ~ 19행 (10개) : LIMIT 10, 10

3페이지 -> 20행 ~ 29행 (10개) : LIMIT 20, 10



이런식으로 페이징 처리가 이루어져야 한다. 그래서 특정 페이지의 첫번째 게시글의 행번호와 출력할 갯수만 전달 받는다면 특정 페이지의 게시글들을 조호할 수 있을 것이다. 나는 전달받을 파라미터들을 각각 pageStart와 perPageNum으로 정했다. 그러면 아래와 같은 쿼리로 페이징 처리를 하면 된다.


1
2
3
4
5
SELECT ...
FROM board
WHERE DEL_CHK='N'
ORDER BY IDX DESC
LIMIT #{pageStart}, #{perPageNum}
cs
  • pageStart : 특정 페이지의 첫번째 게시글의 행이다.
  • perPageNum : 한 페이지당 보여줄 게시글의 개수이다.

특정 페이지를 조회하기 위해 두 개의 파라미터를 담는 클래스를 만들 것이다. 이렇게 클래스를 만드는 이유는 뭘까? 게시판에도 여러 종류의 게시판이 존재한다. 그러면 게시판 마다 페이징 조회 로직을 생성해야 한다. 하지만 페이징 관련된 기능들을 별도의 클래스로 분리해놓는다면 조금 더 효율적인 작업을 할 수 있다. 



4. 특정 페이지 조회를 위한 Criteria 클래스

게시글 조회 쿼리에 전달될 파라미터를 담게 될 클래스이다. VO라고 생각하면 쉬울 것이다.


Criteria

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Criteria {
    
    private int page;
    private int perPageNum;
    
    public int getPageStart() {
        return (this.page-1)*perPageNum;
    }
    
    public Criteria() {
        this.page = 1;
        this.perPageNum = 10;
    }
    
    public int getPage() {
        return page;
    }
    public void setPage(int page) {
        if(page <= 0) {
            this.page = 1;
        } else {
            this.page = page;
        }
    }
    public int getPerPageNum() {
        return perPageNum;
    }
    public void setPerPageNum(int pageCount) {
        int cnt = this.perPageNum;
        if(pageCount != cnt) {
            this.perPageNum = cnt;
        } else {
            this.perPageNum = pageCount;
        }
    }
    
}
cs
  • int page : 현재 페이지 번호
  • int perPageNum : 한 페이지당 보여줄 게시글의 갯수
  • int getPageStart() : 특정 페이지의 게시글 시작 번호, 게시글 시작 행 번호

1
2
//현재 페이지의 게시글 시작 번호 = (현재 페이지 번호 - 1) * 페이지당 보여줄 게시글 갯수
getPerPageNum = (this.page - 1* perPageNum
cs


 현재 페이지 번호

 페이지당 보여줄 게시글 수

 계산식

 게시글 시작 행 번호

 5

 10

 (5-1)*10

 40

 3

 5

 (3-1)*5

 10

 15

 10

 (15-1)*10

 140

  • Criteria() : 기본 생성자
1
2
this.page = 1;
this.perPageNum = 10;
cs


최초로 게시판 목록에 들어 왔을 때를 위해서 기본 셋팅을 해야 한다. 왜냐하면 페이징을 처리하기 위해선 현재 페이지 번호와 페이지당 게시글 수가 필요한데 처음 게시판에 들어오게 되면 두 개의 정보를 가져올 방법이 없기 때문에 기본 생성자를 통해 기본 값을 셋팅하도록 하자. 현재 페이지를 1페이지로, 페이지당 보여줄 게시글의 수를 10개로 기본 셋팅해두었다.

  • setter : 잘 못된 값들이 셋팅되지 않게 적절하게 set 메서드 셋팅
- setPage() : 페이지가 음수값이 되지 않게 설정. 음수가 되면 1페이지를 나타낸다.
- setPerPageNum() : 페이지당 보여줄 게시글 수가 변하지 않게 설정했다.
  • getter : get 메서드를 셋팅



5. 게시판 페이징을 처리하는 PageMaker 클래스

페이징에 관련된 버튼들을 만드는 기능을 하는 클래스이다. 페이지에 페이징 버튼들을 만들기 위한 계산 클래스라고 생각하면 된다. 그래서 계산이 필요한 부분이 많다.(ㅠㅠ) 하지만 그냥 공식이라 생각하고 이렇게 쓰는구나, 정도의 이해만 하고 넘어가도 된다.


PageMaker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class PageMaker {
    
    private Criteria cri;
    private int totalCount;
    private int startPage;
    private int endPage;
    private boolean prev;
    private boolean next;
    private int displayPageNum = 5;
    
    public Criteria getCri() {
        return cri;
    }
    public void setCri(Criteria cri) {
        this.cri = cri;
    }
    public int getTotalCount() {
        return totalCount;
    }
    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
        calcData();
    }
    
    private void calcData() {
        
        endPage = (int) (Math.ceil(cri.getPage() / (double) displayPageNum) * displayPageNum);
 
        startPage = (endPage - displayPageNum) + 1;
        if(startPage <= 0) startPage = 1;
        
        int tempEndPage = (int) (Math.ceil(totalCount / (double) cri.getPerPageNum()));
        if (endPage > tempEndPage) {
            endPage = tempEndPage;
        }
 
        prev = startPage == 1 ? false : true;
        next = endPage * cri.getPerPageNum() < totalCount ? true : false;
        
    }
    
    public int getStartPage() {
        return startPage;
    }
    public void setStartPage(int startPage) {
        this.startPage = startPage;
    }
    public int getEndPage() {
        return endPage;
    }
    public void setEndPage(int endPage) {
        this.endPage = endPage;
    }
    public boolean isPrev() {
        return prev;
    }
    public void setPrev(boolean prev) {
        this.prev = prev;
    }
    public boolean isNext() {
        return next;
    }
    public void setNext(boolean next) {
        this.next = next;
    }
    public int getDisplayPageNum() {
        return displayPageNum;
    }
    public void setDisplayPageNum(int displayPageNum) {
        this.displayPageNum = displayPageNum;
    }
 
}
cs

- 22행: 총 게시글 수를 셋팅할때 calcData() 메서드를 호출하여 페이징 관련 버튼 계산을 한다.

- 25행: 페이징의 버튼들을 생성하는 계산식을 만들었다. 끝 페이지 번호, 시작 페이지 번호, 이전, 다음 버튼들을 구한다.

  • Criteria cri.getPage() : 현재 페이지 번호
  • Criteria cri.getPerPageNum() : 한 페이지당 보여줄 게시글의 갯수
  • int totalCount : 총 게시글 수
1
2
SELECT count(*)
FROM board
cs

조회 쿼리에서 count(*)를 이용해서 구해야 한다. 총 게시글 수 쿼리는 조금 있다가 설정할 것이다.

  • int endPage : 화면에 보여질 마지막 페이지 번호, 끝 페이지 번호
1
2
//끝 페이지 번호 = (현재 페이지 번호 / 화면에 보여질 페이지 번호의 갯수) * 화면에 보여질 페이지 번호의 갯수
endPage = (int) (Math.ceil(cri.getPage() / (double) displayPageNum) * displayPageNum);
cs


 현재 페이지 번호

 페이지 번호의 갯수

 계산식

 끝 페이지 번호

 1

 10

 Math.ceil(1/10) * 10

 10

 3

 10

 Math.ceil(3/10) * 10

 10

 13

 10

 Math.ceil(13/10) * 10

 20

 23

 20

 Math.ceil(23/20) * 20

 40


끝 페이지 번호는 총 게시글 수와 연관이 있다. 근데 100개의 게시글을 20개씩 보여준다고 하면 끝 페이지의 번호가 5여야 하는데 위의 계산식으로 계산을 하게 되면 끝 페이지 번호가 20이 나오게 된다. ( Math.ceil(1/20)*20 = 20 ) 그래서 총 게시글 수와 페이지당 보여줄 게시글의 갯수로 마지막 페이지 번호를 구해 서로 비교해서 화면에 보여질 끝 페이지 번호를 구해야 한다.


1
2
3
4
5
//마지막 페이지 번호 = 총 게시글 수 / 한 페이지당 보여줄 게시글의 갯수
int tempEndPage = (int) (Math.ceil(totalCount / (double) cri.getPerPageNum()));
if (endPage > tempEndPage) {
    endPage = tempEndPage;
}
cs


마지막 페이지의 번호를 구한 뒤, 끝 페이지 번호보다 작은 경우에 마지막 페이지의 번호를 끝 페이지 번호로 저장해준다. 화면에 보여질 끝 페이지 번호는 마지막 페이지의 번호보다 클 수는 없다. 그렇기 때문에 위와 같은 조건을 넣어줘야 한다. 이 부분은 시작 페이지 번호까지 구한 뒤에 처리해줘야 한다.


  • int startPage : 화면에 보여질 첫번째 페이지 번호, 시작 페이지 번호
1
2
3
//시작 페이지 번호 = (끝 페이지 번호 - 화면에 보여질 페이지 번호의 갯수) + 1
startPage = (endPage - displayPageNum) + 1
if(startPage <= 0) startPage = 1
cs


 끝 페이지 번호

 페이지 번호의 갯수

 계산식

 시작 페이지 번호

 10

 10

 (10-10) + 1

 1

 30

 10

 (30-20) + 1

 11

 40

 20

 (40-20) + 1

 21

 20

 5

 (20-5) + 1

 16


시작 페이지 번호를 구할 때, 마지막 페이지 번호가 화면에 보여질 페이징 버튼의 갯수보다 작으면 문제가 생긴다. 시작 페이지 번호가 음수가 되어버리는 상황이 발생한다. 예를들면 끝 페이지의 번호가 3이고, 보여줄 페이지 갯수가 5라면, 시작 페이지 번호는 -1이 된다. 따라서, 구한 시작페이지 번호가 0보다 작으면(음수) 시작 페이지를 1로 해주는 로직을 추가해야 한다.

  • boolean prev : 이전 버튼 생성 여부
1
2
//이전 버튼 생성 여부 = 시작 페이지 번호 == 1 ? false : true
prev = startPage == 1 ? false : true
cs

이전 버튼은 시작 페이지 번호가 1이 아니면 생기면 된다.


  • boolean next : 다음 버튼 생성 여부
1
2
//다음 버튼 생성 여부 = 끝 페이지 번호 * 한 페이지당 보여줄 게시글의 갯수 < 총 게시글의 수 ? true: false
next = endPage * cri.getPerPageNum() < totalCount ? truefalse
cs


 끝 페이지 번호

 페이지당 게시글 수

 총 게시글 수

 계산식

 다음 버튼 생성 여부

 7

 10

 65

 7 * 10 < 65

 false

 10

 10

 100

 10 * 10 < 100

 false

 10

 10

 127

 10 * 10 < 107

 true

 20

 10

 260

 20 * 10 < 260

 true


  • int displayPageNum : 화면 하단에 보여지는 페이지 버튼의 수
보여지는 버튼의 수를 정하면 된다. 나는 5개만 보이게 할 것이다.

PageMaker 객체를 사용하려면 setCri() 와 setTotalCount()를 먼저 호출해서 값을 셋팅해야 한다. 페이징 버튼들의 값을 구하려면 제일 먼저 총 게시글 수가 있어야 위의 계산식대로 차례로 구할 수 있다. 그렇기에 총 게시글을 셋팅할 때 계산식 메소드를 호출하게 한 것이다. 또한 Criteria 객체에서 필요한 page 와 perPageNum을 사용하기 위해서 setCri()를 먼저 셋팅해야 한다. 컨트롤러에서 객체로 값을 셋팅할 때 유의하자.



6. 목록 조회 수정

** 이전에 만들어 둔 CURD 게시판을 수정해서 사용한다.


6-1. Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RequestMapping(value="/board/boardList")
public ModelAndView openBoardList(Criteria cri) throws Exception {
        
    ModelAndView mav = new ModelAndView("/board/boardList");
        
    PageMaker pageMaker = new PageMaker();
    pageMaker.setCri(cri);
    pageMaker.setTotalCount(100);
        
    List<Map<String,Object>> list = boardServcie.selectBoardList(cri);
    mav.addObject("list", list);
    mav.addObject("pageMaker", pageMaker);
        
    return mav;
        
}
cs

- 02행: 현재 페이지 번호와 페이지당 보여줄 게시글 수가 담긴 Criteria 객체를 사용한다.

- 06행: PageMaker() 객체를 생성한다.

- 07행: page와 perPageNum을 셋팅해준다.

- 08행: 총 게시글의 수를 셋팅해준다. 아직 총 게시글 수를 조회하는 로직은 구현하지 않았기 때문에 현재 DB에 있는 총 게시글의 수인 100을 넣어줬다.

- 10행: 원래의 목록 조회 로직에서 Criteria 파라미터를 사용하기 위해 수정했다.

- 12행: 셋팅된 pageMaker에는 페이징을 위한 버튼의 값들이 들어있고 ModelAndView를 이용해 jsp에 넘겨준다.


6-2. Service 영역 및 DAO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//BoardService
List<Map<String, Object>> selectBoardList(Criteria cri);
 
//BoardServiceImpl
@Override
public List<Map<String, Object>> selectBoardList(Criteria cri) {
    return boardDAO.selectBoardList(cri);
}
 
//BoardDAO
@SuppressWarnings("unchecked")
public List<Map<String, Object>> selectBoardList(Criteria cri) {
    return (List<Map<String,Object>>)selectList("board.selectBoardList", cri);
}
cs

게시글 목록 조회하는 Service, DAO 영역에 Criteria 객체에 담긴 파라마터를 보내기 위해 수정했다. 각자의 목록 조회에 맞게 수정하면 된다. Criteria 객체에 담아서 SQL 매핑에 보낼 파라미터는 특정 페이지 게시글의 행(pageStart)과 페이지당 보여줄 게시글의 갯수(perPageNum)이다.


6-3. SQL

1
2
3
4
5
6
7
8
9
10
11
12
<select id="selectBoardList" resultType="hashmap" parameterType="hashmap">
    <![CDATA[
        SELECT
            *
        FROM
            board
        WHERE
            DEL_CHK = 'N'
        ORDER BY IDX DESC
        LIMIT #{pageStart}, #{perPageNum}
    ]]>
</select>
cs

- 10행: 페이징 조회를 위해 LIMIT를 이용해서 원래의 목록 조회 쿼리를 수정했다.


6-4. JSP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<ul class="btn-group pagination">
    <c:if test="${pageMaker.prev }">
    <li>
        <a href='<c:url value="/board/boardList?page=${pageMaker.startPage-1 }"/>'><i class="fa fa-chevron-left"></i></a>
    </li>
    </c:if>
    <c:forEach begin="${pageMaker.startPage }" end="${pageMaker.endPage }" var="pageNum">
    <li>
        <a href='<c:url value="/board/boardList?page=${pageNum }"/>'><i class="fa">${pageNum }</i></a>
    </li>
    </c:forEach>
    <c:if test="${pageMaker.next && pageMaker.endPage >0 }">
    <li>
        <a href='<c:url value="/board/boardList?page=${pageMaker.endPage+1 }"/>'><i class="fa fa-chevron-right"></i></a>
    </li>
    </c:if>
</ul>
cs

- 02행: 이전 버튼의 생성 여부를 확인하여 버튼을 보여줄 것이다.

- 06행: 현재 페이지가 어디인 지 알기 위해 추가했다.

- 07행: 페이지의 시작 번호와 끝 번호를 이용해 페이지 버튼들을 뿌려줄 것이다.

- 12행: 다음 버튼의 생성 여부를 확인하여 버튼을 보여줄 것이다.



7. 총 게시글 갯수 구하기 (totalCount)

그럼 마지막으로 총 게시글 갯수를 구하는 로직을 만들자. 


7-1. SQL

1
2
3
4
5
6
7
8
9
10
<select id="countBoardList" resultType="Integer">
    <![CDATA[
        SELECT
            count(*)
        FROM
            board
        WHERE
            DEL_CHK='N'
    ]]>
</select>
cs

- 01행: 결과는 int로 리턴되어야 한다.

- 04행: 조회한 결과의 갯수를 뿌려주는 쿼리이다.

- 08행: 총 게시글 중에 삭제된 건 빼야 한다.


7-2. DAO

1
2
3
public int countBoardList(){
    return (Integer) selectOne("board.countBoardList");
}
cs


7-3. Service 영역

1
2
3
4
5
6
7
8
//Service
int countBoardListTotal();
 
//ServiceImpl
@Override
public int countBoardListTotal() {
    return boardDAO.countBoardList();
}
cs


7-4. Controller

1
 pageMaker.setTotalCount(boardServcie.countBoardListTotal());
cs

100으로 셋팅한 부분에 총 게시글 수를 구하는 로직을 넣었다.



8. 확인

밑에 페이징 버튼들이 나오고 10개의 게시글만 나왔다! 그럼 다른 페이지의 버튼를 눌러보자.

페이지에 따라 목록이 바뀐다. 이전, 다음 버튼도 알맞게 구동된다!


페이징 처리에 성공했지만 아직 개선해야 될 부분이 남아있다. 페이징 원칙에서도 언급했는데, 특정 페이지의 한 게시글을 조회, 수정, 삭제를 하고 난 후에 다시 목록으로 돌아가게 될 경우 그 특정 페이지로 돌아가야 한다. 그 부분만 해결된다면 페이징 처리는 완성된것이다.


댓글을 달아 주세요

  1. DEV.talk 2019.02.22 14:31

    안녕하세요. 덕분에 페이징 처리를 잘 하게 되었습니다 ^^
    한가지 궁금한 게 있는데요. 위 소스 그대로 사용하면 에러가 안나는 지요!

    저는 에러가 나서 봤더니.
    jsp에서 페이지 번호 생성하는 forEach 문에서 begin < 0 이어서 에러가 뜨더라구요.
    페이지 번호 갯수가 5개 이하인 경우에서는 에러가 나는 거 같습니다.

    제 상황을 예를 들어보겠습니다.
    총 게시물이 23개이고, 한 화면에 보여지는 페이지 번호 갯수는 5개
    endPage 가 3개가 됩니다.
    그럼 startPage 계산하는 부분을 보자면

    startPage = (endPage(3) - 보여지는 번호 갯수(5)) + 1
    그럼 startPage = -1 이 나오게 되어서 startPage 정의 밑에
    if(startPage <= 0) startPage = 1 를 추가해서 했습니다.


    아니면 제가 다른 부분에서 틀린 부분 때문에 이런 걸까요 .. ?ㅠ.ㅠ

    • BlogIcon #에게 2019.02.22 14:37 신고

      네! 맞아요! 추가하신거 넣으시는 게 맞아요!!!! 제가 여기 글엔 수정을 안했네요ㅠㅠㅠ 혼란을 드리게 해서 죄송합니다..

    • DEV.talk 2019.02.22 14:50

      아앗 그렇군요 ㅎㅎ 아닙니다 !!
      쉬운 에러여서 금방 고쳤어요 !!
      #에게님 덕분에 페이징 처리
      쉽게 잘했는 걸요 ㅎㅎ 감사합니다 ^^

      좋은 하루 되세요 !!

    • BlogIcon #에게 2019.02.22 18:28 신고

      네 늦었지만 좋은 하루되세요~!

    • 지나가던사람 2019.07.02 01:40

      음.. 저 문제는 단순히
      startPage = (endPage - displayPageNum) + 1; 를
      endPage선언 바로 뒤에 넣으면 조건문 쓰지 않아도 가능하죠?
      궁금해서 여쭤봅니당

  2. 스니님 2019.05.21 19:50

    감사합니다 정말 도움을 많이 얻고 있습니다!! 혹시 회원가입 로그인 게시판 연동하시는건 아직 소개 안되있는거죠??

    • BlogIcon #에게 2019.05.21 20:27 신고

      네ㅠㅠ 제가 요즘 따로 공부할 시간이 없어서 멈춰있어요ㅠㅠ 흑흑 얼른 해야 되는데... 글은 없는데 프로젝트를 보고 싶으면 제 깃허브가시면 있어요!

    • 스니님 2019.05.21 20:30

      넵!! 언제나 감사드립니다 ㅎㅎ

  3. 감사해요 2019.05.28 17:36

    감사합니다 덕분에 페이징 잘 구현했습니다.

  4. 코머 2019.05.30 13:58

    게시판 두번째 정주행 완료 ~ 아직 갈길이 먼것같네요 ㅜㅜ

  5. 지나가던사람 2019.07.02 01:41

    지식나눔 감사합니다. 덕분에 좋은지식 얻어가요!!!!!!!!!!

  6. 2019.07.08 14:25

    비밀댓글입니다

  7. BlogIcon 곽빵 2019.07.14 15:38 신고

    저 다음버튼 생성여부에 예시로 든 표 내용중에 끝 페이지 번호 7인거 다음버튼 생성여부 false 라고 되어있는데
    잘못된거 같아요~~ ㅎㅎ 감사합니다 덕분에 페이징에대해서 완벽하게 알게된거 같아요!

  8. 2019.12.02 17:18

    비밀댓글입니다

  9. chobo 2020.02.27 09:05

    안녕하세요 혹시 DB Board 테이블에 관한 정보 좀 알 수 있을까요?
    상단의 테이블 속성외에 DEL_CHK같은 속성이 추가로 있던데 무엇을 의미하는지 이해가 잘 안가서요.. ㅜㅜ

    • BlogIcon #에게 2020.02.27 09:42 신고

      DEL_CHK 칼럼은 게시글 삭제여부를 나타냅니다. 게시글 삭제를 어떻게 구현하냐에 따라서 DEL_CHK 부분이 변경되겠네요! 만약 DB삭제(sql문의 delete)로 구현하셨다면 Where 조건에서 DEL_CHK='Y' 는 안해도 되는 거죠!

  10. chobo 2020.02.27 14:58

    안녕하세요 블로그 따라서 페이징 기능 구현하고 있는데 주변에 물어볼데가 없어서 여쭤봅니다.. ㅜㅜ
    타입 예외 보고

    메시지 Handler processing failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.springframework.jdbc.support.SQLErrorCodesFactory

    설명 서버가, 해당 요청을 충족시키지 못하게 하는 예기치 않은 조건을 맞닥뜨렸습니다.

    예외

    org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.springframework.jdbc.support.SQLErrorCodesFactory
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:972)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    이런식으로 에러가 발생하는데 구글링해봤지만 해결을 못하였습니다.. 혹시나 필자님은 아시나 해서 여쭤봅니다.
    감사합니다.

    • BlogIcon #에게 2020.02.27 15:16 신고

      음 이건.. jar파일에 문제가 있어보이네여ㅠㅠ.. 이클립스 껐다가 다시 켜보시거나 Project Clean 이나.. Build Path 설정을 확인해봐야 할 거 같아요 아니면 환경변수가 제대로 설정되었는지도 확인해야 될 듯 해요..

  11. chobo 2020.02.27 15:39

    답변 감사합니다. 위에 질문에 대해 더 여쭤볼게 있는데.. 아직 해결은 못했는데...
    mapper부분의 selectBoardList 부분의 LIMIT #{pageStart}, #{perPageNum} 부분을 제거하면 결과가 나오긴 하는데
    (페이징이 구현되지 않은 결과입니다.) 앞서 말씀하신게 문제라면 #{pageStart}, #{perPageNum} 부분을 제거하더라도 화면이 나오지 않아야 하는건가요? 이 부분과는 별개의 오류인가요?

    • BlogIcon #에게 2020.02.27 15:56 신고

      음!! 그러면 그 LIMIT 부분에 문제에요! SQL문이 문제가 있던거네요 오타라던지(대소문자가 구분이됩니다).. 혹시 mysql이 아니라 다른 걸로 하셨나요?

  12. chobo 2020.02.27 16:25

    oracle sql developer로 하였습니다...

    • BlogIcon #에게 2020.02.27 16:29 신고

      오라클은 LIMIT 를 사용할 수 없어요ㅠㅠ 오라클에는 존재하지않는 구문? 기능? 이라서요.. 오라클에 맞는 구문으로 적용하셔야해요!

  13. chobo 2020.02.27 16:33

    아 알아보니 oracle은 rownum을 사용해서 하는것 같습니다. 상세한 답변 감사합니다!!
    좋은 글 항상 감사합니다~

  14. 공부 2020.04.06 15:28

    안녕하세요!
    따라하다가 조금 막히는 부분이 있어서 댓글 남깁니다
    6-4 jsp는 어디에 넣은건가요?
    새로 생성하신건지, 기존에 있던 jsp를 수정해서 만드신 건지 궁금합니다

  15. Min 2020.05.26 13:43

    감사합니다 덕분에 페이징 성공했어요!

  16. ㅂㅂ 2020.07.22 17:44

    컨트롤러, 서비스, dao 패키지가 있다고 치면 페이징처리 클래스는 어디패키지에 넣어야하나요?