티스토리 뷰

3) 쿠키를 이용한 상태정보 유지하기

  • 기존에 만들고 있었던 guestbook 예제를 이용해 보겠습니다.
  • guestbook에서 list를 요청했을 때 쿠키를 이용해서 이 클라이언트가 처음 방문한 건지 두 번째 방문한 건지 몇 번째 방문한 건지 그것들을 기억하고 있다가 보여주는 예제입니다.

  • 일단 해야 될 일은 이 클라이언트가 해당 페이지로 요청이 들어왔을 때 쿠키가 존재하는지 먼저 알아내야 합니다.
  • 만약 쿠키가 이미 존재하고 있던 클라이언트라고 한다면 이 클라이언트가 가지고 있는 쿠키의 값1이라는 값을 가져와서 이 값에다가 1을 더한 다음에 다시 클라이언트한테 보내주도록 하겠습니다.
  • 그러니까 다시 한번 요청을 하게 되면 1이라는 값을 가져가서 1을 더해서 다시 줬기 때문에 2라는 값이 출력이 되고 있는 것을 확인할 수 있습니다.
  • 변경된 value(count)의 값을 클라이언트 쪽에도 적용하게 하려면 반드시 쿠키는 똑같은 이름으로 매번 새로 만들어서 보내주셔야 합니다그러면 클라이언트에 똑같은 이름의 쿠키가 들어왔을 때 기존의 쿠키랑 교체할 수 있기 때문입니다교체가 돼야 새로운 value를 가진 쿠키를 클라이언트가 갖고 있을 것이고 다시 요청이 들어왔을 때 value 값이 2, 3, 4, 5 이렇게 바뀔 수 있을 것입니다.

  • 마지막으로 jsp에 값을 전달할 수 있도록 model.addAttribute를 지정해줍니다.

실습코드

GuestbookController.java

package kr.or.connect.guestbook.controller;

 

import java.util.ArrayList;

import java.util.List;

 

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

import org.springframework.web.bind.annotation.CookieValue;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.ModelAttribute;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestParam;

 

import kr.or.connect.guestbook.dto.Guestbook;

import kr.or.connect.guestbook.service.GuestbookService;

 

@Controller

public class GuestbookController {

           @Autowired

           GuestbookService guestbookService;

 

           @GetMapping(path="/list")

           public String list(@RequestParam(name="start", required=false, defaultValue="0") int start, ModelMap model, HttpServletRequest request, HttpServletResponse response) {

       

                      String value = null;

                      boolean find = false;

                      Cookie[] cookies = request.getCookies(); //쿠키를 request객체에서 얻어옴.

                      if(cookies != null) {

                                  for(Cookie cookie : cookies) {

                                             if("count".equals(cookie.getName())) {

                                                        find = true;

                                                        value = cookie.getValue();

                                             }

                                  }

                      }

                     

                      if(!find) {  //처음 들어왔을 때

                                  value = "1"; //쿠키는 String으로 된 값만 가질 수 있음

                      }else { // 쿠키를 찾았다면.

                                  try {

                                             int i = Integer.parseInt(value);

                                             value = Integer.toString(++i);

                                  }catch(Exception ex) {

                                             value = "1";

                                  }

                      }

                     

                      Cookie cookie = new Cookie("count", value);

                      cookie.setMaxAge(60 * 60 * 24 * 365); // 1년 동안 유지. 0이면 쿠키 바로 삭제. -1이면 브라우저 닫힐 때까지만 쿠키 보존.

                      cookie.setPath("/"); // "/" 경로 이하에 모두 쿠키 적용.

                      response.addCookie(cookie); // response한테 addCookie()를 달아서 응답 결과로 보내줘야 합니다.

                     

                      //이전코드

                      List<Guestbook> list = guestbookService.getGuestbooks(start);

                     

                      int count = guestbookService.getCount();

                      int pageCount = count / GuestbookService.LIMIT;

                      if(count % GuestbookService.LIMIT > 0)

                                  pageCount++;

                     

                      List<Integer> pageStartList = new ArrayList<>();

                      for(int i = 0; i < pageCount; i++) {

                                  pageStartList.add(i * GuestbookService.LIMIT);

                      }

                     

                      model.addAttribute("list", list);

                      model.addAttribute("count", count);

                      model.addAttribute("pageStartList", pageStartList);

                      //이전코드 끝

                      model.addAttribute("cookieCount", value); // jsp에게 전달하기 위해서 쿠키 값을 model에 담아 전송한다.

                     

                      return "list";

           }

          

