티스토리 뷰
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>
방명록 전체 수: ${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
'부스트코스 웹 프로그래밍 > 5. 웹 앱 개발: 예약서비스 3' 카테고리의 다른 글
4. 상태유지기술(Cookie & Session) - BE (5) (0) | 2019.08.09 |
---|---|
4. 상태유지기술(Cookie & Session) - BE (4) (0) | 2019.08.09 |
4. 상태유지기술(Cookie & Session) - BE (2) (0) | 2019.08.09 |
4. 상태유지기술(Cookie & Session) - BE (1) (0) | 2019.08.09 |
3. form 데이터 보내기 - FE (2) (0) | 2019.08.09 |