[WEB] Client Side Storage

Preview

웹 브라우저들은 다양한 위치에 사용자 데이터를 저장한다. 사용자가 가진 권한, 특성, 클라이언트 측 설정 값(팝업 허용 여부, 자동로그인 설정 여부) 등 여러가지 값들을 저장해 두고 웹 페이지 방문 및 필요할 떄마다 이용한다.

데이터가 보관되는 위치에 따라 보관 기간, 오프라인 사용 가능 여부가 다르다. 이 글은 클라이언트에 저장되는 데이터의 종류와 특징에 대해서 알아본다.

그리고 공격자의 입장에서 이러한 데이터를 안전하게 사용할 수 있는 방법은 있는지 알아본다.

Client-side storage?

먼저 웹은 정적(Static)과 동적(Dynamic)페이지로 구분한다. 정적 페이지는 단순 HTML 요청과 응답으로 구성되고, 동적 페이지는 사용자 요청 값을 포함한 다양한 값들을 가공, 랜더링하여 보여준다. 현대의 많은 웹 페이지들은 동적 페이지로 구성되어 있는 경우가 많다. 데이터는 서버측 데이터베이스에 저장되고 불러오는 구문(fetch)을 통해서 사용자에게 보여진다.
하지만, 동적 페이지를 사용할 때에 매번 사용자의 데이터를 반복해서 전송할 수는 없다. 많은 양의 데이터를 전송하게 되면 패킷의 낭비일 뿐더러 통신 속도 저하의 원인이 된다. 이처럼 민감도가 낮고 반복해서 전송되는 데이터들을 클라이언트에 저장하도록 해서 사용할 수 있다. 이 때 사용하는 것이 Client-side 저장소이다.

Client-side 저장소에는 많은 종류가 있으며, 비슷한 동작 과정을 가지지만 사용 방법이 다르다. client에서 자바스크립트 API를 이용하여 데이터를 저장하고, 가져올 수 있다. 저장되는 위치가 서버가 아닌 클라이언트의 브라우저라는 특징이 있다. 저장되는 데이터의 종류는 다음과 같다.

  • 사용자 개인의 사이트 설정(위젯 설정, 색상 설정, 폰트 크기 등)
  • 유지되어야할 사이트 활동 기록(이전 세션에서의 장바구니 목록, 이전에 사용자가 로그인했는지 기록)
  • 로컬에서 로드했을 때 더 빠르게 불러올 수 있는 데이터(리소스 파일-이미지, 영상, 폰트)
  • 오프라인에서 사용 가능하도록 생성한 문서

종종 서버측 데이터와 클라이언트 측 데이터가 함께 사용되기도 한다. 예를 들어 많은 양의 음악 파일을 다운받으려 할 때, 클라이언트 측 데이터베이스에 저장해 두고 재생할 때 새로 요청할 필요 없이 저장된 음악 파일을 이용해 듣기가 가능하다.

API를 이용하여 클라이언트에 데이터를 저장할때에는 용량 제한이 있다. 이 용량은 브라우저 설정과 사용자 설정에 따라 다양한데 (https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria) 에서 확인할 수 있다.

오래된 기술 - Cookies

Client-side 저장소에서 가장 흔하게 떠올릴 수 있는 것이 쿠키(Cookie)일 것이다. 쿠키는 말 그대로 과자 부스러기처럼 브라우저에 남아, 사용자의 특정하고 흔적을 남긴다. 웹이 도입되는 초기 부터 웹사이트들은 쿠키를 이용하여 사용자화된 데이터를 저장했다. 가장 사용된지 오래되고, 흔하게 사용되고 있다.
세션관리(Session Management), 사용자화(Personalization), 추적(Tracking)의 목적으로 사용하고 있다.

