전체 목록
브라우저Easy#098

localStorage, sessionStorage, Cookie의 차이점을 설명해주세요.

#브라우저#웹스토리지#Cookie#보안

답변 포인트

저장 용량, 만료 시간, 서버 전송 여부를 기준으로 비교해보세요.

정답 및 해설

빠른 요약

localStorage: - 만료 없음 (직접 삭제 전까지 유지) - 약 5~10MB 저장 가능 - 같은 출처 내 모든 탭/윈도우 공유 - 서버에 자동 전송 안 됨 sessionStorage: - 탭/윈도우 종료 시 삭제 - 약 5~10MB - 같은 탭 내에서만 유지 - 서버에 자동 전송 안 됨 Cookie: - 만료 시간 설정 가능 - 약 4KB (매우 작음) - HTTP 요청마다 자동으로 서버에 전송 - HttpOnly, Secure, SameSite 등 보안 옵션 제공 - 주로 인증 토큰, 세션 ID 저장에 사용

웹 브라우저에서 클라이언트 측 데이터를 저장하는 방법으로 localStorage, sessionStorage, Cookie 세 가지가 있습니다. 모두 브라우저에 데이터를 저장하지만 저장 수명, 용량, 서버 전송 여부, 보안 옵션 등에서 중요한 차이가 있습니다. 사용 목적에 따라 적절한 저장소를 선택해야 합니다.

한눈에 비교

특성localStoragesessionStorageCookie
저장 수명영구 (직접 삭제 전까지)탭/세션 종료 시 삭제만료일 설정 가능
저장 용량5~10MB5~10MB4KB
서버 전송자동 전송 안 됨자동 전송 안 됨HTTP 요청마다 자동 전송
탭 간 공유같은 출처 모든 탭 공유같은 탭 내에서만같은 출처 모든 탭 공유
접근 방법JavaScriptJavaScriptJavaScript, HTTP 헤더
보안 옵션없음없음HttpOnly, Secure, SameSite

localStorage

기본 사용법

JavaScript
// 데이터 저장 (문자열만 저장 가능)
localStorage.setItem('theme', 'dark');
localStorage.setItem('language', 'ko');

// 객체 저장 (JSON.stringify 필요)
const userSettings = { fontSize: 16, theme: 'dark', notifications: true };
localStorage.setItem('settings', JSON.stringify(userSettings));

// 데이터 읽기
const theme = localStorage.getItem('theme');  // 'dark'
const settings = JSON.parse(localStorage.getItem('settings'));

// 데이터 삭제
localStorage.removeItem('theme');

// 전체 삭제
localStorage.clear();

// 저장된 항목 수 확인
console.log(localStorage.length);

// 모든 키 순회
for (let i = 0; i < localStorage.length; i++) {
  const key = localStorage.key(i);
  console.log(key, localStorage.getItem(key));
}

특징 및 사용 사례

JavaScript
// 특징 1: 만료 없이 영구 저장
// 사용자가 직접 삭제하거나 코드로 삭제하기 전까지 유지

// 특징 2: 같은 출처(origin)의 모든 탭/윈도우에서 공유
// origin = protocol + hostname + port
// https://example.com 의 모든 탭은 localStorage 공유

// 특징 3: storage 이벤트 - 다른 탭에서 변경 시 감지 가능
window.addEventListener('storage', (event) => {
  console.log('다른 탭에서 변경:', event.key, event.newValue);
  if (event.key === 'theme') {
    applyTheme(event.newValue);  // 다른 탭의 테마 변경을 이 탭에도 반영
  }
});

// ✅ 적합한 사용 사례:
// - 사용자 설정 (테마, 언어, 폰트 크기)
// - 비로그인 사용자의 장바구니
// - 최근 본 항목
// - 게임 점수/진행 상황
// - 초안 자동 저장

주의사항

JavaScript
// ❌ 민감한 정보 저장 금지 (XSS 공격에 취약)
localStorage.setItem('accessToken', 'bearer-token...');  // 위험!
localStorage.setItem('password', '...');                  // 절대 금지!

// localStorage는 JavaScript로 직접 접근 가능
// XSS 공격 시 공격자가 모든 데이터를 읽을 수 있음
document.cookie;  // HttpOnly 쿠키는 접근 불가
localStorage.getItem('accessToken');  // 항상 접근 가능 → 위험

// 저장 공간 부족 시 예외 처리
try {
  localStorage.setItem('largeData', bigData);
} catch (e) {
  if (e.name === 'QuotaExceededError') {
    console.error('저장 공간이 부족합니다.');
    // 오래된 데이터 삭제 후 재시도
  }
}

sessionStorage

기본 사용법

JavaScript
// API는 localStorage와 동일
sessionStorage.setItem('currentStep', '2');
sessionStorage.setItem('formData', JSON.stringify({ name: 'Alice', email: '...' }));

const step = sessionStorage.getItem('currentStep');
sessionStorage.removeItem('currentStep');
sessionStorage.clear();

특징 및 사용 사례

JavaScript
// 특징 1: 탭/윈도우를 닫으면 자동 삭제
// 새로고침은 삭제 안 됨, 탭 닫기/브라우저 종료 시 삭제

// 특징 2: 같은 탭 안에서만 공유
// 같은 URL을 새 탭에서 열면 별개의 sessionStorage

