BackEnd/Spring

SpringMVC_게시판_기능정리_국비

Leo.K 2022. 7. 15. 14:59

[ 조회수 증가 ]

생각보다 간단하게 구현할 수 있는 조회수 증가는 고려해야 할 오점이 하나 있다. 게시글을 클릭하기 했을 때마다 update로 조회수를 1씩 증가시키면 특정 게시물을 한 번만 보더라도 해당 게시물에서 새로고침을 할 때마다 무의미하게 조회수가 계속 올라간다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RequestMapping("view.do")
public String view(Model model, int b_idx) {
    
    //b_idx에 해당되는 게시물 정보를 얻어온다 
    BoardVo vo = board_dao.selectOne(b_idx);
    
    //이 게시물을 안봤으면.. 증가시켜라
    if(session.getAttribute("show"== null) {
        //조회수 증가 
        //그냥 단순히 증가할 수 있도록 하면 refresh할 때마다 조회수가 증가하기 때문에 올바른 결과를 예상할 수 없다.
        int res = board_dao.update_readhit(b_idx);
        
        //show정보를 세션에 넣는다. 
        session.setAttribute("show"true);
        
        //show정보를 다른 게시물을 보기 위해 목록보기로 이동할 때 삭제해야 한다. 안그러면 세션에 값이 남아있어서 다른 글을 읽어도 조회수가 증가하지 않음
    }
    //결과적으로 request binding
    model.addAttribute("vo", vo);
    
    
    return "board/board_view";
}
cs

위의 코드는 특정 게시물을 상세보기 할 때 호출되는 메서드이다. 잘 보면 세션에 값을 확인하고 값이 없을 때만, 처음온 것으로 인식해서 조회수를 증가하고, 세션에 값을 넣는다. 이때 어떤 값을 넣는지는 상관없다. 조건을 검사하는 내용은 세션에 담긴 값이 아니라 있냐 업냐의 여부이기 때문이다. 

저렇게 코드를 작성하면 아무리 새로고침을 누르더라도 처음 게시글을 봤을 때 이후로는 조회수가 올라가지 않는다. 

한가지 주의해야 할 점은 다른 게시물을 보기전에 세션에 있는 값을 삭제해줘야 한다는 것이다. 그렇지 않으면 계속해서 세션에 값이 존재하고 있기 때문에 다른 게시물을 보기전에 이 값을 삭제해야 한다. 

게시글을 보고 뒤로 돌아가는 시점에서 삭제하면 된다. 필자의 경우는 게시글을 보고 뒤로 가는 곳은 게시글 리스트를 보는 것이기 때문에 이를 참조해서 코드를 작성하면 될 것이다. 

  • 게시글 보기
  • 세션에 값이 있는지 확인하고 있으면 그냥 글만 보고, 없으면 조회수 증가 
  • 뒤로 가기로 리스트로 이동하면서 세션에 값 삭제
  • 다른 게시글을 읽으면 세션에 값이 있는지 확인하고 없으면 조회수 증가 .... 반복

 

 

[ 페이징 처리 ] - 코드의 내용을 보면서 이해해보자.

  1. 전체 게시글 수를 구한다. 
  2. 한 페이지에 표시할 게시물의 수, 페이지의 수를 설정한다. 
  3. 게시글의 수에 따라 동적으로 적용할 수 있도록 util클래스를 작성한다. 

getPaging()이라는 메소드의 반환값은 동적으로 작성한 html코드이다. 

파라미터는 (페이징을 적용할 URL주소, 현재 페이지 번호, 전체 게시물수, 한 페이지에 보여줄 게시물 수, 한 페이지에 보여줄 페이지 수) 총 5개를 인자로 받는다.

페이징의 전체적인 원리는 간단하다. 한 페이지에 출력할 게시물이 5개이고, 전체 게시물의 수가 26개라고 해보자.

  • 전체 게시물의 수 26을 5로 나눈 몫 5에다가, 나머지가 존재할 경우에만 +1하여 총 6개의 page가 필요하다는 것을 알수 있다.(totalPage)
  • 시작페이지와 종료 페이지는 아래의 식을 보면 이해할 수 있을 것이다. 
  • 고려사항 1(37행) : 마지막 페이지 수가 전체 페이지 수보다 크다면 마지막 페이지수를 전체 페이지 수로 변경한다.
    • 예를 들어 전체 게시물이 26개 한 페이지에 5개씩 표시한다고 해보자. 그렇다면 총 6페이지가 있을 것인데, 한 호면에 출력할 페이지수가 5개라고 해보자. 
    • 그렇다면,  < 1 2 3 4 5 >, 그리고 <5, 6, 7, 8, 9, 10>이렇게 생성이 될 것인데, 마지막 페이지는 10이 되고, 전체 페이지 수는 6이다. 이 경우 7~10페이지는 이동해봐야 게시글이 없기 때문에 삭제해서 < 6 > 만 표시되게 한다.
  • 고려사항 2(41행) : 반대로 전체 페이지 수가 마지막 페이지보다 큰 경우 다음으로 이동할 수 있도록 버튼을 활성화한다.
  • 고려사항 3(43행) : 시작 페이지 번호가 1보다 크다면 이전페이지로 이동하는 버튼을 활성화 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package util;
/*
        nowPage:현재페이지
        rowTotal:전체데이터갯수
        blockList:한페이지당 게시물수
        blockPage:한화면에 나타낼 페이지 목록수
 */
public class Paging {
    public static String getPaging(String pageURL,int nowPage, int rowTotal,int blockList, int blockPage){
        
        int totalPage/*전체페이지수*/,
            startPage/*시작페이지번호*/,
            endPage;/*마지막페이지번호*/
        
        //다음 페이지 혹은 이전 페이지로 이동할 수 있는 버튼의 활성화 여부를 저장하는 변수
        boolean  isPrevPage,isNextPage;
        StringBuffer sb; //모든 상황을 판단하여 동적으로 HTML코드를 저장할 곳. String불변의 법칙으로 인해 버퍼를 사용한다.
        
        
        isPrevPage=isNextPage=false;
        //입력된 전체 자원을 통해 전체 페이지 수를 구한다..
        totalPage = (int)(rowTotal/blockList); //몫 연산자
        if(rowTotal%blockList!=0)totalPage++;  //만약 나머지가 있다면 페이지 1증가
        
 
        //만약 잘못된 연산과 움직임으로 인하여 현재 페이지 수가 전체 페이지 수를
        //넘을 경우 강제로 현재페이지 값을 전체 페이지 값으로 변경
        if(nowPage > totalPage)nowPage = totalPage;
        
 
        //시작 페이지와 마지막 페이지를 구함.
        startPage = (int)(((nowPage-1)/blockPage)*blockPage+1);
        endPage = startPage + blockPage - 1//
        
        //마지막 페이지 수가 전체페이지수보다 크면 마지막페이지 값을 변경
        //end가 10인데, total이 8이라면 9, 10페이지에는 게시글이 없지만 페이지만 있는 것이므로 클릭하더라도 게시글이 없다.
        if(endPage > totalPage)endPage = totalPage;
        
        //마지막페이지가 전체페이지보다 작을 경우 다음 페이징이 적용할 수 있도록
        //boolean형 변수의 값을 설정
        if(endPage < totalPage) isNextPage = true;
        //시작페이지의 값이 1보다 크면 이전페이징 적용할 수 있도록 값설정
        if(startPage > 1)isPrevPage = true;
        
        //HTML코드를 저장할 StringBuffer생성=>코드생성
        sb = new StringBuffer();
//-----그룹페이지처리 이전 --------------------------------------------------------------------------------------------        
        if(isPrevPage){
            sb.append("<a href ='"+pageURL+"?page=");
            sb.append(startPage - 1);
            sb.append("'>◀</a>");
        }
        else
            sb.append("◀");
        
//------페이지 목록 출력 -------------------------------------------------------------------------------------------------
        sb.append("|");
        for(int i=startPage; i<= endPage ;i++){
            if(i>totalPage)break;
            if(i == nowPage){ //현재 있는 페이지
                sb.append("&nbsp;<b><font color='#91b72f'>");
                sb.append(i);
                sb.append("</font></b>");
            }
            else{//현재 페이지가 아니면
                sb.append("&nbsp;<a href='"+pageURL+"?page=");
                sb.append(i);
                sb.append("'>");
                sb.append(i);
                sb.append("</a>");
            }
        }// end for
        
        sb.append("&nbsp;|");
        
//-----그룹페이지처리 다음 ----------------------------------------------------------------------------------------------
        if(isNextPage){
            sb.append("<a href='"+pageURL+"?page=");
            sb.append(endPage+1);
            sb.append("'>▶</a>");
        }
        else
            sb.append("▶");
//---------------------------------------------------------------------------------------------------------------------        
 
        return sb.toString();
    }
}
cs

'BackEnd > Spring' 카테고리의 다른 글

SpringBoot Day 2  (0) 2022.08.18
SpringBoot Day1  (0) 2022.08.10
SpringLegacyProject_SpringSecurity적용하기  (0) 2022.07.12
Spring기초_Day6_웹 개발 모델  (0) 2022.07.11
Spring_Day5_SpringLifeCycle  (0) 2022.07.11