[WEB] 게시판 페이징(페이지 번호 매기기) 코드 해석 | startRow, endRow

게시판에 페이지 번호를 매기는 작업은 필수적이다. 한 화면에 보여줄 글의 개수가 정해지고 그 개수를 초과하면 페이지가 [1] [2] [3] ... 과 같이 추가되는 식이다.

 

구현 코드는 검색하면 쉽게 찾을 수 있다. 변수 선언을 이런 식으로 한다.

int pageSize = 10; // 한 페이지의 글 개수
int currentPage = Integer.parseInt(pageNum); // 현재 페이지
int startRow = (currentPage - 1) * pageSize + 1; // 한 페이지의 시작글 번호
int endRow = currentPage * pageSize; // 한 페이지의 마지막 글번호
int count = 0;
int number = 0;

그러나 나는 이 코드가 어떻게 동작하는 것인지 이해되지 않았다. 여러 블로그를 돌아다니며 해답을 찾았지만 코드에 대한 설명을 해주는 곳은 찾기 힘들었다. 솔직히 죄다 코드 복붙에 주석만 딸랑 달아놨는데 그마저도 의미하는 바가 중구난방이라 더 헷갈렸다...

 

때문에 내가 알게된 선에서 간단히 정리하기 위해 글을 쓴다. 내용에 잘못된 부분을 지적해주시면 감사히 수정하겠다.


페이징 작업은 한 화면에 몇 개의 게시글을 보여줄지를 정하는 것부터 시작한다. 만약 10개라고 정하면 이 값은 고정값인 상수가 된다. 이제 이 상수를 이용해서 게시글을 10개 단위로 쪼개는 작업을 해야 한다. 그 역할을 위 코드의 경우 startRowendRow가 한다. 두 변수 모두 연산식이 currentPage라는 변하는 값 하나와 pageSize라는 변하지 않는 값 하나로 구성돼 있다.

 

pageSize가 10인 경우엔 currentPage에 어떤 값이 들어가도 startRow와 endRow의 차이는 9가 된다. 예를 들어, 화면에 1번 글부터 10번 글까지 있다고 가정하면 현재 페이지(currentPage)는 1이고 startRow는 1, endRow는 10이 된다. 같은 원리로 pageSize가 20이면 두 값의 차는 currentPage에 관계없이 19가 된다.

 

여기서 중요한 건 startRow와 endRow는 '눈에 보이는' 글번호가 아니라 가상 번호라는 것이다. 글번호란 게시글마다 붙는 고유 번호(primary key)를 말한다. 만약 글번호를 기준으로 1번 글부터 10번 글까지 [1] 페이지, 11번 글부터 20번 글까지 [2] 페이지... 식으로 구현하면 어떨까. 중간에 게시글이 삭제되면 대처가 안된다. 반면 늘 일정한 단위로 구분되는 가상 번호를 이용하면 게시글의 변화와 관계없이 로직을 구현할 수 있다.

 

여기까지 이해했으면 절반 이상 이해한 거다. 다음은 SQL문에서 startRow와 endRow가 어떻게 활용되는지 보면 된다. 아래는 Dao 클래스에서 게시글을 셀렉트하는 메서드의 코드 중 일부다. 파라미터로 startRow와 endRow를 받는다.

public List<BoardDTO> getArticles(int startRow, int endRow) throws Exception {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        List<BoardDTO> articleList=null;

        try {
            conn = getConnection();

            pstmt = conn.prepareStatement(
            "select num,writer,email,subject,passwd,reg_date,ref,re_step,re_level,content,ip,readcount,r  " +
"from (select num,writer,email,subject,passwd,reg_date,ref,re_step,re_level,content,ip,readcount,rownum r " +
"from (select * " +
"from board order by ref desc, re_step asc) order by ref desc, re_step asc ) where r >= ? and r <= ? ");

            pstmt.setInt(1, startRow);
            pstmt.setInt(2, endRow);
            rs = pstmt.executeQuery();

            (중략)
        }

SQL 문에 있는 각종 다른 속성은 그냥 무시해도된다. 선언된 SQL문에서 rownum을 별칭 r로 사용하는 게 확인된다. rownum은 오라클 내부적으로 생성되는 가상 컬럼이다. 주로 자료의 일부를 잘라내서 확인하는 용도로 활용된다. 게시판 페이징에 딱 필요한 녀석이다. 마지막에 where r >= ? and r <= ? 부분을 보자. ? 자리에 각각 전달받은 startRow와 endRow을 넣음으로써 값을 10개씩 잘라서 셀렉트 해주는 SQL 문이 완성됐다. 이렇게 원하는 게시글 수만큼 페이징이 처리된다.


관련 포스팅: [오라클/ORACLE] 데이터 잘라서 보는 ROWNUM

반응형

댓글

Designed by JB FACTORY