본문 바로가기
개발/Next.js

[Next] localstorage를 사용하는 방법 #1

by 핸디(Handy) 2022. 1. 28.

localStorage 란?

웹 스토리지 객체(web storage object)의 한 종류로 sessionStorage와 함께 브라우내 내에 key-vale 쌍을 저장할 수 있도록 해주는 Web API입니다.

 

Window.localStorage - Web API | MDN

localStorage 읽기 전용 속성을 사용하면 Document 출처의 Storage 객체에 접근할 수 있습니다. 저장한 데이터는 브라우저 세션 간에 공유됩니다.

developer.mozilla.org

Why web storage | 영속성

web storage를 쓰는 가장 큰 이유는 영속성에 있습니다. localStorage는 브라우저가 다시 실행되어도 데이터가 사리지지 않고 남아있습니다.

sessionStorage는 어떻냐구요? sessionStorage는 페이지를 새로 고침까지만 데이터를 보장해줍니다.

그러니 이 둘을 적절히 사용하면 데이터들을 유지한데 UX 경험을 향상시킬수 있습니다. 

여기서 말하는 UX 경험이란 자동로그인, 오프라인 동작 등을 의미하는 것입니다.

Web storage vs Cookie

Cookie(쿠키)를 사용하면 브라우저에 데이터를 저장할 수 있는데 왜 web storage라는 별개의 기술을 쓰느냐구요?

잠깐 쿠키에 대해서도 간략하게 살펴보겠습니다.

일반적인 쿠키 표준안인 RFC 2965 에 따르면 쿠키 지원을 위해 브라우저는 다음의 요건을 충족해야 한다고 합니다.

  • 4,096바이트 크기의 쿠키를 지원할 것
  • 한 도메인 당 최소 50개 쿠키를 지원할 것(예: 각 웹사이트 당)
  • 총 최소 3,000개 쿠키를 지원할 것.

요건을 보면 어떻게 떨어르시나요? 저는 갯수는 괜찮은데 용량쪽에 좀더 눈이 가더라구요.

4,096바이트 == 4KB, 너무 작아요. 그래서 용량이 상대적으로 큰 Web storage를 씁니다. 용량 자체도 4KB만 지원하는 쿠키와 달리 2MB 이상의 용량을 지원합니다.( 세부적인 수치는 브라우저마다 달라요)

Web storage는 도메인, 프로토콜, 포트로 정의되는 오리진에 종속되어있습니다. 따라서 이게 다르면 해당 데이터에 접근할수가 없습니다. 그래서 상대적으로 보안도 되고 신뢰성도 보장할 수 있습니다.

localStorage 의 사용법

localStorage의 사용법이라고 했지만 sessionStorage도  동일한 메서드와 프로퍼티를 제공합니다. 

각각의 메서드와 프로퍼티에 대한 설명은 다른 곳에서도 많으니 간략히 적기만 하고 넘어가봅시다.

  • setItem(key, value) – 키-값 쌍을 보관합니다.
  • getItem(key) – 키에 해당하는 값을 받아옵니다.
  • removeItem(key) – 키와 해당 값을 삭제합니다.
  • clear() – 모든 것을 삭제합니다.
  • key(index) – 인덱스(index)에 해당하는 키를 받아옵니다.
  • length – 저장된 항목의 개수를 얻습니다.

 

Next 안에서의 localStorage

오늘 글의 핵심부분인데 잡론이 너무 길었네요. ㅎㅎ 일단 Next 안에서 localStorage를 써보도록 해요.

코드를 재실행하는 순간 testkey로 값이 생기는 것을 확인할수 있습니다.

 

기본적인 사용법 2가지

그러면 이제 글을 마무리할수 있을까 싶은데요. 꼭 그렇지많은 않습니다.

왜냐하면 Next는 무조건 브라우저에서만 실행되는게 아니기 때문입니다. SSG, ISG로 인해 노드환경상에서도 쓰일수가 있기 때문에 체크가 필요합니다.

webStorage는 window의 객체입니다. 근데 window는 브라우저에 있는 글로벌객체입니다. 그래서 

간혹 쓰시다 보면 ReferenceError: localStorage is not defined를 만나게 됩니다.

이때 우회방법은 제가 찾아본 결과본 결과 크게 2가지가 있습니다.

useEffect 내부에서 사용 

이 방법은 React 스러운 해결책입니다.

useEffect는 CSR 전용 훅(마운트 되었을때 실행)이기 때문에 브라우저라는 확신을 줄 수 있게 됩니다. 그래서 not defined라는 에러 걱정없이 사용할 수 있습니다.

  useEffect(() => {
    const result = localStorage.getItem('testKey')
  }, [])