// 예시: 두 탭에서 같은 사이트 접속
// 탭1.sessionStorage !== 탭2.sessionStorage  ← 완전히 독립적
// 탭1.localStorage === 탭2.localStorage      ← 공유됨

// ✅ 적합한 사용 사례:
// - 다단계 폼 임시 데이터 (결제, 회원가입 등)
// - 로그인 세션 중 임시 상태 (뒤로가기 방지)
// - 검색 필터 임시 저장 (탭 종료 시 초기화 원하는 경우)
// - 일회성 안내 팝업 표시 여부

// 다단계 폼 예시
function saveFormStep(stepData) {
  const allData = JSON.parse(sessionStorage.getItem('checkoutData') || '{}');
  Object.assign(allData, stepData);
  sessionStorage.setItem('checkoutData', JSON.stringify(allData));
}

// 탭이 닫히면 자동으로 폼 데이터 삭제 → 개인정보 보호

Cookie

기본 사용법

JavaScript
// JavaScript로 쿠키 설정
document.cookie = 'username=alice';
document.cookie = 'theme=dark; expires=Fri, 31 Dec 2024 23:59:59 GMT; path=/';
document.cookie = 'sessionId=abc123; max-age=3600; path=/; secure; samesite=lax';

// 쿠키 읽기 (모든 쿠키를 하나의 문자열로 반환)
console.log(document.cookie);  // "username=alice; theme=dark"

// HttpOnly 쿠키는 JavaScript로 접근 불가
// → 서버에서만 설정/읽기 가능

// 쿠키 삭제 (만료 날짜를 과거로 설정)
document.cookie = 'username=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
HTTP
// HTTP 응답 헤더로 서버에서 쿠키 설정
Set-Cookie: sessionId=xyz789; HttpOnly; Secure; SameSite=Strict; Max-Age=3600; Path=/
Set-Cookie: refreshToken=abc; HttpOnly; Secure; SameSite=Strict; Max-Age=604800; Path=/auth
Set-Cookie: preferences=dark-mode; SameSite=Lax; Max-Age=31536000; Path=/

쿠키 속성

브라우저
Expires / Max-Age:   
  Expires=        
  Max-Age=             ( )
            (   )

Path:   
  Path=/              ()
  Path=/api        /api   

Domain:   
  Domain=example.com   example.com  
                   ( )

Secure: HTTPS  
   HTTP   

HttpOnly: JavaScript  
   document.cookie / 
   XSS   

SameSite: CSRF  
  SameSite=Strict      
  SameSite=Lax        +      ()
  SameSite=None          (Secure )

쿠키 보안 속성 실무 활용

JavaScript
// 서버에서 인증 토큰 설정 (Node.js Express)
app.post('/auth/login', async (req, res) => {
  const { email, password } = req.body;
  const user = await authenticate(email, password);

  if (user) {
    const accessToken = generateAccessToken(user);
    const refreshToken = generateRefreshToken(user);

    // ✅ HttpOnly + Secure + SameSite로 토큰 보안 강화
    res.cookie('accessToken', accessToken, {
      httpOnly: true,      // XSS 방지
      secure: true,        // HTTPS만
      sameSite: 'strict',  // CSRF 방지
      maxAge: 15 * 60 * 1000,  // 15분
      path: '/'
    });

    res.cookie('refreshToken', refreshToken, {
      httpOnly: true,
      secure: true,
      sameSite: 'strict',
      maxAge: 7 * 24 * 60 * 60 * 1000,  // 7일
      path: '/auth/refresh'  // 갱신 엔드포인트에서만 전송
    });

    res.json({ success: true });
  }
});

쿠키 vs 토큰 인증

브라우저
localStorage JWT  :
 XSS   
 CSRF  
    

HttpOnly Cookie JWT  :
 XSS  
 SameSite  CSRF 
    
   (  )

Web Storage API의 한계와 대안

JavaScript
// localStorage/sessionStorage는 동기적 API → 대용량 처리 시 성능 문제
// 대안: IndexedDB - 비동기, 대용량 구조화 데이터 저장

// IndexedDB 예시
const request = indexedDB.open('myDatabase', 1);

request.onsuccess = (event) => {
  const db = event.target.result;
  const transaction = db.transaction(['users'], 'readwrite');
  const store = transaction.objectStore('users');
  store.add({ id: 1, name: 'Alice', email: 'alice@example.com' });
};

언제 무엇을 사용할까?

브라우저
 / :
 HttpOnly Cookie  (XSS, CSRF )

  (, ):
 localStorage  ( ,   )

   :
 sessionStorage  (    )

   :
 Cookie  (HTTP   )

  ( ):
 IndexedDB  ( MB  )

정리

항목localStoragesessionStorageCookie
수명영구 (수동 삭제까지)탭 닫으면 삭제설정 가능 (없으면 세션)
용량5~10MB5~10MB4KB
서버 전송없음없음매 요청마다 자동 전송
탭 간 공유공유됨탭마다 독립공유됨
JS 접근가능가능HttpOnly 시 불가
보안 옵션없음없음HttpOnly, Secure, SameSite
주요 용도사용자 설정, 장바구니폼 임시 저장인증 토큰, 세션 관리

핵심: 인증 토큰은 XSS 방지를 위해 HttpOnly Cookie에 저장하고, 사용자 환경설정은 localStorage에, 임시 폼 데이터는 sessionStorage에 저장하는 것이 권장 패턴입니다.

관련 질문

같은 카테고리/태그 기준