자바스크립트와 쿠키

자바스크립트와 쿠키

이 글에서는 자바스크립트와 쿠키에 대해 설명합니다.

쿠키의 기본, 읽기와 쓰기, 보안, 실제 예제까지 단계별로 자세히 설명하겠습니다.

YouTube Video

javascript-cookie.html
  1<!DOCTYPE html>
  2<html lang="en">
  3<head>
  4  <meta charset="UTF-8">
  5  <title>JavaScript &amp; HTML</title>
  6  <style>
  7    * {
  8        box-sizing: border-box;
  9    }
 10
 11    body {
 12        margin: 0;
 13        padding: 1em;
 14        padding-bottom: 10em;
 15        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 16        background-color: #f7f9fc;
 17        color: #333;
 18        line-height: 1.6;
 19    }
 20
 21    .container {
 22        max-width: 800px;
 23        margin: 0 auto;
 24        padding: 1em;
 25        background-color: #ffffff;
 26        border: 1px solid #ccc;
 27        border-radius: 10px;
 28        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
 29    }
 30
 31    .container-flex {
 32        display: flex;
 33        flex-wrap: wrap;
 34        gap: 2em;
 35        max-width: 1000px;
 36        margin: 0 auto;
 37        padding: 1em;
 38        background-color: #ffffff;
 39        border: 1px solid #ccc;
 40        border-radius: 10px;
 41        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
 42    }
 43
 44    .left-column, .right-column {
 45        flex: 1 1 200px;
 46        min-width: 200px;
 47    }
 48
 49    h1, h2 {
 50        font-size: 1.2rem;
 51        color: #007bff;
 52        margin-top: 0.5em;
 53        margin-bottom: 0.5em;
 54        border-left: 5px solid #007bff;
 55        padding-left: 0.6em;
 56        background-color: #e9f2ff;
 57    }
 58
 59    button {
 60        display: block;
 61        margin: 1em auto;
 62        padding: 0.75em 1.5em;
 63        font-size: 1rem;
 64        background-color: #007bff;
 65        color: white;
 66        border: none;
 67        border-radius: 6px;
 68        cursor: pointer;
 69        transition: background-color 0.3s ease;
 70    }
 71
 72    button:hover {
 73        background-color: #0056b3;
 74    }
 75
 76    #output {
 77        margin-top: 1em;
 78        background-color: #1e1e1e;
 79        color: #0f0;
 80        padding: 1em;
 81        border-radius: 8px;
 82        min-height: 200px;
 83        font-family: Consolas, monospace;
 84        font-size: 0.95rem;
 85        overflow-y: auto;
 86        white-space: pre-wrap;
 87    }
 88
 89    .highlight {
 90        outline: 3px solid #ffc107; /* yellow border */
 91        background-color: #fff8e1;  /* soft yellow background */
 92        transition: background-color 0.3s ease, outline 0.3s ease;
 93    }
 94
 95    .active {
 96        background-color: #28a745; /* green background */
 97        color: #fff;
 98        box-shadow: 0 0 10px rgba(40, 167, 69, 0.5);
 99        transition: background-color 0.3s ease, box-shadow 0.3s ease;
100    }
101  </style>
102</head>
103<body>
104    <div class="container">
105        <h1>JavaScript Console</h1>
106        <button id="executeBtn">Execute</button>
107        <div id="output"></div>
108    </div>
109
110    <script>
111        // Override console.log to display messages in the #output element
112        (function () {
113            // Override console.log
114            const originalLog = console.log;
115            console.log = function (...args) {
116                originalLog.apply(console, args);
117                const message = document.createElement('div');
118                message.textContent = args.map(String).join(' ');
119                output.appendChild(message);
120            };
121
122            // Override console.error
123            const originalError = console.error;
124            console.error = function (...args) {
125                originalError.apply(console, args);
126                const message = document.createElement('div');
127                message.textContent = args.map(String).join(' ');
128                message.style.color = 'red'; // Color error messages red
129                output.appendChild(message);
130            };
131        })();
132
133        document.getElementById('executeBtn').addEventListener('click', () => {
134            // Prevent multiple loads
135            if (document.getElementById('externalScript')) return;
136
137            const script = document.createElement('script');
138            script.src = 'javascript-cookie.js';
139            script.id = 'externalScript';
140            //script.onload = () => console.log('javascript-cookie.js loaded and executed.');
141            //script.onerror = () => console.log('Failed to load javascript-cookie.js.');
142            document.body.appendChild(script);
143        });
144    </script>
145</body>
146</html>

자바스크립트와 쿠키

쿠키사용자 브라우저에 저장되는 작은 데이터 조각을 의미합니다. 쿠키는 주로 다음과 같은 용도로 사용됩니다:.

  • 사용자 인증(로그인 상태 유지)
  • 사용자 설정 저장(언어, 테마 등)
  • 추적(브라우징 이력 등)

자바스크립트에서는 document.cookie를 사용하여 쿠키를 읽거나 쓸 수 있습니다.

쿠키 생성(쓰기)

쿠키는 다음과 같은 문법으로 생성됩니다:.

