만족은 하되 안주하지는 말자

기록해야 기억한다

프로그래밍/JAVA

[Java] Java Servlet Cookie 생성 및 관리

D36choi 2021. 5. 13. 11:27
728x90

쿠키

쿠키는 작은 데이터 조각입니다.

이 데이터 조각은 클라이언트 - 서버 간 통신에서 클라이언트가 저장하고 있는 데이터로, 서버가 클라이언트의 요청 정보에서 확인할 수 있습니다.

이걸 통해 서버는 클라이언트가 누군지를 확인할 수 있습니다. 또 어떤 servlet 에서 다른 servlet 으로 어떤 데이터를 전달할때도 쓰입니다.

쿠키를 사용할 때 중요한 것은 임시 데이터라는 것입니다. 쿠키는 특정 시간이 지나면 자동으로 만료 되며 사용자가 언제든지 삭제하거나 차단할 수 있습니다.

또한 기본적으로 쿠키는 기본적으로 암호화되지 않고 전송되기 때문에 비밀번호 같은 민감한 데이터는 담아선 안됩니다.

쿠키 생성법

java11, spring-boot-web-starter 에서 진행해보겠습니다.

Cookie 클래스는 javax.servlet.http 패키지에 존재합니다. 인텔리제이나 이클립스가 알아서 패키지들을 임포트해주겠지만 알아둡시다.

간단한 REST API 를 만들어서 쿠키를 생성해보겠습니다.

@Controller
public class IndexController {


    @ResponseBody
    @GetMapping("/cookie")
    public String cookie(HttpServletRequest request, HttpServletResponse response) {
        Cookie cookie = new Cookie("name", "d36choi");
        cookie.setMaxAge(60 * 60); // 기준: 1초
        cookie.setPath("/cookie");
        response.addCookie(cookie);
        return "cookie added";
    }

}

Cookie 생성자의 첫번쨰는 key, 두번째는 value 입니다. 해당 주소에 접속하면 클라이언트는 name = "d36choi" 쿠키가 생성됩니다.

cookie 가 추가되었다. 이제 이 쿠키는 1시간 동안 클라이언트 요청에 자동 포함되서 전송될 것이다.

쿠키 수명

cookie.setMaxAge(60*60) 은 쿠키의 수명을 의미합니다. 이 메서드에 값 1을 넣으면 그 지속시간은 1초라는 것입니다.

여기서는 60곱하기60이니 설정된 값은 1시간의 수명을 의미합니다.

쿠키 유효 path 설정

cookie.setPath("/cookie") 는 쿠키가 유효한 범위를 의미합니다.

만약 이 쿠키가 있는 상태로 다른 path(경로) 에 접속하면 쿠키는 서버에게 전달되지 않습니다.

쿠키 확인

클라이언트가 HTTP Request 를 보내면 WAS(Web Application Server) 를 통해 Filter,DispatcherServlet 을 거쳐

Controller 에 전달됩니다. 이 객체에는 쿠키값들의 리스트도 포함되어있습니다.

    @ResponseBody
    @GetMapping("/cookie/list")
    public Map<String, String> getCookie(HttpServletRequest request, HttpServletResponse response) {
        final Cookie[] cookies = request.getCookies();

        Map<String, String> result = new HashMap<>();
        for (Cookie cookie : cookies) {
            result.put(cookie.getName(),cookie.getValue());
        }
        return result;
    }

쿠키를 생성한 뒤 위 url 에 접근해봅니다.

cookie 리스트가 응답으로 왔다.

 

쿠키 path 설정 확인해보기

    @ResponseBody
    @GetMapping("/another/path/{key}")
    public String pathTest(HttpServletRequest request, HttpServletResponse response, @PathVariable String key) {
        final Optional<Cookie[]> cookies = Optional.ofNullable(request.getCookies());
        final Cookie[] cookies1 = cookies.orElseThrow(NullPointerException::new);
        final Optional<String> s = readCookie(cookies1, key);
        return s.orElse("no cookie matching that key.");

    }

    public Optional<String> readCookie(Cookie[] cookies,String key) {
        return Arrays.stream(cookies)
                     .filter(c -> key.equals(c.getName()))
                     .map(Cookie::getValue)
                     .findAny();
    }

제가 만든 쿠키는 유효범위가 "/cookie" 와 그 하위 경로였습니다.

위 경로는 전혀 다른 "/another" 로 시작합니다. 만약 해당 경로에 요청을 보낼 때에 클라이언트는 자동적으로 위에서 만든 쿠키를 포함하지 않고 요청을 날리게 됩니다.

만약 찾으려는 key 값에 해당하는 쿠키가 없다면 no cookie 메시지가 뜰것입니다.

 

"name" 을 키로 가지는 쿠키가 없기 때문에, 없다는 응답 메시지가 왔다.

 

 

회사에서 처음으로 맡게된 개발업무에서 이벤트의 추천인코드를 쿠키로 저장해 전달하는 기능을 구현해야하는 요구사항이 있었기에,

쿠키를 조금 공부하는 겸 포스팅해봤다. 

 

참고로 실무에서는 개발자분들이 전부 "쿠키를 만든다" 가 아니라 "쿠키를 굽는다" 라고 표현하신다. 왠지 모르게 귀여운 어감이다..