오래된 만큼 쿠키를 노리는 다양한 공격들도 발전해 왔는데 개발자가 민감정보(Id, Password, 권한 구분자, 연락처, 주민번호 등)를 쿠키에 포함하도록 한 경우 값을 탈취하거나 변조하는 공격에 취약하다.

  • 쿠키값으로 사용자와 관리자 권한을 구분하는 경우(ex> admin=1) 공격자는 참, 거짓 값을 유추하여 변조하여 권한을 상승시킬 수 있다.
  • XSS, CSRF 등 자바스크립트를 이용하여 피해자의 세션값을 탈취하거나 로그인한 피해자의 권한을 이용하여 특정 행위를 수행하도록 할 수 있다.

사용자 측의 데이터(Client-side)는 언제든지 변조가 가능하기 때문에 서버에서 처리할 때 절대로 신뢰해서는 안되며 추가 검증절차가 마련된 후 사용해야 안전하다.

간단한 데이터의 저장 - Web Storage

  • Web Storage API는 유저의 이름이나, 로그인 여부, 배경 색상 등 크기가 작은 데이터를 저장하거나 불러오는 기능을 제공한다.
  • 사용 방법도 쉽다. 이름/값 쌍을 이용하여 저장, 불러오기를 하면 된다.(입력할 수 있는 데이터의 형식에는 제한이 있다)

실습

  1. 브라우저 새 탭에서 Javascript 콘솔을 로드한다.
  2. web storage는 두 가지 객체 지향 저장소를 지원한다. sessionStorage는 브라우저를 사용하는 동안만 유지되는 데이터, localStorage는 브라우저 종료 후에도 유지되는 데이터를 저장할 수 있다. 실습에서는 사용용도가 더 많은 localStorage를 이용한다.
  3. Storage.setItem() 함수는 저장소에 데이터를 저장한다. 두 개의 파라미터를 필요로 하며 이름/값이다. 자바스크립트 콘솔에 아래와 같이 입력한다.
    /// localStorage.setItem('name','Chris');
  4. Storage.getItem() 함수는 입력받은 하나의 파라미터에 대해 값을 반환한다. 콘솔에 아래와 같이 입력한다.
    /// let myName = localStorage.getItem('name');
    /// myName
    두 번째 행을 입력했을 때, "name"에 해당하는 값을 확인할 수 있다.

이외에도 removeItem() 등 많은 메소드가 있으니 공식 문서를 통해 확인할 수 있다.

복잡한 데이터의 저장 - IndexedDB

  • IndexedDB API는 쿠키에 저장되는 데이터보다 복잡한 데이터를 저장하는 데 사용한다. 고객들의 정보일 수도 있고 여러 개로 구성된 오디오나 비디오 파일일 수도 있다.

IndexedDB는 거대한 양의 데이터(파일/블롭)을 저장할 수 있는 Client-side 저수준 API이다.

색인이 포함된 JSON 객체가 모여있는 트랜잭셔널 로컬데이터베이스를 위해 W3C가 2015년 1월 8일을 최종 버전으로 권고하였다.

자료를 빠르게 검색하고 인덱스할 수 있다. Web Storage가 적은 양의 데이터를 처리하는 데 강점이 있다면, 크기가 크고 구조화된 데이터를 처리할 때에는 IndexedDB가 유용하다.

특징은 다음과 같다.

  • 키(Key)-값(Value)로 데이터를 관리한다.
  • Transaction Model을 따르며 모든 변경은 Transaction 안에서 일어난다.
    = 만약 Transaction이 실패한 경우 모든 변경사항을 폐기하고 이전 상태로 돌아간다.
  • 비동기 방식의 API로 이루어져 있어 실행 완료 시 콜백함수를 전달해야 한다.
  • same-origin 정책을 따르기 때문에 다른 서브도메인이나 도메인에서 만든 DB에는 접근할 수 없다.

Creating Data

someObjectStore.add(data, optionalKey);

References

https://web.dev/indexeddb/
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage#storing_complex_data_%E2%80%94_indexeddb

반응형