반응형

 

To-Do 리스트 항목을 로컬 스토리지에 저장하고, 페이지 새로고침 후에도 할 일 목록이 유지되도록 기능을 추가하겠습니다.

이를 위해 ToDoList.vue 컴포넌트의 코드를 수정할 것입니다.

 

수정된 ToDoList.vue 코드

<template>
  <div>
    <h2>To-Do List</h2>
    <input v-model="newTodo" placeholder="Add a new to-do" @keyup.enter="addTodo" />
    <button @click="addTodo">Add</button>

    <ul>
      <li v-for="(todo, index) in todos" :key="index">
        <input type="checkbox" v-model="todo.completed" @change="saveTodos" />
        <span :class="{ completed: todo.completed }">{{ todo.text }}</span>
        <button @click="removeTodo(index)">Delete</button>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'ToDoList',
  data() {
    return {
      newTodo: '',
      todos: []
    };
  },
  mounted() {
    // 컴포넌트가 마운트될 때 로컬 스토리지에서 할 일 목록을 불러옵니다.
    const savedTodos = localStorage.getItem('todos');
    if (savedTodos) {
      this.todos = JSON.parse(savedTodos);
    }
  },
  methods: {
    addTodo() {
      if (this.newTodo.trim()) {
        this.todos.push({ text: this.newTodo, completed: false });
        this.newTodo = '';
        this.saveTodos(); // 새로운 할 일 추가 후 로컬 스토리지에 저장
      }
    },
    removeTodo(index) {
      this.todos.splice(index, 1);
      this.saveTodos(); // 할 일 삭제 후 로컬 스토리지에 저장
    },
    saveTodos() {
      // 현재 할 일 목록을 로컬 스토리지에 저장합니다.
      localStorage.setItem('todos', JSON.stringify(this.todos));
    }
  }
};
</script>

<style>
.completed {
  text-decoration: line-through;
  color: grey;
}
</style>

코드 설명

 

1. 로컬 스토리지에서 할 일 목록 불러오기:

mounted() 훅에서 컴포넌트가 마운트될 때 localStorage.getItem('todos')를 통해 로컬 스토리지에 저장된 할 일 목록을 불러옵니다.

만약 저장된 할 일 목록이 있으면, 이를 JSON으로 파싱하여 todos 배열에 할당합니다.

2. 할 일 목록 저장:

addTodoremoveTodo 메소드가 실행될 때, saveTodos() 메소드를 호출하여 현재 todos 배열을 로컬 스토리지에 저장합니다.

saveTodos() 메소드는 localStorage.setItem('todos', JSON.stringify(this.todos))를 통해 todos 배열을 문자열로 변환하여 로컬 스토리지에 저장합니다.

3. 할 일 완료 상태 변경 시 저장:

할 일의 체크박스를 클릭하여 완료 상태를 변경할 때도 saveTodos() 메소드를 호출하여 변경된 상태를 로컬 스토리지에 저장합니다.

 

 

 

개발자도구 > Application > Local storage > 도메인 > todos 에 데이터가 쌓인 걸 볼 수 있습니다. 


로컬스토리지란

로컬 스토리지는 웹 브라우저에서 제공하는 클라이언트 측 저장소입니다. 이를 통해 웹 애플리케이션은 사용자의 데이터를 클라이언트(브라우저) 측에 영구적으로 저장할 수 있습니다. 로컬 스토리지에 저장된 데이터는 브라우저를 닫거나 컴퓨터를 재부팅해도 유지됩니다.

 

로컬 스토리지의 특징

 

1. 키-값(Key-Value) 쌍으로 저장:

로컬 스토리지는 데이터를 키-값 쌍으로 저장합니다. 즉, 데이터에 접근할 때 특정 키를 사용하여 해당 값을 가져오거나 수정할 수 있습니다.

2. 영구 저장:

로컬 스토리지에 저장된 데이터는 사용자가 명시적으로 삭제하지 않는 한 영구적으로 저장됩니다. 쿠키와 달리 만료 시간이 없으며, 브라우저를 닫거나 컴퓨터를 재부팅해도 유지됩니다.

3. 도메인 별 저장:

로컬 스토리지는 도메인 단위로 데이터를 저장합니다. 이는 특정 웹사이트에서 저장된 데이터가 다른 도메인에서는 접근할 수 없음을 의미합니다.

4. 5MB 정도의 용량 제한:

대부분의 브라우저에서는 로컬 스토리지에 약 5MB 정도의 데이터를 저장할 수 있습니다. 이는 비교적 큰 용량으로, 텍스트 기반 데이터나 간단한 설정 값을 저장하는 데 충분합니다.

5. 동기적 접근:

로컬 스토리지는 동기적으로 동작합니다. 즉, 데이터를 저장하거나 불러올 때 해당 작업이 즉시 처리되며, 결과가 바로 반환됩니다.

 

로컬 스토리지 사용 방법

 

로컬 스토리지는 JavaScript를 통해 접근할 수 있으며, 다음과 같은 메서드를 사용합니다:




1. 데이터 저장:

localStorage.setItem(key, value)

예:

localStorage.setItem('username', 'JohnDoe');

2. 데이터 가져오기:

localStorage.getItem(key)

예:

const username = localStorage.getItem('username');
console.log(username); // 'JohnDoe'

3. 데이터 삭제:

특정 데이터 삭제: localStorage.removeItem(key)

모든 데이터 삭제: localStorage.clear()

예:

localStorage.removeItem('username');
localStorage.clear(); // 모든 데이터 삭제

