뭉균의 개발일지

[CS지식] 쿠키 vs 로컬 스토리지, 무엇이 다를까? 본문

CS

[CS지식] 쿠키 vs 로컬 스토리지, 무엇이 다를까?

박뭉균 2024. 10. 26. 22:52

🚪 들어가며

 

프로젝트 진행 중 백엔드(서버)에서 토큰 값을 넘겨줄 때, 프론트엔드에서 토큰의 저장 방식을 결정해야 하는 상황이 발생했습니다. 이 경우에 쿠키 또는 로컬 스토리지에 토큰을 보관해야하는데 각각 어떤 상황에 사용해야하는 지 의문이 생겨 해당 부분을 공부하게 되었고 공부한 내용을 정리하기위해 이번 포스팅을 작성했습니다🖥️

 

 

📚 쿠키와 로컬 스토리지가 무엇인가?

 

🍪 쿠키(Cookie)

 

쿠키는 웹 서버에서 클라이언트(사용자의 브라우저)에 저장하는 작은 데이터 파일입니다. 웹사이트를 방문할 때 특정 정보를 클라이언트에 저장해두고, 이후 재방문 시 이 정보를 활용하여 사용자 경험을 맞춤화하거나 사용자의 로그인 상태를 유지하는 용도로 사용됩니다. 쿠키는 브라우저에 저장되며, 서버와 클라이언트 간의 HTTP 요청과 함께 전송되기 때문에, 서버 측에서 사용자를 식별하거나 세션을 유지하는 데도 활용됩니다.

  • 저장 용량: 최대 4KB로 매우 작으며, 주로 간단한 텍스트 데이터 저장에 적합합니다.
  • 유효 기간: 쿠키는 만료 날짜를 설정할 수 있습니다. 만료 날짜가 지정되면 쿠키는 영구 쿠키(persistent cookie)로 저장되며, 유효 기간이 없을 경우 브라우저나 탭이 닫힐 때 삭제되는 세션 쿠키(session cookie)로 저장됩니다.
  • 자동 전송: 쿠키는 웹 사이트의 HTTP 요청과 응답에 자동으로 포함되어 서버와 주고받기 때문에, 사용자의 로그인 상태를 유지하는 용도로 널리 사용됩니다. 그러나 이로 인해 데이터 전송이 추가되어 대역폭을 소모할 수 있습니다.
  • 주요 용도: 세션 유지, 사용자 맞춤 설정(예: 언어 설정), 쇼핑 카트 정보 저장 등에서 쓰입니다.

 

 🫙로컬 스토리지(LocalStorage)

로컬 스토리지는 HTML5에서 추가된 클라이언트 측 데이터 저장 방식으로, 웹 애플리케이션에서 데이터를 브라우저에 저장해두고 지속적으로 사용할 수 있습니다. 로컬 스토리지는 HTTP 요청에 포함되지 않고 브라우저 내부에만 저장되므로, 사용자 정보나 설정을 서버와 주고받지 않아도 되며, 더 많은 양의 데이터를 저장하는 데 적합합니다.

  • 저장 용량: 최대 5MB로 쿠키보다 큰 데이터를 저장할 수 있습니다. 이미지나 텍스트 같은 다양한 형식의 데이터를 저장할 수 있지만, 주로 문자열로 저장되므로 JavaScript 객체 형태로 저장할 때는 JSON으로 변환해야 합니다.
  • 유효 기간: 로컬 스토리지는 명시적으로 삭제하지 않는 한 영구적으로 저장되며, 브라우저를 닫아도 삭제되지 않습니다. 사용자가 수동으로 데이터를 삭제하거나 웹 애플리케이션에서 삭제하는 코드를 추가해야만 제거됩니다.
  • 자동 전송되지 않음: 로컬 스토리지에 저장된 데이터는 HTTP 요청 시 자동으로 전송되지 않기 때문에, 대역폭 낭비가 없습니다. 다만, 필요할 때 JavaScript를 통해 데이터를 호출하여 사용할 수 있습니다.
  • 주요 용도: 사용자 설정 유지, 오프라인 모드 지원, 긴 시간 동안 데이터 유지 등이 있으며, 데이터가 자주 바뀌지 않는 경우에 적합합니다.

 

 

📚 보안과 성능 관점

쿠키와 로컬 스토리지를 사용할 때 보안과 성능 관점에서 각기 다른 취약점을 고려해야 합니다.

 

📌 보안 측면 

 

쿠키는 서버와의 세션을 유지하기 위한 인증 정보를 담을 때 흔히 사용되지만, XSS(사이트 간 스크립팅) 및 CSRF(사이트 간 요청 위조) 공격에 취약할 수 있습니다. 특히 CSRF 공격에서 해커가 쿠키를 악용하여 사용자를 사칭할 가능성이 있어, Secure 및 HttpOnly 속성을 설정해 보안을 강화해야 합니다. 로컬 스토리지는 HTTP 요청과 무관하게 클라이언트에만 저장되므로 상대적으로 안전해 보일 수 있지만, 클라이언트 쪽에 민감한 정보를 저장할 경우 로컬 스토리지는 암호화가 불가능하기에 쿠키로 암호화하여 보호해야 합니다.

 

더보기

XSS는 사용자가 웹 애플리케이션에 악의적인 스크립트를 삽입할 수 있는 취약점입니다. 공격자가 이를 통해 사용자의 브라우저에서 악성 JavaScript 코드를 실행할 수 있습니다. 이 코드는 사용자의 세션 쿠키, 개인 정보 등을 탈취하거나, 사용자의 브라우저에 악성 행동을 수행할 수 있습니다.

 