           @PostMapping(path="/write")

           public String write(@ModelAttribute Guestbook guestbook,

                                                                   HttpServletRequest request) {

                      String clientIp = request.getRemoteAddr();

                      System.out.println("clientIp : " + clientIp);

                      guestbookService.addGuestbook(guestbook, clientIp);

                      return "redirect:list";

           }

}

 

  • list.jsp 에서 방명록 전체 수 옆에 방문한 수를 출력하는 el 코드를 추가합니다.
    • 방명록 전체 수 : ${count }
    • 방문한 수 : ${cookieCount }<br><br>

guestbook list.jsp 화면

방명록 전체 수: ${count}, 방문한 수: ${cookieCount}

 

  • 위의 코드를 Spring MVC가 제공하는 CookieValue애노테이션을 이용해 수정한 소스를 보도록 하겠습니다.

GuestbookController.java

package kr.or.connect.guestbook.controller;

 

import java.util.ArrayList;

import java.util.List;

 

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

import org.springframework.web.bind.annotation.CookieValue;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.ModelAttribute;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestParam;

 

import kr.or.connect.guestbook.dto.Guestbook;

import kr.or.connect.guestbook.service.GuestbookService;

 

@Controller

public class GuestbookController {

           @Autowired

           GuestbookService guestbookService;

 

           @GetMapping(path="/list")

           public String list(@RequestParam(name="start", required=false, defaultValue="0") int start, ModelMap model, @CookieValue(value="count", defaultValue="1", required=true) String value, HttpServletResponse response) {

                     

        // 쿠키 값을 1증가 시킨다.

                      try {

                                  int i = Integer.parseInt(value);

                                  value = Integer.toString(++i);

                      }catch(Exception ex){

                                  value = "1";

                      }

                     

        // 쿠키를 전송한다.

                      Cookie cookie = new Cookie("count", value);

                      cookie.setMaxAge(60 * 60 * 24 * 365); // 1년 동안 유지.

                      cookie.setPath("/"); // / 경로 이하에 모두 쿠키 적용.

                      response.addCookie(cookie);

                     

                      //이전코드

                      List<Guestbook> list = guestbookService.getGuestbooks(start);

                     

                      int count = guestbookService.getCount();

                      int pageCount = count / GuestbookService.LIMIT;

                      if(count % GuestbookService.LIMIT > 0)

                                  pageCount++;

                     

                      List<Integer> pageStartList = new ArrayList<>();

                      for(int i = 0; i < pageCount; i++) {

                                  pageStartList.add(i * GuestbookService.LIMIT);

                      }

                     

                      model.addAttribute("list", list);

                      model.addAttribute("count", count);

                      model.addAttribute("pageStartList", pageStartList);

                      //이전코드 끝

                      model.addAttribute("cookieCount", value); // 쿠키를 추가한다.

                     

                      return "list";

           }

          

           @PostMapping(path="/write")

           public String write(@ModelAttribute Guestbook guestbook,

                                                                   HttpServletRequest request) {

                      String clientIp = request.getRemoteAddr();

                      System.out.println("clientIp : " + clientIp);

                      guestbookService.addGuestbook(guestbook, clientIp);

                      return "redirect:list";

           }

}

 

생각해보기

  • HttpServletRequest는 특정 이름의 Cookie를 구하는 메소드를 가지고 있지 않습니다.
  • 그렇기 때문에, 특정 이름의 쿠키를 구하려면 반복문을 이용해 원하는 이름의 쿠키가 있는지 찾아야 합니다.
  • CookieValue애노테이션을 이용하면 쉽게 특정 이름의 쿠키 값을 구할 수 있습니다.
  • 불편한 느낌의 코드가 있다면, 어떻게 개선해야 할지 이미 개선된 다른 방법이 있는지 찾아보세요.

참고 자료

[참고링크] Class Cookie
https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/Cookie.html

[참고링크] Cookies in Servlet      https://www.javatpoint.com/cookies-in-servlet

 

Comments