1document.cookie = "username=JohnDoe";
  • 이 코드는 브라우저에 "username=JohnDoe"라는 쿠키를 저장합니다.

만료 날짜가 있는 쿠키 생성하기

쿠키에는 만료 날짜를 설정할 수 있습니다. 만료 날짜를 설정하지 않으면 세션 쿠키로 간주되어 브라우저를 닫으면 삭제됩니다.

1const date = new Date();
2date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 days
3const cookieText = "username=JohnDoe; expires=" + date.toUTCString() + "; path=/; SameSite=None; Secure"
4document.cookie = cookieText;
5console.log(`Cookie Text  : ${cookieText}`);
6console.log(`Cookie Value : ${document.cookie}`);
  • expires 속성은 쿠키의 만료 날짜를 UTC 형식으로 지정합니다.
  • path 속성은 쿠키가 전송될 경로를 지정합니다. /는 사이트 전체를 의미합니다.
  • 만약 SameSite=None을 지정하면, 교차 사이트 요청에도 Cookie가 전송됩니다. 그러나 이 경우에는 반드시 Secure 속성을 항상 포함해야 합니다.
  • Secure 속성을 지정하면 Cookie가 HTTPS 통신에서만 전송되어 보안이 강화됩니다.
  • document.cookie를 참조하면 현재 페이지에서 사용 가능한 모든 Cookie를 문자열로 얻을 수 있습니다.
  • console.log를 사용하여 브라우저에 설정된 실제 Cookie 값과 가져올 수 있는 값의 차이를 확인할 수 있습니다.

쿠키 읽기

document.cookie로 모든 쿠키를 문자열로 가져올 수 있습니다.

1const date = new Date();
2date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 days
3document.cookie = "theme=dark; expires=" + date.toUTCString() + "; path=/; SameSite=None; Secure"
4
5console.log(document.cookie);
6// Output: "username=JohnDoe; theme=dark"
  • document.cookie의 반환값은 모든 Cookie가 'key=value;' 형식으로 연결된 하나의 문자열입니다.
  • 이 문자열을 파싱하고 원하는 값을 추출하는 함수를 사용하면 편리합니다.

쿠키의 값을 가져오는 함수

 1function getCookie(name) {
 2    const cookies = document.cookie.split('; ');
 3    for (const cookie of cookies) {
 4        const [key, value] = cookie.split('=');
 5        if (key === name) {
 6            return decodeURIComponent(value);
 7        }
 8    }
 9    return null;
10}
11
12console.log(getCookie("username")); // "JohnDoe"
  • 이 함수는 split()을 사용해 키와 값을 분리하고, 지정된 키와 일치하면 값을 반환합니다.
  • decodeURIComponent를 사용하면 인코딩된 문자를 올바르게 가져올 수 있습니다.
  • 해당 키가 존재하지 않으면 null을 반환합니다.

쿠키 삭제

쿠키의 만료 날짜를 과거로 설정하면 쿠키가 삭제됩니다.

1document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=None; Secure";
2
3console.log(document.cookie);
4// Output: "theme=dark"
  • username에 빈 값을 할당하고 만료일을 과거로 지정하면 삭제됩니다.
  • Cookie를 삭제할 때는 생성할 때 사용한 path, SameSite, Secure 속성도 일치시켜야 합니다.
  • 이 예시에서는 username이 삭제되고, theme=dark와 같은 다른 Cookie는 남아 있습니다.

쿠키 옵션

쿠키의 동작을 제어하기 위해 다양한 옵션을 지정할 수 있습니다. 주요 옵션은 다음과 같습니다:.

쿠키의 만료 날짜를 UTC 형식으로 지정합니다. 지정하지 않으면 세션 쿠키가 되어 브라우저를 닫으면 삭제됩니다.

쿠키의 만료 기간(초 단위)을 지정합니다. 이 값이 설정되어 있으면 `expires`보다 우선합니다.

쿠키가 전송될 경로를 지정합니다. 예를 들어 `/admin`을 지정하면 그 경로 이하의 페이지에서만 쿠키가 전송됩니다.

쿠키가 유효한 도메인을 지정합니다. 일반적으로 현재 도메인에 설정되지만, `.example.com`처럼 모든 하위 도메인에 적용할 수도 있습니다.

이 속성이 지정되면 쿠키는 HTTPS로만 전송됩니다. 보안 강화를 위해 중요한 정보에는 항상 이 속성을 설정하세요.

쿠키가 사이트 간 요청에서 전송되는지를 제어합니다. 다음 세 가지 값 중 하나를 지정할 수 있습니다:.

- `Strict`
    쿠키는 동일 사이트에서의 요청에만 전송됩니다.

- `Lax`
    일반적인 탐색에서는 쿠키가 전송되지만 일부 제한이 있습니다.

- `None`
    사이트 간 요청에서도 쿠키가 전송될 수 있습니다. 단, 이때는 `Secure` 속성도 함께 필요합니다.

예시: 보안 쿠키

