본문 바로가기
Dev.Basic/컴퓨터 공학

[HTTP] Cookie 기본 개념

by superpil 2021. 9. 2.

목차

Cookie

쿠키(영어: cookie)란 하이퍼 텍스트의 기록서(HTTP)의 일종으로서 인터넷 사용자가 어떠한 웹사이트를 방문할 경우 그 사이트가 사용하고 있는 서버를 통해 인터넷 사용자의 컴퓨터에 설치되는 작은 기록 정보 파일을 일컫는다.
이 기록 파일에 담긴 정보는 인터넷 사용자가 같은 웹사이트를 방문할 때마다 읽히고 수시로 새로운 정보로 바뀐다.
쿠키는 소프트웨어가 아니다. 쿠키는 컴퓨터 내에서 프로그램처럼 실행될 수 없으며 바이러스를 옮길 수도, 악성코드를 설치할 수도 없다. 하지만 스파이웨어를 통해 유저의 브라우징 행동을 추적하는데에 사용될 수 있고, 누군가의 쿠키를 훔쳐서 해당 사용자의 웹 계정 접근권한을 획득할 수도 있다. - 위키백과 -

 

쿠키에 대한 개념은 위키백과의 설명글을 참고하면 이해하기 쉽다.

단, 공부하고 읽어보면....

나만 그런가?! 위키백과에서 설명하는 글은 공부하기 전에는 아무리 읽어도 모르겠는데 공부하고 나면 정리가 잘된 글이라고 느낀다. 😓

공부하기 전 나에게 설명하 듯 위키백과 내용을 이해하기 쉽게 풀어서 정리하고 더!불어~ 쿠키의 특징들 까지 살펴보자.

 

쿠키 다이어그램

쿠키는 뭔가를 저장하는 저장소 다. 끝! (완전 단순 소오름!🙀)

여기서 뭔가가 뭔가?! 이다.

 

위 클라이언트(브라우저를 뜻함. 현재 글에서 클라이언트와 브라우저는 동일한 의미로 사용)와 서버간의 통신하는 다이어그램을 보자.

클라이언트는 서버와 HTTP프로토콜 통신으로 데이터를 주고 받고 한다.

 

다이어그램에서 2번을 보면, 서버가 클라이언트로 응답할때 Cookie에 "Superpil"데이터를 포함해서 보내게 된다. (Cookie로 설정된 "Superpil"데이터는 HTTP Response Header에 저장되어 클라이언트에게 전송된다.)

 

응답을 받은 클라이언트는 "Superpil"데이터를 브라우저의 Cookie에 자체적으로 저장한다.

이후, 클라이언트는 동일한 서버와 재통신 할 경우 쿠키에 저장한 데이터("Superpil")를 함께 서버로 전송 한다.(다이어그램 3번)

 

위 나열한 순서가 Cookie가 동작되는 일련의 과정이다.

대체로 쿠키는 자동로그인, 장바구니, 하루동안 창닫기(팝업)와 같은 기능을 구현할때 사용하며, 보안상 중요한 데이터는 저장하지 않는다.

 

특징

  1. 쿠키는 클라이언트에 저장되며, Key와 Value로 이루어진 데이터 이다.
  2. 주로 쿠키는 서버에서 생성하여 Set-Cookie HTTP Response Header에 넣어 클라이언트에게 전달 하고, 클라이언트에서 직접 쿠키에 데이터를 저장 할 수도 있다.
  3. 쿠키는 사용자가 별다른 컨트롤 없이 Request시 자동으로 브라우저가 Request Header를 넣어서 서버에 전송한다.
  4. 쿠키는 만료기간을 설정할 수 있으며, 만료기간 전 까지 브라우저가 종료 되어도 삭제 되지 않는다.

 

문법 및 속성

key=value; path=경로; expires=만료날짜; domain=도메인; secure; httpOnly

쿠키는 Key=Value쌍으로 구성되고 path, expires 등의 속성을 가진다. 해당 속성들은 ;로 구분된다.

 

👉 key=value

  1. value에 실제 데이터가 담겨져 있다.
  2. key값으로 쿠키의 value값을 조회, 갱신, 삭제를 할 수 있다.

 

👉 path

"super=pil;path=/hello"

