게시판9) 게시판 페이징

  • 1000개의 글이 있다고 쳤을 때, 이 글을 한 페이지에 보여주는 것 보다 여러 페이지에 보여주는 것이 훨씬 정보를 쉽게 전달할 수 있다. 아래와 같이 페이지를 나누고, 글 번호도 그에 따라 줘보도록 한다.

1202sp1

1202sp2

1202sp3

페이징 개념

  • 한 페이지에 내가 20 개의 글을 보여주고 싶을 수도 있고, 10개의 글을 보여주고 싶을 수도 있다. 이것을 countPerPage 라고 하자. 이걸 기준으로 페이징을 시작할 수 있다.

    1202sp4

과정

  1. countPerPage 를 정한다. (나는 10으로 정했다)
  2. totalRecordCount 는 record가 총 몇개 있는지 읽어온다.
  3. totalPageCount는 totalRecordCount + (countPerPage-1) 를 countPerPage 로 나누면 구할 수 있다. 여기서 만약 “totalRecordCount/countPerPage” 만 하면, 나머지 글이 담길 페이지가 없어서 안된다. 그냥 한페이지를 더해준다고 했을 때 나머지가 0일 때 불필요한 페이지가 생생된다. 그래서 저렇게 해준다.
  4. currentPage 는 현재 페이지가 몇쪽인지 알려준다.
  5. 현재 페이지의 srow(글 시작번호)와 erow(글 끝번호)는 currentPage와 countPerPage를 이용해 구할 수 있다.
  • 만약 이 과정이 어렵게 생각된다면, 그냥 간단한 숫자를 대입해보면 쉽게 이해될 것이다.
    • 11개의 글이 있다고 할 때 totalRecordCount =11 이다.
    • 한페이지에 5개의 글을 넣고싶다고 하면 countPerPage=5 가된다. 총 페이지는 (11+5-1)/5 = 3totalPageCount=3이다. (1페이지 : 1개글, 2페이지: 5개글, 3페이지: 5개글).
    • currentPage=2 **라면, 행의 시작값은 (2-1)*5+1이 된다. **srow = 6
    • erow =10이다.

변수들은 다음과 같이 생성된다. (아래서 좀 더 자세히 볼 것이다.)

countPerPage = 10;
totalRecordCount = repository.getBoardCount(searchItem,searchWord);
totalPageCount = (totalRecordCount+countPerPage-1)/countPerPage;
currentPage
srow = 1+(currentPage-1)*countPerPage;
erow = currentPage*countPerPage;

페이징 코드

controller

  • @RequestParam으로, currentPage에 대한 정보가 전달되지 않을 때는 디폴트로 1을 준다. 인덱스에서 boardList로 넘어올 때 항상 1페이지로 되어있다.

    @RequestParam(value="currentPage",defaultValue="1") int currentPage
    
  • 변수는 위에서 설명한 대로 만든다. 그리고 model에 저장해서 jsp에서 꺼내쓸 수 있게 해준다.

    int totalRecordCount = repository.getBoardCount(searchItem,searchWord);
    int countPerPage = 10;
    int totalPageCount = (totalRecordCount+countPerPage-1)/countPerPage;
    //srow,erow는 jsp 에서는 안 쓰이고,DB에서 record 가져올 때 쓰임
    int srow = 1+(currentPage-1)*countPerPage;
    int erow = currentPage*countPerPage;
    
    model.addAttribute("currentPage",currentPage);
    model.addAttribute("totalRecordCount",totalRecordCount);
    model.addAttribute("totalPageCount",totalPageCount);
    
  • 전체 코드

    @RequestMapping("/boardlist")
    public String boardList(
        @RequestParam(value="currentPage",defaultValue="1") int currentPage,
        @RequestParam(value="searchItem", defaultValue ="title") String searchItem,
        @RequestParam(value="searchWord", defaultValue ="") String searchWord,
        Model model) {
        int totalRecordCount = repository.getBoardCount(searchItem,searchWord);
        int countPerPage = 10;
        int totalPageCount = (totalRecordCount+countPerPage-1)/countPerPage;
        int srow = 1+(currentPage-1)*countPerPage;
        int erow = currentPage*countPerPage;
        List<Board> list = repository.boardList(srow,erow,searchItem,searchWord);//글 목록 조회
        model.addAttribute("list",list);
        model.addAttribute("currentPage",currentPage);
        model.addAttribute("searchItem", searchItem);
        model.addAttribute("searchWord", searchWord);
        model.addAttribute("totalRecordCount",totalRecordCount);
        model.addAttribute("totalPageCount",totalPageCount);
        return "board/boardList";
    }
    