CSRF는 사용자가 의도하지 않은 요청을 사용자의 세션을 통해 강제 실행하는 공격입니다. 사용자가 로그인된 상태에서 공격자의 사이트를 방문하면, 공격자가 사용자를 대신해 요청을 보내 피해를 줄 수 있습니다.

 

📌 성능 측면 

쿠키는 서버로 자동 전송되므로, 자주 업데이트되거나 큰 데이터를 담는 경우 대역폭 사용을 초과하게 되어 웹사이트 로딩 속도에 영향을 미칠 수 있습니다. 반면, 로컬 스토리지는 서버에 전송되지 않으므로 빠른 접근성로딩 속도를 유지할 수 있습니다. 따라서 자주 사용되며 클라이언트에서 즉시 접근 가능한 데이터에 적합합니다.

 

 

📝 예시 코드

 

저희 팀은 보안 설정을 위해 쿠키로 토큰을 관리하기로 결정했고 아래 코드는 프로젝트 수행 중 제가 작성한 로그인 호출 함수와 쿠키 설정하는 프록시 서버 코드입니다. 쿠키는 클라이언트에서 보안 설정이 불가능하여 따로 프록시 서버를 만들어 보안 설정 후, 다시 클라이언트에서 넘겨주게 설계했습니다. 

해당 코드는 email과 password를 request body로 담아, 서버에 로그인 요청을 하면 서버가 accessToken을 던져주고, 그 token을 쿠키로 만들고 보안 설정을 하여 클라이언트에 저장하도록 설계습니다. 

 

export const postSignIn = async ({email, password}) => {
  try {
    const res = await proxy.post("/api/auth/sign-in", {email, password});
    if (res.status >= 200 && res.status < 300) return res.data;
  } catch (err) {
    console.error("에러 메시지: ", err instanceof Error ? err.message : err);
  }
};
//api/auth/sign-in.ts

import { serialize } from "cookie";

import axiosInstance from "@/lib/api/axiosInstanceApi";
import { NextApiRequest, NextApiResponse } from "next";

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
  if (req.method === "POST") {
    try {
      const { email, password } = req.body;

      const response = await axiosInstance.post("/auth/sign-in", {
        email,
        password,
      });

      const token = response.data.accessToken;

      if (token) {
        // 토큰을 쿠키에 저장 (httpOnly, secure 설정)
        res.setHeader(
          "Set-Cookie",
          serialize("accessToken", token, {
            httpOnly: true, // 클라이언트에서 접근 불가
            sameSite: "lax",
            maxAge: 60 * 60 * 24, // 1일 동안 쿠키 유지
            path: "/", // 루트 경로에 쿠키 적용
            // secure
          })
        );

        return res.status(200).json({ message: "로그인 성공" });
      } else {
        return res.status(401).json({ message: "권한 없음" });
      }
    } catch (error) {
      return res.status(500).json({ message: "서버 오류" });
    }
  } else {
    res.status(405).json({ message: "허용되지 않은 접근 방법" });
  }
};

export default handler;

 

 

📚 상황별 선택 가이드

웹 애플리케이션의 다양한 상황에서 쿠키와 로컬 스토리지를 선택하는 방법은 다음과 같습니다.

 

  • 짧은 세션 유지가 필요한 경우, 예를 들어 사용자가 페이지를 이동할 때마다 인증이 필요한 경우, 쿠키가 더 적합합니다. 쿠키는 자동으로 서버로 전송되므로 사용자의 인증 세션을 유지하기 쉬워 로그인 상태 유지와 같은 상황에 유리합니다.
  • 오프라인 기능이 요구되는 경우 로컬 스토리지가 적합합니다. 로컬 스토리지는 네트워크 상태와 무관하게 저장되기 때문에, 네트워크 연결이 불안정한 환경에서도 사용자 설정이나 데이터를 유지할 수 있습니다. 로컬 스토리지는 브라우저 내에서 데이터 유지가 필요하거나 앱이 오프라인 환경에서도 동작할 수 있도록 하는데 적합합니다.
  • 데이터의 보안 수준이 중요한 경우, 쿠키와 로컬 스토리지의 사용 방식에 주의해야 합니다. 예를 들어 인증 토큰 등 민감한 정보를 저장할 때는 보안 취약성 문제를 고려하여 암호화와 보안 속성을 추가하는 등의 조치를 취해야 합니다.

 

📚 결론

  • 쿠키는 세션 관리, 사용자 인증 등의 단기적인 상태 관리에 유리하며, 로컬 스토리지는 클라이언트 측에서 대용량의 데이터를 장기적으로 저장하기에 적합합니다.
  • 상황에 따라 각기 다른 저장 방식을 적용하여 보안과 성능 문제를 최소화할 수 있습니다. 예를 들어 사용자 경험을 개선하기위해 두 방식을 혼합하는 방법도 있습니다.

 

 

⚒️ 참고 자료

1. https://medium.com/swlh/cookies-vs-localstorage-whats-the-difference-d99f0eb09b44

 

Cookies vs. LocalStorage: What’s the difference?

For a long time, cookies were the main way to store information about users visiting your app or website. They were used to record…

medium.com

 

2. https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies

 

HTTP 쿠키 - HTTP | MDN

HTTP 쿠키(웹 쿠키, 브라우저 쿠키)는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각입니다. 브라우저는 그 데이터 조각들을 저장해 놓았다가, 동일한 서버에 재 요청 시 저장된 데이

developer.mozilla.org