본문 바로가기
Side Project/spring 기반으로 웹 게시판 개발하기

Spring 공지사항 게시판 만들기 - (3) 공지사항 목록 (List)

by 잇서니 2021. 1. 12.
반응형

 

혼자 이해한 내용이니 혹시 잘못된 부분이 있을시 댓글 남겨주시면 감사하겠습니다 :)

 


 

공지사항 목록 기능의 핵심은 페이징처리인 것 같습니다. 목록 정보를 가져와 보여주는 것은 공지사항 보기 기능과 비슷한 로직입니다. (공지사항 등록,공지사항 보기기능은 이전 글을 참고해주세요.) 그래서 페이징 처리 위주로 포스팅을 하겠습니다.

페이징 처리를 하는 객체를 따로 만들고, Controller에서 해당 객체를 생성하고 호출하는 형태입니다. 이 외에 service, DAO, mapper 등의 흐름은 공지사항 등록, 보기와 동일합니다.

 

  • pageSize 한 페이지에 5개씩 데이터를 리스팅할 것입니다.
  • pageBlock 페이지 블록 사이즈는 5개로 하였습니다. 페이지가 5개씩 나뉜다고 보면 됩니다. <1,2,3,4,5> <6,7,8,9,10> ...

 

Controller 코드 (src/main/java/net/admins/controller/BoardNoticeAdminsController.java)

@Controller
public class BoardNoticeAdminsController {

    @Resource(name = "boardNoticeAdminsService")
    private BoardNoticeAdminsService BoardNoticeAdminsService;

    @RequestMapping(value = "/admins/promoter/boardmgr/PmtNoticeList.mwav")
    public ModelAndView selectListPmtNtmList(CommandMap commandMap,
            HttpServletRequest request) throws Exception {

        // mv 생성        
        ModelAndView mv = new ModelAndView("/Admins/Promoter/BoardMgr/PmtNoticeList");


        // 페이징 작업
        String pageNum = (String) commandMap.get("pageNum");
        if (pageNum == null || pageNum == "") {
            pageNum = "1";
        }

        int totalRow = BoardNoticeAdminsService.selectOneGetPmtNtmTotalCount();

        Paging paging = new Paging();
        PagingVO pagingVO = paging.setPagingInfo(totalRow, 5, pageNum); // 총 숫자, 한페이지에 노출 수, 현재 페이지

        commandMap.put("startRow", paging.getStartRow(pageNum)); // 시작 열
        commandMap.put("endRow", paging.getEndRow(pageNum)); // 끝 열


        // 공지사항 목록 select하는 service 호출
        List<Map<String, Object>> selectListPmtNtmList;

        if (totalRow > 0) {
            selectListPmtNtmList = BoardNoticeAdminsService.selectListPmtNtmList(commandMap.getMap());
        } else {
            selectListPmtNtmList = Collections.emptyList();
        }


        // mv에 데이터 추가
        String mm = "site";
        mv.addObject("mm", mm);

        mv.addObject("selectListPmtNtmList", selectListPmtNtmList);
        mv.addObject("pagingVO", pagingVO);
        mv.addObject("totalRow", totalRow);


        // view에 결과 넘겨주기
        return mv;
    }

}
  • pageNum
    • 사용자가 선택한 페이지 번호입니다. commandMap을 사용하여 사용자가 넘겨준 페이지 번호를 받을 수 있습니다.
    • 만약 아무 페이지도 선택하지 않았다면 default를 1페이지로 설정합니다.
  • Paging 객체
    • Paging 객체를 만들고 setPagingInfo(), getStartRow() 등의 함수를 호출합니다.
    • Paging 코드는 아래에서 설명해보겠습니다.

 

 

페이징 코드 (src/main/java/net/mwav/common/module/Paging.java)

package net.mwav.common.module;

public class Paging {

    PagingVO paging = new PagingVO();