repository

  • DB에서 srow ~ erow 까지의 정보를 요청하고 가져와준다.

    public List<Board> boardList(int srow, int erow, String searchItem, String searchWord) {
        Map<String,Object> map = new HashMap<String,Object>();
        BoardMapper mapper =  session.getMapper(BoardMapper.class);
        map.put("searchItem",searchItem);
        map.put("searchWord",searchWord);
        map.put("srow",srow);
        map.put("erow",erow);
        List<Board> list = mapper.boardList(map);
        return list;
    }
    

boardMapper.xml

  • 좀 복잡하다!

  • DB에서 제공해주는 ROWNUM이 우리가 arg로 전달한 srow와 erow 범위에 있으면 데이터를 가져오려고 한다 . ROWNUM은 DB가 기본으로 제공해주는 데이터이므로, 우리 테이블 열네임에는 포함되어있지않다. 그래서 그것을 우리 테이블 열에 포함시키기 위해 아래와 같은 작업을 해준다.

    SELECT ROWNUM as nu, temp.* FROM (
    SELECT boardseq, userid, title, message, to_char(regdate, 'YYYY-MM-DD') as regdate, hitcount, originalfile, savedfile
    FROM board) temp
    
  • 이렇게 하면, ROWNUM과 BOARDTABLE의 정보를 가진 TEMP 테이블이 생성된다.

  • 그 런 데! 이렇게 해서 바로 WHERE절을 쓰면 안된다!

    • SELECT * FROM TEMP WHERE ROWNUM >= 1 AND ROWNUM <=10 일케하면 1~10까지는 나오지만,

    • SELECT * FROM TEMP WHERE ROWNUM >= 11 AND ROWNUM <=20 은 안 나온다.

      왜냐면, ROWNUM은 동적 데이터라서 항상 1번부터 나타난다.

  • 해결방법은 간단하다. SELECT * FROM 으로 감싸서 하나의 테이블로 정착? 시켜버리면 된다.

  • 그리고 <= 이거 먹히지 않는다. 태그로 알아먹어서.. 그래서

    &gt; &lt; 로 써줘야한다.
    
  • 대충 전체 코드

    <select id="boardList" resultType="Board" parameterType="map">
        SELECT * FROM (
        SELECT ROWNUM as nu, temp.* FROM (
        SELECT boardseq, userid, title, message, to_char(regdate, 'YYYY-MM-DD') as regdate, hitcount, originalfile, savedfile
        FROM board) temp
        ) WHERE nu &gt;= #{srow} AND nu &lt;= #{erow}
    </select>
    

boardList.jsp

  • 위 DB에서 가져온 자료들은 controller에서 list에 저장된다.
  • list에는 해당 페이지에 들어가야할 board 객체들이 들어있다.

  • 예를들어 2페이지라면, DB에서 11~20의 ROWNUM을 가지는 board가 list에 들어가있다.
<c:forEach var= "board" items="${list}" varStatus="status">
<tr>
<td>${ status.count + (currentPage-1)*10}</td>
    </tr>
</c:forEach>

페이지 번호

  • 쉬우니 설명 생략!

    <div class = "navigator">
        전체 글개수 : ${totalRecordCount }<br><c:forEach var ="page" begin="1" end = "${totalPageCount }">
            <c:if test = "${currentPage eq page}">
                <span style = "color : red; font-weight: bold">"${page}"</span>
            </c:if>
            <c:if test = "${currentPage ne page}">
                <a href = "boardlist?currentPage=${page }&currentPage=${page}&searchItem=${ searchItem}&searchWord=${searchWord}">
                    ${page} &nbsp;
                </a>
            </c:if>
        </c:forEach></div>
    

◇ Spring 게시판 포스팅 시리즈 ◇

  1. Spring 과 DB 연결하기
  2. 회원 가입 화면 구성
  3. ID 중복 확인 하기
  4. 로그인 페이지 만들기
  5. 게시판 화면 구성하기
  6. 글 쓰기 기능 구현
  7. 글 확인 기능 구현
  8. 글 수정 기능 구현
  9. 게시판 페이징 - 현재 글
  10. 파일 첨부 기능
  11. 파일 다운 기능
  12. MIME 타입
  13. 글 수정시 파일 변경

© 2018. All rights reserved.

Powered by Hydejack v8.5.2