Class로 만들어서 사용

이 방식은 제가 사용하고 있는 방법으로 LocalStorage라는 클래스를 만드는 방식입니다.
그렇지 않다면 매번 if문을 통해 확인을 해야하는 불편함이 있기 때문이죠.

다만 모든 storage 메소드가 필요한게 아니라 필요한것만 만들어서 사용하고 있습니다.

class LocalStorage {
  constructor() {}

  static setItem(key: string, item: string) {
    if (typeof window !== "undefined") {
      localStorage.setItem(key, item);
    }
  }

  static getItem(key: string) {
    if (typeof window !== "undefined") {
      return localStorage.getItem(key);
    }
    return null;
  }

  static removeItem(key: string) {
    if (typeof window !== "undefined") {
      localStorage.removeItem(key);
    }
  }
}

export default LocalStorage;

이렇게 클래스로 만든다음에 아래와 같이 쓰고 있습니다.

localStorage 의 몰락

이제 Next에서도 localStorage를 쓰는데 아무 문제가 없게 되었습니다.

하지만 여기서 마무리하지 말고 한걸음 더 나아가보겠습니다.

일단 글을 하나 추천해드리고 싶어요.

 

Randall Degges - Please Stop Using Local Storage

Seriously. Just stop it already. I don’t know what it is, exactly, that drives so many developers to store session information in local storage, but whatever the reason: the practice needs to die out. Things are getting completely out of hand. Almost eve

www.rdegges.com

 

localStorage 의 단점

위에 글도 읽어보고 다른 자료도 찾아보시면 localStorage를 쓰지 말라는 말을 많이 듣게 됩니다.

저도 사용할땐 이것만큼 편한게 없다고 생각했는데 그렇지 않나봐요. 

이제 단점을 하나씩 살펴보겠습니다.

단점 1 | 열려있는 데이터

일단 localStorage에 있는 모든 데이터는 볼 수 있습니다. 그래서 중요한 보안이 필요한 데이터를 그대로 때려박는건 아주 위험한 행위입니다. 또한 자바스크립트를 통해 가져갈수 있는 데이터이기 때문에 수집되어선 안되는 데이터도 들고있으면 안됩니다.

단점 2 | 문자열만 가능한 데이터

바스크립트를 통해 위에서 key와 value로 이뤄진 데이터셋이라고 했는데 value에는 문자열밖에 안들어갑니다. 그래서 일반적으로 JSON.stringfy 와 JSON.parse를 통해 문자열 <> 객체를 변환하며 사용합니다.

근데 이런 변환과정의 효율이 생각보다 좋지 않습니다. 물론 간단한 문자열이라면 상관없지만 오프라인동작을 위해 큰 데이터를 변환하고 또 빈번하게 잃어난다면 당연히 성능상의 저하를 일으킵니다.

localStorage 의 대안

대안 1 | IndexedDB

그래서 web storage 모두 더 괜찮은 web api가 등장하게 되었습니다.

아직 많이들 사용하지 않는듯 합니다. 저 또한 아직 사용해본적은 없는 web 기술이기도 해요.

일단 MDN 문서에는 아래와 같이 표현하고 있습니다.

 

IndexedDB 사용하기 - Web API | MDN

IndexedDB는 사용자의 브라우저에 데이터를 영구적으로 저장할 수 있는 방법 중 하나입니다. IndexedDB를 사용하여 네트워크 상태에 상관없이 풍부한 쿼리 기능을 이용할 수 있는 웹 어플리케이션을

developer.mozilla.org

다만 이것도 살펴보니 똑같이 window 객체의 값이니 위에 훅이든 클래스로 묶는 과정이 필요하긴 하겠네요.

대안 2 | Cache API(서비스 워커의 일부)

위에서 localStroage가 영속성을 위해 사용되고 또 이를 통해 오프라인 동작을 하는 캐시에도 사용된다고 말씀드렸습니다.

cache api는 해당 이슈에 대응되는 web 기술입니다. 

도메인별로 여러개의 cache 객체을 들고 service worker가 제어하고 실행을 합니다. 하지만 이부분은 저도 아직 제대로 써보지 않아 추후에 프로젝트에 도입을 한 다음에 추가해보도록 하겠습니다.

 

Cache - Web API | MDN

Cache 인터페이스는 ServiceWorker 의 생명주기의 일부로 캐시 된 Request와 Response를 나타냅니다.

developer.mozilla.org

 

 

댓글