1️⃣ 일정보관함 페이징 처리
페이징 처리 위해 필요한 것들
- 정렬
- page당 레코드 몇 개를 보여줄지
- 전체 레코드 갯수
- 현재 페이지 번호
- 정해진 레코드 갯수의 글만 보여지는 리스트
⇒ 2~5번의 4개의 data를 뭉쳐서 관리해야한다
⇒ PageDTO.java
✔ PageDTO2.java
4가지 정보를 작성하고, getter/setter를 생성한다.
- 목록 List<TravelListDTO> list;
- 페이지 당 보여줄 행의 갯수 int perPage = 8;
- 전체 레코드 갯수 int totalCount;
- 현재 페이지 번호 int curPage;
✔ TravelMapper.xml
정렬 ⇒ order by contentNum DESC
✔ TravelListDAO.java
- List<TravelListDTO> list = session.selectList("TravelMapper.travel", null, new RowBounds(offset, limit));
=> MyBatis의 selectList 메서드를 사용하여 "TravelMapper.travel"라는 네임스페이스의 travel 쿼리를 실행
RowBounds 객체를 사용하여 페이징(offset, limit)을 적용
- PageDTO2 pageDTO2 = new PageDTO2();
=> PageDTO2 객체를 생성 - int offset = (curPage-1) * pageDTO2.getPerPage();
=> 현재 페이지(curPage)에 따른 오프셋(offset)을 계산 - int limit = pageDTO2.getPerPage();
=> 한 페이지당 보여질 항목의 개수(limit)를 가져옴
- offset : 결과 집합에서 가져올 데이터의 시작 위치를 지정한다.
- limit : 가져올 데이터의 개수를 지정한다.
예를 들어, 페이지당 10개의 항목을 보여주고, 현재 사용자가 3페이지를 요청했다면, offset은 20이 되고, limit은 10이 된다. 따라서 데이터베이스는 21번째부터 30번째까지의 결과를 반환하게 된다.
offset=(현재 페이지 번호−1)×페이지당 항목 수
- pageDTO2.setCurPage(curPage);
=> PageDTO2 객체에 현재 페이지(curPage) 값을 설정
사용자가 요청한 페이지 번호를 PageDTO2 객체에 설정하여, 이 정보를 통해 특정 페이지의 데이터를 가져올 수 있도록 한다. - int totalCount = session.selectOne("TravelMapper.totalCount");
=> "TravelMapper.totalCount"라는 네임스페이스의 totalCount 쿼리를 실행
전체 데이터의 개수를 조회 - pageDTO2.setTotalCount(totalCount);
=> 조회된 전체 데이터 개수를 PageDTO2 객체에 설정
이 정보는 페이징 처리에서 전체 페이지 수를 계산하는 데 사용된다.
✔ TravelMapper.xml
일정 갯수 세는 쿼리문 추가
✔ TravelListService.java
✔ TravelListServiceImpl.java
✔ TravelListController.java
🧨 500 오류 발생
원인)
페이징 처리 로직을 사용자에 따라 다르게 하려면 사용자의 ID가 필요한데 페이징 처리 로직들에 userID를 작성안함.
mapper 쿼리에는 where userID=#{userID} 를 작성해놓고선 다른 로직들에는 userID 값을 넣지않아서 발생한 문제였다.
즉, userID 값을 사용하여 사용자별로 필요한 데이터를 검색하고 페이징하는 작업을 수행해야 하는데 쿼리가 userID값을 받지 못하게 된 것이다.
해결)
userID를 추가해야 쿼리의 파라미터로 전달되어 해당 사용자의 여행 목록을 조회하게 된다.
500 에러는 해결되었는데 perPage가 적용이 안되고 있다 🙄
🧨 페이징 처리가 안되고 모든 데이터가 다 출력되는 이슈 발생
500 에러는 해결이 되었는데 지정한대로 페이징 처리가 안되고 모든 데이터들이 한 페이지에 다 나오는 이슈가 발생했다.
처음에는 한 페이지 당 몇개의 데이터들을 나오게 할건지 작성한 perPage 로직에 원인이 있는 줄 알고 삽질을 엄청 했다.
삽질을 해도 해결이 안되어서 테스트 코드로 콘솔을 확인해보기로 한다.
DAO 클래스에서 offset과 limit 그리고 for문으로 dto를 확인해본 테스트 코드의 모습이다.
콘솔은 내가 의도한대로 잘 나오는 것을 볼 수 있었다.
Controller와 jsp를 확인해보자
원인1)
나는 사용자 ID를 전달해서 여행 리스트를 가져오고, 또 사용자 ID를 전달해서 거기서 페이징된 데이터를 가져와야 한다고 잘못 생각하고 있었던 것 이다.
결과적으로 pageDTO2가 있음에도 불구하고 travelList와 관련된 서비스를 호출하고 있었다.
서비스를 두번 호출하게 되니 문제가 된 것!
해결)
pageDTO2에 이미 travelList가 담겨있으므로 두 번 호출된 부분을 삭제해준다.
원인2)
jsp에서 데이터를 출력해오는 부분이 pageDTO2가 아닌 travelList로 되어있었다.
<c:forEach var="travel" items="${travelList}" varStatus="status">
해결)
items="${travelList}" 를 items="${pageDTO2.list}" 으로 바꿔준다.
pageDTO2에 있는 List<TravelListDTO> 이다.
<c:forEach var="travel" items="${pageDTO2.list}" varStatus="status">
8개씩 페이징 처리 적용된 모습)
2️⃣ 화면에 보여지는 총 페이지 수
1페이지부터 10페이지까지 다 보이는게 아니고 글 갯수에 맞춰 페이징된대로 페이지 수도 보여지게끔 했다.
pageDTO2.totalCount는 전체 항목의 개수이고
pageDTO2.perPage는 한 페이지당 보여질 항목의 개수이다.
- 전체 페이지 수 계산 <c:set var="totalPages" value="${pageDTO2.totalCount / pageDTO2.perPage+1}" />
전체 페이지 수는 전체 항목 수를 한 페이지당 보여질 항목 수로 나눈 값에 1을 더한 것이다.
여기서 +1은 나누어 떨어지지 않을 때 남은 항목이 있을 경우 페이지를 하나 더 추가하기 위함이다. - 페이지 번호 순회 <c:forEach var="i" begin="1" end="${totalPages}" >
JSTL의 <c:forEach>를 사용하여 1부터 totalPages까지의 숫자를 변수 i에 할당하며 순회한다.
전체 페이지 수에 따라 페이지 번호를 생성하기 위한 것이다.
결과)
수업시간 때 배운 대로 최대한 활용해봤는데 현재 사용한 로직보다는
DAO는 최대한 간결하게 하고, Controller에서 모든 로직을 구현하는 고민이 필요하다고 생각된다.
'Project 여담 > 5주차' 카테고리의 다른 글
11/04 : 3번째 멘토링 / 중간점검 (0) | 2023.11.05 |
---|---|
11/03 : 일정 삭제하기 DataIntegrityViolationException 오류 => ON CASCADE 추가 (0) | 2023.11.03 |
11/02 : 일정 상세보기 지도에 인포윈도우 추가 (0) | 2023.11.02 |
11/01 : 일정 상세보기 kakao map api와 DB 연동해 마커 찍기 (0) | 2023.11.01 |
10/31 : 일정 상세보기 로직 구현 (0) | 2023.10.31 |