-
[Spring] 페이징처리를 위해 써먹는 Paging 객체 만들기 및 활용웹 개발/Spring Framework 2019. 5. 18. 18:12
회사 내에서 페이징 객체를 만들어야겠다고 생각한 계기는 특정 고객사에서 특정 메뉴를 주로 사용하는데 이 메뉴가 페이징 처리가 안되어있어 너무 느리다는 불만사항을 자주 들었다. 그 이외 UI 라이브러리 문제도 있었어서(고객사는 이 문제에 대한 불만이 더 많았다.) 새로 회사에서 사용하는 라이브러리로 바꿀 겸 이 메뉴에 대한 페이징 처리를 하기로 마음 먹었다.
기존에는 페이징 처리를 메서드마다 페이지 인덱스와 페이지 사이즈를 계산하고 Map에 담아 return 방식으로 페이징 처리를 하고 있었는데, 이 부분 때문에..
페이징 객체를 만들자!!!
먼저 내가 구성한 건, 페이징 처리를 위한 변수 정하기. 내가 생각한 리스트는 아래와 같다.
- pageIndex : 현재 이 페이지가 몇번째 페이지냐
- pageSize : 페이지 사이즈가 얼마나 되냐? 10개를 보여줄거냐 50개를 보여줄거냐
- startRow : 그럼 DB는 몇번째 데이터부터 찾으면 되냐
- endRow : 그럼 DB는 몇번째 데이터까지 찾으면 되냐
- resultList : DB에서 가져온 리스트 결과를 담아줄 변수
- totalCount : 페이징 인덱스를 매기기 위해 실제 데이터는 몇개가 되냐
코드로 표현해보면?
public class Paging { private int pageIndex; private int startRow; private int endRow; private int pageSize; private List<?> resultList; private int totalCount; public int getPageIndex() { return pageIndex; } public int getStartRow() { return startRow; } public int getEndRow() { return endRow; } public int getPageSize() { return pageSize; } public List<?> getResultList() { return resultList; } public int getTotalCount() { return totalCount; } }
- ResultList는 어떤 형의 데이터든지 받을 수 있도록 와일드카드(List<?>) 방식을 사용했다.
- 의미없는 setter는 안 만들고 값을 꺼내쓰기 위한 getter만 구현
- 내 생각에 MySQL, Maria 사용자는 변수 endRow는 필요없을 것 같다. 쿼리에서 limit를 사용해 데이터를 가져올 때 페이지 사이즈로 마지막 row를 찾으니까 말이다. 난 oracle도 사용하기 때문에 그에 대비하여 만들었다.
이렇게 기본적인 골격을 짰고, 이제 페이지 인덱스와 페이지 사이즈를 활용하여 startRow와 endRow를 계산할 메서드를 만들어야 한다.
public void handlePaging(int pageIndex, int pageSize) { this.pageIndex = pageIndex < 1 ? 1 : pageIndex; this.pageSize = pageSize; this.startRow = ((pageIndex-1) * pageSize); this.endRow = startRow + pageSize; }
- 페이지 인덱스에 0 이하로 들어올 일은 없겠지만, 혹시나 하는 마음에 1 미만의 숫자는 강제로 1부터 시작하도록 만들었다.
- startRow는 페이지 인덱스 1이 들어오면(1페이지), -1을 통해 0, 2 페이지면서 페이지 사이즈가 10이라면 index가 10부터 시작할 수 있도록 했다.
- endRow는 단순하게 startRow에서 페이지 사이즈만큼만 더해주었다.
처리된 데이터들을 Paging객체에 담아줄 수 있는 메서드는.
public void handlePagingList(List<?> resultList, int totalCount) { this.resultList = resultList; this.totalCount = totalCount; }
- DB의 리스트 결과값은 resultList에 담기고, 총 데이터 갯수는 totalCount에 담긴다.
완성된 페이징 객체를 보면 아래처럼 구성된다.
public class Paging { private int pageIndex; private int startRow; private int endRow; private int pageSize; private List<?> resultList; private int totalCount; // startRow, endRow를 계산한다. public void handlePaging(int pageIndex, int pageSize) { this.pageIndex = pageIndex < 1 ? 1 : pageIndex; this.pageSize = pageSize; this.startRow = ((pageIndex-1) * pageSize); this.endRow = startRow + pageSize; } // 페이징 처리된 결과값을 담는 메서드 public void handlePagingList(List<?> resultList, int totalCount) { this.resultList = resultList; this.totalCount = totalCount; } public int getPageIndex() { return pageIndex; } public int getStartRow() { return startRow; } public int getEndRow() { return endRow; } public int getPageSize() { return pageSize; } public List<?> getResultList() { return resultList; } public int getTotalCount() { return totalCount; } }
활용편
Service layer
@Service public class ZorbaServiceImpl { private final ZorbaDao zorbaDao; public ZorbaServiceImpl(ZorbaDao zorbaDao) { this.zorbaDao = zorbaDao; } public Paging findZorbaUsers(UserDto userDto) { Paging paging = new Paging(); paging.handlePaging(userDto.getPageIndex(), userDto.getPageSize()); // startRow, endRow, pageSize가 계산된 페이징 객체값을 파라미터 변수에 set. userDto.setPaging(paging); return zorbaDao.findZorbaUsers(userDto); } }
- handlePaging 메서드를 통해 startRow, endRow, pageSize를 계산해서 페이징 객체에 set해둔다.
- 처리가 된 페이징 객체(Paging)을 DAO 메서드에 보내기 위한 파라미터인 UserDto에 담아준다.
- 내부적으로 startRow, endRow, pageSize를 set한다.
Repository layer
@Repository public class ZorbaDao { public Paging getSearchAttReqMainMgrList(UserDto userDto) { Paging paging = new Paging(); // findList라는 list 쿼리를 조회하는 메서드, findOne이라는 하나의 데이터만 가져오는 메서드가 있다고 가정 return paging.handlePagingList(findList("findZorbaUsers",userDto) ,findOne("findZorbaUsers_totalcount", userDto)); }
- 쿼리의 리스트 결과 값을 곧바로 페이징 객체의 resultList에 담고, totalCount 결과 값을 페이징 객체의 totalCount에 담는다.
정리
전체 데이터를 가져와서 리스트에 뿌려주는 것보다 페이징 처리된 메뉴가 빠르다는 걸 몸소 느꼈고, 앞으로 리스트를 보여줘야할 메뉴는 사용자를 위해 페이징 처리가 필수일 것 같다.
'웹 개발 > Spring Framework' 카테고리의 다른 글
[Spring] 팩토리 메소드 패턴을 적용하여 bean을 동적으로 사용하기 (5) 2020.04.19 [Spring] Lombok을 이용해 Builder 패턴을 만들어보자. (1) 2020.03.21 [Spring] war에 test class가 포함된다?(war에서 test class 빼는 법) (0) 2019.05.08 [Spring Boot, Gradle] gradle dependency 전체 삭제하는 법(gradle build 에러 해결 방법) (0) 2019.03.08 [Spring, jQuery] Controller에서 객체(Object)로 파라미터 받기 (0) 2019.02.24