1document.cookie = "sessionId=abc123; secure; SameSite=Strict";
  • secure를 지정하면 Cookie는 HTTPS 통신에서만 전송됩니다.
  • SameSite=Strict를 지정하면 교차 사이트 요청에는 Cookie가 전송되지 않아 CSRF 대책으로 효과적입니다.
  • 이러한 보안 속성은 인증이나 세션 관리를 위한 중요 Cookie에 필수적입니다.

인코딩과 디코딩

쿠키 값에 특수 문자가 포함될 수 있으므로 encodeURIComponent를 사용하는 것이 안전합니다.

1const date = new Date();
2date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 days
3
4const username = "JohnDoe";
5document.cookie =
6    "username=" + encodeURIComponent(username) +
7    "; max-age=604800; path=/; SameSite=None; Secure";
8
9console.log(decodeURIComponent(getCookie("username"))); // "JohnDoe"
  • encodeURIComponent를 사용하면 공백이나 기호 등도 안전하게 Cookie에 저장할 수 있습니다.
  • 읽어올 때는 decodeURIComponent를 사용해 원래 문자열로 되돌릴 수 있습니다.
  • 이 예시에서는 max-age=604800을 사용하여 만료 기간을 7일(604,800초)로 설정합니다. expires와 유사하게 만료일을 지정하는 방법입니다. max-age는 초 단위로 지정할 수 있어 더 간편하게 사용할 수 있습니다.

실용 예제: 테마 저장 및 불러오기

다음은 사용자가 선택한 테마를 쿠키에 저장하고 다음 방문 시 자동으로 적용하는 예제입니다.

 1function setTheme(theme) {
 2    document.cookie =
 3        "theme=" + encodeURIComponent(theme) +
 4        "; max-age=604800; path=/; SameSite=None; Secure"; // 1 week
 5    applyTheme(theme);
 6}
 7
 8function applyTheme(theme) {
 9    document.body.style.backgroundColor = theme === "dark" ? "#333" : "#fff";
10    document.body.style.color = theme === "dark" ? "#fff" : "#000";
11}
12
13function getCookie(name) {
14    const cookies = document.cookie.split('; ');
15    for (const cookie of cookies) {
16        const [key, value] = cookie.split('=');
17        if (key === name) {
18            return decodeURIComponent(value);
19        }
20    }
21    return null;
22}
23
24const savedTheme = getCookie("theme");
25if (savedTheme) {
26    applyTheme(savedTheme);
27}
1<button onclick="setTheme('light')">Light</button>
2<button onclick="setTheme('dark')">Dark</button>
  • setTheme 함수는 선택한 테마를 Cookie에 저장하고 즉시 applyTheme을 호출하여 화면을 업데이트합니다.
  • applyTheme 함수는 테마에 따라 body의 배경색과 텍스트 색상을 전환합니다.
  • 이 예시에서는 max-age=604800이 설정되어 테마 설정이 1주일 동안 유지됩니다.
  • 사용자가 페이지를 다시 방문해도 선택 사항이 유지되기 때문에 UX가 향상됩니다.

쿠키의 제한 사항 및 주의점

쿠키 사용 시 다음 점들에 주의하세요:.

  • 크기 제한 단일 쿠키의 크기는 약 4KB로 제한됩니다.

  • 저장 가능한 쿠키 개수 제한 브라우저에 따라 도메인별로 약 20~50개만 저장할 수 있습니다.

  • 보안 주의사항 Cookie의 내용은 기본적으로 평문으로 저장되므로, 비밀번호와 같은 기밀 정보를 저장하는 데 적합하지 않습니다.

  • JavaScript에서 접근할 수 없는 쿠키 HttpOnly 속성이 있는 Cookie는 보안상 JavaScript에서 읽을 수 없습니다.

서버와 Cookie

1Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict

HttpOnly와 같은 일부 Cookie 속성은 JavaScript로 설정할 수 없습니다. 이러한 속성들은 서버 측에서 설정해야 합니다.

요약

JavaScript로 Cookie를 조작하면 사용자 경험을 향상시키고 상태를 유지할 수 있습니다. 그러나 안전하고 적절하게 다루기 위해 다음 사항을 참고하세요.

  • 꼭 필요한 최소한의 정보만 저장하세요 개인정보 보호와 보안을 위해 개인적이거나 민감한 정보를 저장하지 않고, 필요한 데이터만 기록하세요.

  • 보안 속성을 올바르게 설정하세요 SecureSameSite와 같은 속성을 설정하여 XSS, CSRF와 같은 크로스 사이트 공격을 방지하세요.

  • 데이터 인코딩과 디코딩 encodeURIComponentdecodeURIComponent를 사용하여 쿠키 값을 안전하게 저장하고 읽음으로써 특수 문자와 일본어 등이 올바르게 처리되도록 하세요.

Cookie의 올바른 사용법을 배우면 더 발전되고 안전한 웹 애플리케이션을 구축할 수 있습니다.

위의 기사를 보면서 Visual Studio Code를 사용해 우리 유튜브 채널에서 함께 따라할 수 있습니다. 유튜브 채널도 확인해 주세요.

YouTube Video