💡 로컬스토리지는 웹 스토리지 객체로 브라우저 내에 { key : value } 형태로 오리진에 종속되어 저장되는 데이터
하나의 값만 저장됩니다.5MB입니다.localStorage.setItem(key, value); // 설정
localStorage.getItem(key); // key에 해당하는 value 가져오기
localStorage.removeItem(key); // 제거
localStorage.clear() // 전체 제거

origin443이기 때문에 ⇒ 생략 가능80 ⇒ 생략 가능💡 컨텐츠가 달라도 오리진만 같으면 로컬스토리지 공유 가능
header-authorization 헤더를 이용해서 서버에 전달을 함<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,
initial-scale=1.0">
<title>Document</title>
<style>
/* CSS */
.button-62 {
background: linear-gradient(to bottom right, #EF4765,
#FF9A5A);
border: 0;
border-radius: 12px;
color: #FFFFFF;
cursor: pointer;
display: inline-block;
font-family: -apple-system, system-ui, "Segoe UI",
Roboto, Helvetica, Arial, sans-serif;
font-size: 16px;
font-weight: 500;
line-height: 2.5;
outline: transparent;
padding: 0 1rem;
text-align: center;
text-decoration: none;
transition: box-shadow .2s ease-in-out;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
white-space: nowrap;
}
.button-62:not([disabled]):focus {
box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.5), -.125rem -.125rem 1rem rgba(239, 71, 101, 0.5), .125rem .125rem 1rem rgba(255, 154, 90, 0.5);
}
.button-62:not([disabled]):hover {
box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.5), -.125rem -.125rem 1rem rgba(239, 71, 101, 0.5), .125rem .125rem 1rem rgba(255, 154, 90, 0.5);
}
#field {
font-size: 27px;
}
body {
display: flex;
justify-content: center;
align-items: center;
margin: 0 auto;
height: 100vh;
}
</style>
</head>
<body>
<div>
<input type="text" id="field" />
<input type="button" class="button-62" value="검색" 89 id="save" />
<input type="button" class="button-62" value="조회" id="read" />
<input type="button" class="button-62" value="삭제" id="clear" />
</div>
</body>
<script>
window.onload = async () => {
const field = document.getElementById("field"),
save = document.getElementById("save"),
read = document.getElementById("read"),
clear = document.getElementById("clear")
save.addEventListener("click", e =>
localStorage.setItem("입력값", field.value))
read.addEventListener("click", e =>
alert(window.localStorage["입력값"]))
clear.addEventListener("click", e => {
window.localStorage.clear()
field.value = ""
})
if (window.localStorage["입력값"]) {
field.value = window.localStorage["입력값"]
}
}
</script>
</html>
세션 스토리지(session Storage)는 로컬 스토리지와 매우 유사합니다.
💡 세션 스토리지는 웹 스토리지 객체로 브라우저 내에 { key : value } 형태로 오리진에 종속되어 저장되는 데이터. (오리진이 같은 브라우저 내에서 공유 됩니다.)탭을 닫으면 데이터는 만료 됩니다.sessionStorage.setItem(key, value); // 설정
sessionStorage.getItem(key); // 탐색
sessionStorage.removeItem(key); // 제거
sessionStorage.clear() // 전체 제거
💡 브라우저에 저장된 데이터 조각
응답헤더로 Set-Cookie로 어떤 값을 설정해서 쿠키를 보내면 그 때 부터 클라이언트에서 요청헤더 Cookie에 설정되어 자동으로 서버에 전달되게 되고 브라우저에도 저장되게 됩니다.
axios.get(url, {
headers: {
Cookie: "cookie1=value; cookie2=value;
cookie3=value;"
}
}).then
| 세션쿠키 (Session Cookie) | 영구쿠기 (Persistent Cookie) |
|---|---|
| - 브라우저가 열려 있는 동안 유효함 | - 하드디스크에 유효기간 동안 저장됨 |
| - 서버를 이용하는 동안 사용자 정보를 유지하기 위해 사용됨 | - 사이트 재방문 시 사용자 정보를 기억하기 위해 사용됨 |
| 세션 | 세션 쿠키 | 세션 스토리지 | |
|---|---|---|---|
| 위치 | 서버 측에서 관리되는 상태 저장 방법 | 클라이언트 측에서 관리되는 쿠키의 일종 | 클라이언트 측 웹 스토리지 메커니즘 |
| 동작 방식 | 서버는 각 유저마다 고유한 세션을 생성하고, 클라이언트에 대한 세션 ID를 부여합니다. 이 세션 ID는 일반적으로 쿠키를 통해 클라이언트에게 전달됩니다. | 보통 세션 ID와 같은 정보가 쿠키에 저장되어, 클라이언트가 해당 ID를 서버에 전달하면 서버는 해당 세션과 관련된 데이터를 찾아 사용 | 클라이언트의 브라우저 내부에 데이터를 저장합니다. 같은 도메인과 프로토콜을 가진 페이지 간에 데이터를 공유 |
| 수명 | 일반적으로 유저의 활동 동안 유지되며, 서버가 일정 기간 동안 세션 데이터를 보관할 수 있습니다. | 브라우저 세션이 끝날 때(브라우저 종료 시) 쿠키가 삭제 | 해당 페이지의 세션이 유지되는 동안 데이터가 유지 |
| 보안 | 주로 서버 측에서 데이터를 관리하므로 보안 측면에서 더 안전합니다. 중요한 정보나 인증 데이터를 저장 | 서버 측 세션보다는 보안적으로 약간 취약 (클라이언트가 직접 관리) | 서버 측 세션보다는 약간 취약합니다. 중요한 정보를 저장하는 데는 적합하지 않음 |
웹 사이트의 속도 저하 문제도 일으킬 수 있기 때문이다.지워지고 조작되고 가로채이더라도 문제 없을 정보만 쿠키로 사용되고
중요한 보안과 관련된 정보 등은 세션을 통해 서버에서 다뤄지는 것이다.
빈번한 새로고침이나 페이지 이동을 감지하고 세션을 보호하기 위해 세션을 만료시키는 경우도 있을 수 있습니다.˙ 자바스크립트를 이용하여 document.cookie 값을 탈취할 수 있음
˙ 네트워크를 통해 전송되는 쿠키값을 암호화하지 않고 전송하는 경우 네트워크 스니핑 공격을 통해 쿠키값을 탈취할 수 있음
˙ 영속성 쿠키는 하드디스크에 저장되며, 간단한 방법으로 접근 가능하기 때문에 공용PC 사용시 PC에 저장된 사용자 정보가 유출될 수 있음
Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
이 사양을 현재는 무시합니다.const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
// 쿠키 설정 Secure 옵션으로
res.setHeader('Set-Cookie', ['kundol = amumu; httponly',
'loltier = master; Secure']);
res.end('큰돌, 그는 신인가?!\n');
});
server.listen(port, hostname, () => {
console.log(Server running at < http: //$>{hostname}:${port}/);
});cookie에 세션ID를 담을 때 이 세션ID기반으로 클라이언트의 개인정보를 유추할 수 없게 해야 합니다.
자바스크립트로는 파악할 수 없게 http only 옵션을 걸어야 합니다.
일정시간의 세션 타임아웃 걸어야 합니다.
업비트의 세션타임아웃으로 공격자의 접근을 차단할 수 있다.

실수로 로그인을 하고 떠나더라도 자동으로 로그아웃 되기 때문에 안전
사용자의 데이터 간접수집에 해당하며 거기에 해당하는 KISA 지침을 준수해야 하기 때문입니다.정보보호 및 개인정보보호 관리체계(ISMS-P) 인증기준(KISA) 2019.01
3.1.5 간접수집 보호조치
정보주체(이용자) 이외로부터 개인정보를 수집하거나 제공받는 경우에는 업무에 필요한 최소한의 개인정보만 수집 ․ 이용하여야 하고 법령에 근거하거나 정보주체(이용자)의요구가 있으면 개인정보의 수집 출처, 처리목적, 처리정지의 요구권리를 알려야 한다.
서비스 계약 이행을 위해 필요한 경우로서 사업자가 서비스 제공과정에서 자동수집장치 등에
의해 수집 ․ 생성되는 개인정보(통화기록, 접속로그, 결제기록, 이용내역 등)에 대해서도,
해당 서비스의 계약 이행 및 제공을 위해 필요한 최소한의 개인정보만을 수집하여야 한다.
▶ 다만, 서비스 제공 계약 이행과는 무관한 목적으로 이용하기 위해 수집하는 경우에는 선택 동의 항목으로 분류하여 별도의 사전 동의를 받아야 함 (예를 들어, 쿠키를 통해 수집하는 행태정보를 분석하여 개인별 맞춤형 광고에 활용하는 경우 등)
| 쿠키 | 로컬 스토리지 | 세션 스토리지 | |
|---|---|---|---|
| 최대저장용량 | 4KB | 5MB | 5MB |
| 브라우저 허용 | HTML4 + 5 | HTML 5 | HTML 5 |
| 접근 범위 | 창 | 창 | 탭 |
| 만료 기한 | 수동으로 설정 | 영구적 | 탭 닫으면 소멸 |
| 설정할 수 있는 주체 | 클라이언트 + 서버 | 클라이언트 | 클라이언트 |
| 요청과 함께 서버에 자동전송 유무 | O | X | X |
출처 : 인프런 CS 지식의 정석