cookie에 설정한 path경로와 같은 경우
cookie에 설정한 path경로와 같은 하위 경로
cookie에 설정한 path경로가 다른 경우

  1. 특정 경로에서만 쿠키를 활성화 시키는 속성이다.
  2. 가령 localhost:8080에서 위와 같이 path=/hello로 cookie를 설정했다면, localhost:8080/hellolocalhost:8080/hello/모든 하위경로 는 cookie가 저장되어 확인 할 수 있지만, 그외 다른 경로(/hello를 제외한)의 경우 cookie를 확인 할 수 없다.

 

👉 domain

  1. 쿠키가 전송되어질 서버 도메인을 지정하는 속성 이다.
  2. 도메인을 설정할 경우 해당 도메인 및 하위 도메인에서만 쿠키에 접근할 수 있다.
  3. 가령, domain에 tistory.com로 설정할 경우 skin.tistory.com에서도 쿠키 정보에 접근이 가능하다.
  4. 반면 domain을 설정하지 않을 경우 tistory.com에서만 쿠키에 접근 가능하다.

 

👉 expires

  1. 쿠키의 만료기간을 의미하며 만료기간이 지난경우 자동 삭제된다.
  2. 반대로 만료기간 전까지는 삭제되지 않는다.(직접 쿠키를 삭제하는 경우는 제외)

 

👉 secure

  1. secure속성을 설정하면 HTTPS통신이 아닌경우 서버로 쿠키를 전송하지 않는다.
  2. HTTP통신을 하게 되면 쿠키를 암호화 하지 않은 상태로 서버로 전달하기 때문에 보안상 secure속성을 설정하는게 좋을 것 같다.

 

👉 httpOnly

cookie HttpOnly속성 설정
httpOnly설정 후 cookie조회

  1. 저장된 쿠키는 서버와 통신할때만 정보를 확인 할 수 있으며, 자바스크립트로 document.cookie에 접근하여 쿠키 정보를 조회 할 수 없다.

 

클라이언트와 서버 통신으로 쿠키 핸들링

클라이언트 요청에 서버에서 쿠키를 생성 후 응답하고 클라이언트에 저장되는 일련의 과정을 예제로 만들어 보자.(위 쿠키 개념 다이어그램을 예제로 구현)

예제는 Spring Boot와 Vue 환경에서 작성한 코드 이다.

 

서버에서 쿠키생성

<template>
  <div>
    <h1>Cookie 요청</h1>
  </div>
</template>

<script>
import { apiGetCookie } from "@/api/index";

export default {
  async created() {
        // http://localhost:8081/api/cookie로 요청
    await apiGetCookie();
  },
}
</script>

