AXIOS를 활용해 페이징 처리하기

KEH·2021년 3월 1일
1
post-thumbnail

오늘은 axios를 활용하여 페이징처리를 진행할 것이다.
결과물은 아래와 같다!

  • 한 페이지 당 총 6개의 데이터를 보여준다.
  • 페이지 버튼은 5개씩 보여준다.

1. BackEnd(Spring)

@RequestMapping("/productList/{categoryCode}")
public String productByCategory(@PathVariable("categoryCode") int categoryCode, Model model, 
	@CookieValue(value="productCnt", required=false) Cookie cookieCnt, HttpServletResponse response) {
	      
	//상품 총 갯수 쿠키에 저장
	String cnt = Integer.toString(pm.getCount(categoryCode));
	if (cookieCnt==null) {
		cookieCnt = new Cookie("productCnt", cnt);
	} else if (!cookieCnt.getValue().equals(cnt)) {
		cookieCnt.setValue(cnt);
	}
	response.addCookie(cookieCnt);
        
  	return "/ProductList";
}

우선 상품리스트 페이지로 이동하게 되면 해당 카테고리의 상품들의 총 갯수를 카운트하고, 이를 쿠키에 저장했다.
(쿠키에 대해서 더 많은 설정을 해 줘야 하지만, 우선 여기서는 간단히 저장만 하도록 하겠다.)


2-1. FrontEnd : 첫 로딩시

var categoryCode = Number($(location).attr('pathname').slice(-1));
var totalPage = Math.ceil($.cookie("productCnt")/6);
var buttonHtml = "";

$(window).ready(function() {
	var data = {"page":1, "categoryCode":categoryCode};
	
	if (totalPage>5) {
		for (var page=1; page<=5; page++) {
			buttonHtml += "<button type=\"button\" class=\"btn btn-light pageButton\" index=\"" + page + "\">" + page + "</button>";
		}
		buttonHtml += "<button id=\"nextButton\" type=\"button\" class=\"btn btn-light\">다음</button>";
	} else {
		for (var page=1; page<=totalPage; page++) {
			buttonHtml += "<button type=\"button\" class=\"btn btn-light pageButton\" index=\"" + page + "\">" + page + "</button>";
		}
	}
  
	$("#pageButtonGroup").html(buttonHtml);
	$(".pageButton").first().css({background:"black", color:"white"});
	
	pagingProduct(data);
});
  1. 해당 페이지에서 계속 사용되는 변수들인 categoryCode, totalPage, buttonHtml을 전역변수로 선언한다.
  • categoryCode : 현재 상품 페이지의 카테고리 코드.
  • totalPage : cookie에 저장한 전체 상품 갯수를 이용해 총 페이지를 계산한다.
  • buttonHtml : 페이지 버튼과 관련된 html 코드.
  1. 처음 페이지가 로딩되면 1페이지의 상품을 보여줄 것이다. 따라서 axios를 활용해 서버에 요청 시 함께 전달할 데이터를 담고 있는 data 변수에 현재 페이지(page=1)와 카테고리 코드를 저장한다.
  2. 전체 페이지가 5보다 크면 다음페이지 버튼을 추가하고, 그렇지 않으면 전체페이지 만큼만 페이지 버튼을 생성하는 html 코드를 작성한다.
  3. 버튼 생성 html 코드를 브라우저에 추가하고, 클릭된 버튼(현재는 1페이지 버튼)의 색을 바꾼다.
  4. pagingProduct(data) 함수를 호출한다.

2-2. FrontEnd : 페이지 버튼 클릭시

$(document).on("click", ".pageButton", function() {
	$(".pageButton").css({background:"#F8F9FA", color:"black"});
	$(this).css({background:"black", color:"white"});
	
	var page = Number($(this).text());
	var data = {"page":page, "categoryCode":categoryCode};
	
	pagingProduct(data);
});
  1. 클릭한 페이지 버튼의 색과 글자 색을 변경한다.
  2. 서버로 전송할 페이지 버튼과 카테고리코드를 data 변수에 저장한다.
  3. pagingProduct(data) 함수를 호출한다.

2-3. FrontEnd : 다음 버튼 클릭시

$(document).on("click", "#nextButton", function() {
	var data = {"page":Number($(".pageButton").last().text())+1,
				"categoryCode":categoryCode};
				
	buttonHtml = "<button id=\"prevButton\" type=\"button\" class=\"btn btn-light\">이전</button>";
	if (totalPage>=data.page+5) {
		for (var page=data.page; page<data.page+5; page++) {
			buttonHtml += "<button type=\"button\" class=\"btn btn-light pageButton\" index=\"" + page + "\">" + page + "</button>";
		}
		buttonHtml += "<button id=\"nextButton\" type=\"button\" class=\"btn btn-light\">다음</button>";
	} else {
		for (var page=data.page; page<=totalPage; page++) {
			buttonHtml += "<button type=\"button\" class=\"btn btn-light pageButton\" index=\"" + page + "\">" + page + "</button>";
		}
	}
	$("#pageButtonGroup").html(buttonHtml);
	$(".pageButton").first().css({background:"black", color:"white"});
	
	pagingProduct(data);

});
  1. 1~5 페이지의 버튼이 있는 페이지에서 다음 버튼을 클릭하게 되면 6페이지로 넘어가야 한다. 이를 고려해 서버에 전송할 페이지와 카테고리 코드를 data 변수에 저장한다.
  2. 버튼 html 코드를 생성하고, 해당 브라우저에 추가한다.
  3. 해당 페이지의 버튼 색상과 글자 색을 변경한다.
  4. pagingProduct(data) 함수를 호출한다.