    int pageSize; // 한 페이지에 노출되는 글의 개수
    int pageBlock; // 하나의 블록에 몇 페이지가 속해있는지
                    // 즉 5이면 <<1,2,3,4,5>> 페이지가 한블록 <<6,7,8,9,10>> 페이지가 한 블록    
    int currentPage; // 현재 페이지
    int totalRow; // 전체 글의 갯수    

    int startRow; // 한 페이지의 시작글 번호 = 쿼리에서 ROWNUM (시작)
                  // ex) pageSize가 5인경우, 1페이지-> 1 2페이지 -> 6 ...
    int endRow; // 한 페이지의 마지막 글번호 = 쿼리에서 ROWNUM (끝)
                // ex) pageSize가 5인경우, 1페이지-> 5 2페이지 -> 10 ...


    int pageCount; // 전체 페이지수

    int remainRow; // 남은 행이 있는지 검사
                    // 전체 행(totalRow) % 페이지 크기(pageSize) 0이면 글의 개수가 딱 맞는 것이고, 1이면 글의 개수 적거나 많은 것

    int startPage; // 현재 페이지가 속한 페이지블록의 시작 페이지
                    // 3페이지는 1번째 페이지 블록임 <<1,2,3,4,5>>. 이 페이지블록의 시작 페이지는 1이다.
                    // 8페이지는 2번째 페이지 블록임 <<6,7,8,9,10>>. 이 페이지블록의 시작 페이지는 6이다.
    int endPage; // 현재 페이지블록의 마지막 페이지


    public PagingVO setPagingInfo(int totalRow, int pageSize, String pageNum) {
        this.totalRow = totalRow;
        this.pageSize = pageSize; // 한 페이지에 5개의 게시글 노출
        this.currentPage = Integer.parseInt(pageNum);
        initialize();

        return paging;
    }

    public void initialize() {

        if (totalRow % pageSize == 0) {
            remainRow = 0;
        } else {
            remainRow = 1;
        }

        pageCount = totalRow / pageSize + remainRow;
        pageBlock = 5; // <<1,2,3,4,5>>

        startPage = ((currentPage - 1) / pageBlock) * pageBlock + 1;
        endPage = startPage + pageBlock - 1;

        startRow = (currentPage - 1) * pageSize + 1;
        endRow = currentPage * pageSize;

        // 남는 페이지에 대한 처리를 위해서 사용
        // 만약에 내가 페이지 블록으로 1~5까지 설정했을 때, 3,4,5에 내용이 없어도 페이지는 생성하게 된다.
        // endPage = pageCount로 잡아주어 해당 페이지까지만 생성해준다.
        if (endPage > pageCount) {
            endPage = pageCount;
        }

        paging.setStartPage(startPage);
        paging.setEndPage(endPage);
        paging.setPageBlock(pageBlock);
        paging.setPageCount(pageCount);
        paging.setEndRow(endRow);
        paging.setStartRow(startRow);
    }

    public int getStartRow(String pageNum) { // 현재 페이지에서 첫 열 계산
        startRow = (currentPage - 1) * pageSize + 1;
        return startRow;

    }

    public int getEndRow(String pageNum) { // 현재 페이지에 마지막 열 계산
        endRow = currentPage * pageSize;
        return endRow;

    }

    public String getPageNum(String imsi_pageNum) {
        String pageNum = imsi_pageNum;
        if (imsi_pageNum == null || imsi_pageNum == "") {
            pageNum = "1";
        }
        return pageNum;
    }
}

 

아래 4개의 값들은 직접 설정하거나 쿼리 count 결과입니다. 계산이 필요없는 값들입니다.

  • pageSize : 한 페이지에 몇 개의 글을 보여줄 것인가
  • pageBlock : 몇 개의 페이지가 한 묶음인가
  • currentPage : 사용자가 선택한 페이지 번호. (default = 1)
  • totalRow : 전체 글의 개수 (count(*) 쿼리 수행한 결과)

 

