본문 바로가기

스파르타코딩 내일배움캠프

내일배움캠프 99일차 - 페이징 처리 디버깅

페이징 처리

 

프론트에서 GET 요청을 했더니 서버에서 다음과 같은 에러가 났다. 

 

java.lang.NullPointerException: null
	at shop.heartmuscle.heartmuscle.controller.QnaController.getQna(QnaController.java:36) ~[main/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.13.jar:5.3.13]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.13.jar:5.3.13]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.13.jar:5.3.13]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.13.jar:5.3.13]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.13.jar:5.3.13]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.13.jar:5.3.13]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.13.jar:5.3.13]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.13.jar:5.3.13]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.13.jar:5.3.13]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.13.jar:5.3.13]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.55.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.13.jar:5.3.13]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.55.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.55.jar:9.0.55]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.55.jar:9.0.55]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.55.jar:9.0.55]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.55.jar:9.0.55]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.55.jar:9.0.55]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113) ~[spring-web-5.3.13.jar:5.3.13]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.55.jar:9.0.55]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.55.jar:9.0.55]

QnaController에서 null값이 나왔다. 

 

디버깅을 했다. 

userDetails에서 null 값이 나왔다. 

수업에서 가져온 코드다. 생각해보니 수업에서는 각 사용자마다 조회하는 "상품" 목록이 다르기 때문에 각 사용자 별로 조회를 해야 해서 유저 값이 필요하다. 게다가 사용자가 "관리자"인지 아닌지도 확인한다. 

 

그러나 내가 구현하는 게시판에서는 조회는 누구나 할 수 있고, 작성/수정/삭제만 회원가입이 되어 있어야 한다. 그렇기 때문에 user정보가 필요없었다. 

 

userDetails를 삭제한다. 프론트에서 호출 다시 해본다. 

이제 불러온다. 

 

 

 

문제는 페이지 2를 누르면 페이지 2만 나오는게 아니라, 페이지 1 목록에 페이지 2목록이 추가 되어서 나온다. 그리고 다시 페이지 1을 누르면 또 페이지 2에 페이지 1이 추가 되어서 나온다. 

 

https://pagination.js.org/docs/index.html

 

Pagination.js | Docs

Constructor Commonly used dataSource array | string | object | function Specify the data source of the pagination. dataSource supports 4 formats. Array Directly provide an array, such as: ['1', '2', '3', '4'] Object Provide an object contained an array, th

pagination.js.org

 

pagination library documentation을 보면서 뭐가 잘 못 되었는지 본다. 

 

각 설정이 뭐하는지 대충 파악 해도 페이지 1을 누르면 1만, 2를 누르면 2 내용만 나오는 설명을 없다. 

 

유튜브에서 스프링 부트 페이징 설명도 듣는다. 타임리프, JSP를 쓰다보니 감이 안 잡힌다. 기존 코드 말고 다른 코드로 새로 작성할까 고민한다. 기존 코드 구현이 거의 다 온 것 같아서 조금만 더 시도 해보기로 한다. 

 

튜터님께 도움을 요청한다. "수업 코드" 테스트 해봤냐고 질문하신다. 수업 코드가 에러가 났고, 이미 코드 자체는 다 가져왔기 때문에 따로 더 보려고 하지 않았다. 

 

$('#product-container').empty();

튜터님께서 '이게 빠져서 그렇다'는 답변을 해주셨다.

 

저 코드가 search-result-box랑 같이 있어서, 내 코드랑은 관련 없는 코드이겠지 간주하며 확인도 하지 않고 지웠다. 

$('#product-container').empty();
$('#search-result-box').empty();

추가 해줘도 구현 되지 않았다 .

 

이번엔 "수업 코드"와 내 코드가 뭐가 다를까 하며 유심히 살펴보았다. 

 

let tempHtml = ` <tr>
          <th scope="row">${qnaList['id']}</th>
          <td>${qnaList['createdAt']}</td>
          <td>${qnaList['user']['username']}</td>
          <td><a href="qna-detail.html?id=${qnaList['id']}">${qnaList['title']}</td>

          </tr>
        `;
$("#post_table").append(tempHtml);

바로 위에 것이 내 코드. 

 

return ` <tr>
          <th scope="row">${qnaList['id']}</th>
          <td>${qnaList['createdAt']}</td>
          <td>${qnaList['user']['username']}</td>
          <td><a href="qna-detail.html?id=${qnaList['id']}">${qnaList['title']}</td>

          </tr>
        `;

그리고 이게 "수업"에서 작성한 코드 형태다. template literal도 함수 안에서 return 할 수 있는지 몰랐다. 

 

let tempHtml방식으로도 구현할 수 있지만, 더 좋은 코드를 익히기 위해 가능한 수업 코드 방식으로 구현 해보고 싶었다. 

 

 

 

수정하니 이제 작동 된다.

 

callback: function(data, pagination) {
    $('#post_table').empty();
    for (let i = 0; i < data.length; i++) {
        let list = data[i];
        let tempHtml = makeQnaList(list);
        $('#post_table').append(tempHtml);
    }

 

$('#post_table').empty();

위에 코드가 필요한 건 알겠다. 기존에 데이터를 먼저 지우고 새로운 데이터를 불러온다는 것을. 

그런데 왜 callback 함수 밑에 있어야 하는지 모르겠다. callback함수를 찾아봐도 아직 개념 확 닿지 않는다. 

callback 함수는 좀 더 찾아봐야겠다. 

 

구현 되고 나니 쾌감이 느껴졌다. 그것도 오래갔다. 술에 취한 것과 다른 취한 기분이었다.