2-4. FrontEnd : 이전 버튼 클릭시

$(document).on("click", "#prevButton", function() {
	var data = {"page":Number($(".pageButton").first().text())-1,
				"categoryCode":categoryCode};
	buttonHtml = "";
  
	if (data.page-5!=0) {
		buttonHtml = "<button id=\"prevButton\" type=\"button\" class=\"btn btn-light\">이전</button>";
	}
	for (var page=data.page-4; page<=data.page; page++) {
		buttonHtml += "<button type=\"button\" class=\"btn btn-light pageButton\" index=\"" + page + "\">" + page + "</button>";
	}
	buttonHtml += "<button id=\"nextButton\" type=\"button\" class=\"btn btn-light\">다음</button>";
			
	$("#pageButtonGroup").html(buttonHtml);
	$(".pageButton").last().css({background:"black", color:"white"});
	
	pagingProduct(data);
});
  1. 6~10 페이지 버튼이 있는 페이지에서 이전 버튼을 클릭하게 되면 5페이지의 상품리스트로 넘어가야 한다. 이를 고려하여 서버에 전송할 페이지 버튼과 카테고리 코드를 data 변수에 저장한다.
  2. 이전 버튼을 클릭했을 때 1~5페이지 버튼이 존재하는 페이지인지, 그렇지 않은 페이지인지를 고려하여 버튼을 생성하는 html 코드를 작성한 후 브라우저에 추가한다.
  3. 클릭된 버튼(해당 페이지)의 버튼 색상과 글자 색상을 변경한다.
  4. pagingProduct(data) 함수를 호출한다.

3. pagingProduct(data) 함수

이 함수는 axios를 활용해 서버에 인자로 받은 데이터를 호출하는 함수이다.

function pagingProduct(data) {
	axios.post("/productList/paging", data).then(function(res) {
		var html = "";
		var imageSrc = "";
      
		for (var i=0; i<res.data.length; i++) {
          
		//서버에서 전달받은 데이터를 이용해 상품 리스트 관련 html 코드 작성
          
		$("#productRow").html(html);
	}).catch(function(error) {
		alert("오류가 발생했습니다!");
		if (error.response) {
	      	// 요청이 이루어졌으며 서버가 2xx의 범위를 벗어나는 상태 코드로 응답했습니다.
	      	console.log(error.response.data);
	      	console.log(error.response.status);
	      	console.log(error.response.headers);
	     } else if (error.request) {
	      	// 요청이 이루어 졌으나 응답을 받지 못했습니다.
	      	console.log(error.request);
	     } else {
	      	// 오류를 발생시킨 요청을 설정하는 중에 문제가 발생했습니다.
	      	console.log('Error', error.message);
	     }
	     console.log(error.config);
	});
}
  1. /productList/paging로 서버에 인자로 받은 데이터(data)를 axios를 활용하여 POST 전송한다.
  2. 서버에서 전달받은 데이터를 활용하여 상품 리스트 html을 작성하고, 브라우저에 추가한다.

4. BackEnd(Spring) - 클라이언트에서 POST 요청 후

@RequestMapping(value="/productList/paging", method=RequestMethod.POST)
@ResponseBody
public List<ProductVO> productPaging(@RequestBody HashMap<String, Object> reqHm) {
	//log.info(reqHm);
	PageDTO page = new PageDTO(Integer.parseInt(reqHm.get("page").toString()), 6);
	List<ProductVO> productVOList = pm.getListByCategory(page.getOffset(), Integer.parseInt(reqHm.get("categoryCode").toString()));
		
	return productVOList;
}

해당 코드는 클라이언트에서 axios를 활용하여 POST 전송을 요청했을 때 서버에서 이뤄지는 Controller 클래스이다. 클라이언트를 통해 전달받은 데이터(reqHm)를 활용하여 해당 페이지의 상품 리스트 정보를 클라이언트에게 다시 전달한다.
여기에서 PageDTO라는 객체가 등장하는데, 이 객체는 페이지와 관련된 정보를 담고 있는 DTO 객체이다.

  1. 전달받은 데이터(reqHm)의 페이지(page)와 cntPerPage=6으로 하여 pageDTO 객체를 생성한다.
  2. DB를 통해 해당 페이지의 상품 상세정보 리스트(productVOList)를 가져온다.
  3. 상품 상세정보 리스트(productVOList)를 클라이언트에게 전달한다.
@Data
public class PageDTO {
	private int page;
	private int cntPerPage;
	private int offset;
	
	public PageDTO() {};
	
	public PageDTO(int page, int cntPerPage) {
		this.page = page;
		this.cntPerPage = cntPerPage;
		if (this.page==1) {
			this.offset = 0;
		} else {
			this.offset = (page-1)*cntPerPage; 
		}
	}
}
  • page : 해당 페이지 번호.
  • cntPerPage : 한 페이지에서 보여줄 데이터의 개수.(여기서는 6)
  • offset : DB 조회 시 첫 시작 인덱스. (만약 2페이지의 상품 데이터를 검색할 경우 offset은 6이다.)

axios를 활용한 페이징 처리를 끝냈다..!
하지만 아직도 문제가 있다. 만약에 6페이지에 있는 상품리스트 중 하나를 클릭해 상세정보를 보고 뒤로 가게 되면 6페이지가 아닌 1페이지로 돌아간다. 또 새로고침을 해도 6페이지가 아니라 1페이지가 나온다... 이 문제를 어떻게 해결해야할지 아시는 분이 있다면 꼭 댓글 부탁드립니다...!!!

profile
개발을 즐기고 잘하고 싶은 안드로이드 개발자입니다 :P

0개의 댓글