이제 페이징 처리를 위해 계산이 필요한 값들에 대해 알아보겠습니다.

  • StrartPage
    • 페이지블록값(pageBlock)을 5개로 설정한 상태입니다. StartPage는 각 페이지블록의 첫번째 페이지번호입니다.
    • 예를 들어 첫번째 페이지 블록<<1,2,3,4,5>>의 StartPage는 1이고, 두번째 페이지 블록<<6,7,8,9,10>>의 StartPage는 6입니다.
    • 즉, 이런 규칙이 나옵니다. 첫번째 블록의 StrartPage는 (5x0) + 1, 두번째 페이지 블록의 StratPage는 (5x1)+1 ...
    • 식으로 표현하면 ((currentPage - 1) / pageBlock) \* pageBlock + 1 입니다. 현재 페이지를 페이지블록값(pageBlock)으로 나눈 몫 x 페이지블록값(pageBlock) + 1 입니다.
  • EndPage
    • 각 페이지블록의 마지막 페이지번호입니다.
    • 예를 들어 첫번째 페이지 블록<<1,2,3,4,5>>의 EndPage는 5이고, 두번째 페이지 블록<<6,7,8,9,10>>의 EndPage는 10입니다.
    • 그러나 총 페이지 수가 7인데 EndPage가 10으로 잡혀있으면 빈 페이지(8,9,10)가 만들어지게 됩니다. 그래서 EndPage > PageCount 인 경우, EndPage값을 PageCount값으로 설정하여 빈 페이지가 만들어지지 않도록 합니다.
  • StartRow
    • 각 페이지의 시작 글 번호입니다.
    • 각 페이지에는 5개의 글이 노출됩니다. 그러면 첫번째 페이지의 StartRow는 1, 두번째 페이지의 StartRow는 6이 됩니다.
    • 식으로 표현하면 (currentPage - 1) \* pageSize + 1 입니다.
  • EndRow
    • 각 페이지의 마지막 글 번호입니다.
    • 식으로 표현하면 currentPage * pageSize 입니다.

 

 

Service 코드 (src/main/java/net/admins/controller/BoardNoticeAdminsServiceImpl.java)

@Service("boardNoticeAdminsService")
public class BoardNoticeAdminsServiceImpl implements BoardNoticeAdminsService {

    @Resource(name = "boardNoticeAdminsDAO")
    @Autowired(required = true)
    private BoardNoticeAdminsDAO boardNoticeAdminsDAO;

    @Override
    public List<Map<String, Object>> selectListPmtNtmList(Map<String, Object> map) {
        // TODO Auto-generated method stub

        return boardNoticeAdminsDAO.selectListPmtNtmList(map);
    }

}

공지사항 등록, 보기와 마찬가지로 Controller에서 Service를 호출합니다. Service는 DAO를 호출합니다. DAO의 selectListPmtNtmList를 호출합니다.

 

 

DAO 코드 (src/main/java/net/admins/dao/BoardNoticeAdminsDAO.java)

@Repository("boardNoticeAdminsDAO")
public class BoardNoticeAdminsDAO extends AbstractDAO {

    @SuppressWarnings("unchecked")
    public List<Map<String, Object>> selectListPmtNtmList(Map<String, Object> map) {
        // TODO Auto-generated method stub
        return (List<Map<String, Object>>) selectList(
                "boardNoticeAdminsDAO.selectListPmtNtmList", map);

    }

}

DAO는 Mybatis의 selectList 함수를 호출합니다.

 

 

mapper (src/main/resources/mapper/board/admins/BoardNoticeAdmins_SQL.xml)

<select id="selectListPmtNtmList" parameterType="hashmap" resultType="hashmap">
<![CDATA[
select c.* from (select @ROWNUM := @ROWNUM + 1 AS ROWNUM, a.* from (select * from BoardPromoter_tbl where bpDeleteDt IS NULL order by bpInsertDt desc) a,  (SELECT @ROWNUM := 0) R ) c where c.ROWNUM >= #{startRow} and c.ROWNUM <= #{endRow}
]]>
</select>    

쿼리에서 ROWNUM을 사용하여 각 행에 번호를 매깁니다. 페이징 처리에서 몇번째 글부터 몇번째 글까지 보여줘야 하기 때문에 ROWNUM을 활용합니다.

 

 

 

반응형

댓글