4. 저장된 데이터 개수 확인:

localStorage.length

예:

const length = localStorage.length;
console.log(length);

 

로컬 스토리지의 활용 사례

 

사용자 설정 저장:

예를 들어, 웹사이트의 테마 설정이나 글꼴 크기 등의 개인 설정을 로컬 스토리지에 저장하여, 사용자가 브라우저를 닫았다가 다시 열어도 같은 설정을 유지할 수 있습니다.

간단한 데이터 캐싱:

네트워크 요청 결과를 로컬 스토리지에 저장하여, 동일한 데이터를 다시 요청할 필요 없이 빠르게 접근할 수 있습니다.

폼 데이터 임시 저장:

사용자가 폼을 작성하는 중에 브라우저를 닫거나 페이지를 떠났다가 돌아오더라도, 작성된 내용을 잃지 않도록 로컬 스토리지에 임시로 저장할 수 있습니다.

 

로컬 스토리지의 한계

 

보안 문제: 로컬 스토리지는 클라이언트 측에 저장되므로, 악의적인 사용자가 쉽게 접근할 수 있습니다. 따라서 민감한 정보(예: 비밀번호, 개인 정보)를 저장하는 데는 적합하지 않습니다.

용량 제한: 로컬 스토리지는 보통 5MB 정도의 용량 제한이 있습니다. 이 때문에 대용량 데이터를 저장하는 데는 적합하지 않습니다.

브라우저 호환성: 대부분의 현대 브라우저는 로컬 스토리지를 지원하지만, 매우 오래된 브라우저에서는 지원되지 않을 수 있습니다.




이전 블로그

https://juntcom.tistory.com/316

 

반응형
반응형

프론트에서 개발하다보면 api 중에 시간소요가 1초 이상 소요되어 화면에 랜더링 되기 전에 어떤 구성된 화면이 나왔으면 하는 순간이 있습니다.

왜냐하면 api 로 데이터를 받아올 때 까지 로딩되는 화면에는 아무런 리스트 화면도 보여주지 않으면, 사용자 입장에서 어색한 느낌이 있습니다.

이럴때 쓰는 로딩 방식보고 skeleton 로딩이라고 합니다.

vue 에 라이브러리가 있나 찾아보았는데, 라이브러리 보다 css 만으로도 처리가 가능한 리소스를 찾아 내용 정리합니다.

1. vue skeletonBox 소스

<template>
  <span
    :style="{ height, width: computedWidth }"
    class="SkeletonBox"
  />
</template>

<script>
export default {
  name: `SkeletonBox`,
  props: {
    maxWidth: {
      default: 100,
      type: Number
    },
    minWidth: {
      default: 80,
      type: Number
    },
    height: {
      default: `1em`,
      type: String
    },
    width: {
      default: null,
      type: String
    }
  },
  computed: {
    computedWidth () {
      return this.width || `${Math.floor((0.9 * (this.maxWidth - this.minWidth)) + this.minWidth)}%`
    }
  }
}
</script>

<style lang="scss">
.SkeletonBox {
  display: inline-block;
  position: relative;
  vertical-align: middle;
  overflow: hidden;
  background-color: #DDDBDD;
  &::after {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    transform: translateX(-100%);
    background-image: linear-gradient(
      90deg,
      rgba(#fff, 0) 0,
      rgba(#fff, 0.2) 20%,
      rgba(#fff, 0.5) 60%,
      rgba(#fff, 0)
    );
    animation: shimmer 5s infinite;
    content: '';
  }
  @keyframes shimmer {
    100% {
      transform: translateX(100%);
    }
  }
}
</style>

2. 사용예시

<template>
<table summary="샘플">
  <colgroup>
    <col style="width:200px"/>
    <col style="width:340px"/>
    <col style="width:150px"/>
    <col/>
  </colgroup>
<tbody>
  <template v-if="isFirstLoading">
    <tr>
      <th><skeleton-box/></th>
      <td colspan="3"> <skeleton-box /><skeleton-box/><skeleton-box/></td>
    </tr>
    <tr>
        <th><skeleton-box/></th>
        <td colspan="3"> <skeleton-box/><skeleton-box/><skeleton-box/></td>
    </tr>
    <tr>
        <th><skeleton-box/></th>
        <td colspan="3"> <skeleton-box/><skeleton-box/><skeleton-box/></td>
    </tr>
    <tr>
        <th><skeleton-box/></th>
        <td colspan="3"> <skeleton-box/><skeleton-box/><skeleton-box/></td>
    </tr>
  </template>
  <template v-for="listItem in list">
   <!-- list 내용 -->
  </template>
</tbody>
</template>

<script>
import SkeletonBox from '@/components/common/SkeletonBox'

export default {
  name: 'ModalAttribute',
  components: {
    SkeletonBox
  },
  data () {
    return {
      isFirstLoading: true,
      list: []
    }
  },
}

위 소스코드가 예시로 짠 소스코드입니다.

간단히 설명하자면, isFirstLoading 이 true 이면, skelecton 박스가 보이게 되는 처리입니다.

 

아래 참고문헌의 코드를 그대로 구현 한 내용이고 다른 위의 예시 소스와 다른 내용은 라인 넓이를 랜덤함수로 구현된 내용은 수정했습니다.

넓이와 세로 px 값을 넣어줄 수 있어, 별다른 npm 다운 없이 위 소스코드만 복붙해서 사용가능합니다.

 

참고

https://markus.oberlehner.net/blog/skeleton-loading-animation-with-vue/  [skeleton 화면 구성]

 

반응형

+ Recent posts