👉 await apiGetCookie()

  1. Axios를 사용해 클라이언트에서 서버로 요청(http://localhost:8081/api/cookie)을 한다.
  2. src/api/index에 Axios코드가 있으며, import구문으로 apiGetCookie 함수를 불러온다.
  3. 쿠키 예제에 집중하기 위해 Axios코드는 간단한 설명으로 대체한다.

 

package com.example.demo.controller;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

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

@RestController
@RequestMapping("/api")
public class Sample {

  @GetMapping("/cookie")
  public void cookie(HttpServletResponse response) {
    Cookie cookie = new Cookie("super", "pil");
    cookie.setPath("/");
    response.addCookie(cookie);
  }

}

👉 new Cookie("super", "pil")

  1. 클라이언트 요청을 받은 서버는 Cookie객체를 생성 후, key=value를 설정한다.
  2. 위 예제에서 keysuper, valuepil로 설정한다.

 

👉 cookie.setPath("/")

  1. path를 설정하지 않으면 쿠키는 Response Header에 담아서 응답하지만 브라우저에 저장하지 않는다. ( 테스트 해본결과 path가 없어도 브라우저에 저장은 하는 것 같다. 다만, 개발자도구에 cookies를 확인해보면 해당 쿠키는 확인할 수 없다. 하지만 서버와 재통신에서는 쿠키가 전달된다. 왜 그런지 모르겠지만.. 걍 정신건강을 생각해서 path속성을 사용하자.)
  2. 현재 예제에서는 최상위 Root 경로로 설정했으며, 모든 경로에서 super=pil 쿠키를 사용할 수 있게 된다.

 

👉 response.addCookie(cookie)

  1. HttpServletResponse객체에 쿠키정보를 담아서 클라이언트에 응답한다.
  2. 이제 클라이언트는 Response Header에 set-cookie정보를 브라우저의 cookies에 저장한다.
  3. 아래 이미지에서 정상적으로 저장된 것을 확인 할 수 있다.

 

Response Headers에 set-cookie 정보
브라우저 쿠키에 담긴 정보

 

클라이언트가 보낸 쿠키 정보 확인

앞에서 서버가 응답해준 쿠키를 브라우저에 정상적으로 저장했다.

이제 클라이언트가 동일한 서버와 재통신할 경우 저장된 쿠키를 서버로 전송하여 서버에서 조회 할 수 있는 코드를 만들어 보자.

 

<template>
  <div>
    <button @click="sendCookie">서버와 재통신</button>
  </div>
</template>

<script>
import { apiSendCookie } from "@/api/index";

export default {
  methods:{
    async sendCookie(){
      await apiSendCookie();
    }
  },
}
</script>

👉 <button @click="sendCookie">

  1. 버튼을 클릭하면 sendCookie()가 실행된다.
  2. Axios를 사용해 서버와 재통신을 요청하며, 이번 요청 API 주소는 http://localhost:8081/api/cookie/send로 한다.

 

👉 await apiSendCookie()

클라이언트와 서버간 재통신 Request Headers정보

  1. 현재 쿠키 생성 예제로 인해 쿠키 정보는 브라우저에 저장된 상태이며, 이번 API요청으로 저장된 쿠키는 서버로 전송 될 것 이다.
  2. 쿠키정보는 브라우저에서 자체적으로 Request Header에 담아서 보내기 때문에 특별한 코드는 없다.

 

package com.example.demo.controller;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

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

@RestController
@RequestMapping("/api")
public class Sample {

  @GetMapping("/cookie/send")
  public void cookieSend(HttpServletRequest request) {
    Cookie[] cookies = request.getCookies();
    for(int i = 0; i < cookies.length; i++) {
      System.out.println(i + "번째 쿠키 Key: " + cookies[i].getName()); // super
      System.out.println(i + "번째 쿠키 Value: " + cookies[i].getValue()); // pil
    }
  }

}

👉 HttpServletRequest request

  1. 이제 클라이언트에 보낸 쿠키 정보를 출력 해보자.
  2. 쿠키는 HttpServletRequest객체에 담겨있으며, getCookies()로 쿠키를 확인 할 수 있다.

 

지금까지 서버에서 쿠키를 내려주면 클라이언트에서 저장하고, 저장된 쿠키는 클라이언트가 재요청시 서버로 올려주는 가장 기본적인 일련의 과정을 코드로 만들어 봤다.

이제 한발 더 나아가 쿠키의 속성에 대해 다뤄 보자.

 

쿠키 속성 설정

Expire

서버에서 쿠키를 생성할때 setMaxAge()로 만료기간을 설정 할 수 있으며, 만료기간 단위는 초(sec)다.

 

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

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

@RestController
@RequestMapping("/api")
public class Sample {

  @GetMapping("/cookie")
  public void cookieSend(HttpServletResponse response) {
    Cookie cookie = new Cookie("super", "pil");
    cookie.setPath("/");
    cookie.setMaxAge(60 * 60 * 24 * 365); // 만료기간 1년 설정
    response.addCookie(cookie);
  }

}

👉 cookie.setMaxAge(60 * 60 * 24 * 365)

  1. 위 예제에서 만료기간 1년으로 설정했다.
  2. 예제처럼 계산식으로 넣어도 되지만 직접 계산해서 cookie.setMaxAge(31536000)로 잘~ 적용된다(당연한 말이지만)

 

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

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

@RestController
@RequestMapping("/api")
public class Sample {

  @GetMapping("/cookie")
  public void cookieSend(HttpServletResponse response) {
    Cookie cookie = new Cookie("super", "pil");
    cookie.setPath("/");
    cookie.setMaxAge(-1);
    response.addCookie(cookie);
  }

}

cookie 세션단위로 만료기간 설정

👉 cookie.setMaxAge(-1)

  1. -1의 경우 브라우저가 종료가 될 때 쿠키도 만료 되어 삭제된다.
  2. 개발자도구에서 Expires / Max-Age에 Session의미가 세션단위으로 만료기간이 설정되었다는 의미다.

 

path

위 "문법 및 속성"에서 자세히 설명한 내용으로 여기서는 복습겸 간단하게 알아보고 넘어가자.

 

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

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

@RestController
@RequestMapping("/api")
public class Sample {

  @GetMapping("/cookie")
  public void cookieSend(HttpServletResponse response) {
    Cookie cookie = new Cookie("super", "pil");
    cookie.setPath("/super");
    response.addCookie(cookie);
  }

}

👉 cookie.setPath("/super")

  1. URL경로가 /super 또는 /super하위경로 일 경우만 쿠키 정보를 확인할 수 있다.

 

domain

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

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

@RestController
@RequestMapping("/api")
public class Sample {

  @GetMapping("/cookie")
  public void cookieSend(HttpServletResponse response) {
    Cookie cookie = new Cookie("super", "pil");
    cookie.setPath("/");
        cookie.setDomain("superpil.com")
    response.addCookie(cookie);
  }

}

👉 cookie.setDomain("superpil.com")

  1. 도메인이 superpil.com또는 서브 supepril도메인에서 해당 쿠키 정보에 접근 가능하다.

 

클라이언트에서 직접 쿠키 핸들링

쿠키는 서버로 부터 받을 수 있지만 클라이언트에서 자바스크립트를 사용하여 직접 쿠키를 저장할 수 있다.

당연하게 생각할수 있겠지만, 클라이언트에서 직접 저장한 쿠키도 서버와 통신 할 경우 서버로 전송 된다.

 

Cookie 생성

// cookie생성 문법
document.cookie = "Name=Value(값);Expires=날짜;Domain=도멘인;Path=경로;Secure;httpOnly";

쿠키 생성 문법과 속성은 서버에서 생성하는 것과 동일 하다.

다른점은 자바스크립트에서는 특정 메소드는 없고 document에 접근하여 쿠키를 생성,조회,수정,삭제를 할 수 있다.

 

const btn = document.querySelector("#btn");

btn.addEventListener("click", ()=>{
  const cookieInfo = "CookieName=Value;"
  document.cookie = cookieInfo;
})

쿠키 생성

👉 document.cookie = cookieInfo

  1. 버튼을 클릭하면 "CookieName=Value" 를 쿠키에 저장한다.

 

Cookie 조회

document.cookie // CookieName=Value

const cookieValue = document.cookie.match('(^|;) ?' + 'CookieName' + '=([^;]*)(;|$)');
console.log('cookieValue', cookieValue[2]); // value

👉 document.cookie

  1. 단순하게 쿠키값을 조회 할 수 있다.
  2. 하지만 key값과 value값이 한번에 나오기 때문에 값으로 사용할 수 없다. value값만 얻기 위해서는 아래 코드를 사용해서 문자열을 잘라야한다.

 

👉 const cookieValue = document.cookie.match('(^|;) ?' + 'CookieName' + '=([^;]*)(;|$)')

cookie 자르기

  1. CookieName에 찾고 싶은 쿠키의 key값을 넣으면 배열로 리턴 된다.
  2. 2번 index에 쿠키 value값이 할당되어 있다.

 

Cookie 수정

document.cookie="CookieName=superpil"
  1. 수정하고 싶은 쿠키의 key값=변경하고 싶은 value값을 다시한번 설정하면 된다.
  2. 해당 쿠키에 새로운 value값이 덮어씌워진다.

 

Cookie 삭제

document.cookie = 'CookieName' + '=; expires=Thu, 01 Jan 1999 00:00:10 GMT;';
  1. 쿠키 이름으로 삭제할 쿠키를 선택하고 expires에 과거 date를 설정하면 삭제 된다.

 

잘못된 내용이나 보충이 필요한 내용이 있다면 댓글 남겨 주세요!

주니어 개발자에게 큰 도움이 됩니다! 감사합니다! 😃

 

Reference

  1. 쿠키와 document.cookie - cookie 설명
  2. HTTP 쿠키 - 위키백과, 우리 모두의 백과사전 - cookie 설명
  3. HTTP 쿠키 - HTTP | MDN - cookie 설명
  4. Path 와 Domain - cookie path 설명
  5. https://nsinc.tistory.com/121 - cookie secure 설명

댓글