728x90

조회수 구현 게시글을 클릭해서 포스트를 조회할 때 조회수를 올려주기만 하면 된다.

그러나 이렇게만 한다면 댓글 작성할 때나 같은 아이디로 다시 들어갈 때나 조회수가 계속 올라간다.

이를 방지하기 위해 쿠키를 이용해서 조회수를 구현하는 방법을 기록한다.

쿠키란?

  • 서버가 클라이언트에게 보내는 데이터 중 하나로써, 클라이언트는 받은 쿠키 데이터를 로컬영역에 저장한다.
  • 다음에 서버를 방문한다면 쿠키를 요청 헤더에 포함해서 서버에게 전달한다.

1. 게시판 DB

CREATE TABLE `tb_board` (
  `id` int NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `content` text NOT NULL,
  `writer_id` int NOT NULL,
  `writer` varchar(20) NOT NULL,
  `delete_yn` varchar(1) DEFAULT 'N',
  `create_date` datetime DEFAULT NULL,
  `views` int DEFAULT '0',
  `image` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `writer_id` (`writer_id`),
  CONSTRAINT `tb_board_ibfk_1` FOREIGN KEY (`writer_id`) REFERENCES `tb_userinfo` (`id`) ON DELETE CASCADE
)
  • views : 조회수

2. View에 조회수 추가 (게시판 목록 html)

            <!-- contents -->
            <table class="table caption-top table-bordered table-hover">
                <caption>List</caption>
                <thead>
                    <tr>
                        <th class="text-center" width="50" scope="col">No</th>
                        <th class="text-center" width="950" scope="col">제목</th>
                        <th class="text-center" width="180" scope="col">작성자</th>
                        <th class="text-center" width="200" scope="col">작성일</th>
                        <th class="text-center" width="150" scope="col">조회수</th>
                    </tr>
                </thead>

                <tbody>
                    <tr th:each="board : ${boardList}">
                        <td class="mt-5 text-center" scope="row" th:text="${board.id}">1</td>
                        <td><a th:text="${board.title}" th:href="@{/board/post(id=${board.id})}" style="text-decoration:none; color:black;">제목</a></td>
                        <td class="text-center" th:text="${board.writer}">작성자</td>
                        <td class="text-center" th:text="${#dates.format(board.createDate, 'yyyy/MM/dd HH:mm')}">작성일</td>
                        <td class="text-center" th:text="${board.views}">조회수</td>
                    </tr>
                </tbody>
            </table>
  • 마지막 줄 th:text="${board.views}" : 조회수

3. Service

// 조회수 증가
    public void updateViews(Board board, String username, HttpServletRequest request,
                            HttpServletResponse response) throws Exception {
        Cookie[] cookies = request.getCookies();
        Map<String, String> mapCookie = new HashMap<>();

        if (request.getCookies() != null) {
            for (int i = 0; i < cookies.length; i++) {
                mapCookie.put(cookies[i].getName(), cookies[i].getValue());
            }

            String viewsCookie = mapCookie.get("views");
            String newCookie = "|" + board.getId();

            // 쿠키가 없을 경우 쿠키 생성 후 조회수 증가
            if (viewsCookie == null || !viewsCookie.contains(newCookie)) {
                Cookie cookie = new Cookie("views", viewsCookie + newCookie);
                response.addCookie(cookie);

                boardRepository.updateViews(board);
            }
        }
    }
  • request : 쿠키 정보를 얻을 HttpServletRequest 객체
  • response : 쿠키 정보를 추가할 HttpServletResponse 객체 
  • mapCookie.put : HashMap을 이용해 key value로 쿠키 값을 저장
  • viewsCookie : hashmap에 views라는 key값으로 저장된 value객체를 저장
  • newCookie : 새로운 쿠키를 추가할 때 사용 (id : 게시판 번호)
  • 쿠키 객체를 생성하고 추가할 쿠키 값을 초기화
    • 2번 게시글 조회 -> (views, null|2)
    • 3번 게시글 조회 -> (views, null|2|3) ...
  • response.addCookie를 통해 쿠키를 추가하고 조회수 1 증가
  • contains -> https://black-mint.tistory.com/39
 

[Java] String contains() 문자열 포함 여부

문자열 포함 여부 확인 방법을 기록한다. 1. 코드 String s = "hello World"; System.out.println("e : " + s.contains("e")); System.out.println("hello : " + s.contains("hello")); System.out.println("oW :..

black-mint.tistory.com

4. Controller

// 포스트 조회
@GetMapping("/post")
public String readPost(Model model, @RequestParam(required = false) Long id,
                       Principal principal, HttpServletRequest request,
                       HttpServletResponse response) throws Exception {
    String loginUser = principal.getName();
    Board board = boardService.contentLoad(id);

    boardService.updateViews(board, loginUser, request, response);

    model.addAttribute("board", board);
    model.addAttribute("loginUser", loginUser);

    return "board/post";
}
  • 쿠키를 사용하기 위해 HttpServletRequest request, HttpServletResponse response 를 파라미터로 받는다.

+ Recent posts