웹 애플리케이션이 점점 더 복잡해지고 풍부한 기능을 요구하면서, 클라이언트 측 데이터 저장소의 중요성이 커지고 있습니다. 로컬 스토리지(LocalStorage)나 세션 스토리지(SessionStorage) 같은 간단한 저장소는 비교적 적은 용량의 데이터를 다루기에 적합하지만, 대규모 데이터를 처리하거나 복잡한 데이터 구조를 저장해야 하는 경우에는 적합하지 않습니다. 이때 사용하기 좋은 기술이 바로 IndexedDB입니다.
IndexedDB는 브라우저에 내장된 비관계형 데이터베이스로, 대용량 데이터 저장과 고성능 쿼리를 지원합니다. 오늘은 React 애플리케이션에서 IndexedDB를 사용하는 방법을 상세히 살펴보겠습니다.
IndexedDB란 무엇인가?
IndexedDB는 브라우저 내에서 동작하는 키-값 기반의 데이터베이스로, 다음과 같은 특징을 가지고 있습니다:
- 대용량 데이터 지원: 로컬 스토리지의 5MB 제한과 달리, IndexedDB는 수백 메가바이트에서 기가바이트 단위의 데이터도 저장할 수 있습니다.
- 비동기 작업: IndexedDB는 비동기 API를 제공하여 성능 저하 없이 데이터를 읽고 쓸 수 있습니다.
- 구조화된 데이터 저장: 단순한 문자열이 아닌 객체 같은 복잡한 데이터 구조를 저장할 수 있습니다.
- 트랜잭션 지원: 데이터베이스 작업의 원자성을 보장합니다.
- 인덱스와 키 범위 쿼리: 데이터를 효율적으로 검색할 수 있는 기능을 제공합니다.
React에서 IndexedDB 사용 방법
React에서 IndexedDB를 사용하기 위해 순수 JavaScript API를 활용할 수도 있지만, 이는 다소 복잡하고 코드의 가독성을 떨어뜨릴 수 있습니다. 따라서 idb와 같은 라이브러리를 사용하면 개발 생산성을 높이고 코드 유지보수를 용이하게 할 수 있습니다.
필수 라이브러리 설치
먼저 idb 라이브러리를 설치합니다. 이 라이브러리는 IndexedDB의 비동기 API를 간단하게 래핑한 유틸리티입니다.
npm install idb
데이터베이스 초기화
IndexedDB를 사용하려면 먼저 데이터베이스를 생성하고 테이블에 해당하는 **오브젝트 스토어(Object Store)**를 정의해야 합니다. 아래는 데이터베이스 초기화 예제입니다:
import { openDB } from 'idb';
const initDB = async () => {
const db = await openDB('MyDatabase', 1, {
upgrade(db) {
if (!db.objectStoreNames.contains('tasks')) {
db.createObjectStore('tasks', { keyPath: 'id', autoIncrement: true });
}
},
});
return db;
};
export default initDB;
위 코드에서 openDB 함수는 데이터베이스를 열거나 초기화합니다. upgrade 콜백은 데이터베이스 버전이 변경될 때 실행되며, 여기에서 필요한 오브젝트 스토어를 생성합니다.
데이터 삽입
IndexedDB에 데이터를 삽입하려면 add 메서드를 사용합니다.
import initDB from './initDB';
const addTask = async (task) => {
const db = await initDB();
const tx = db.transaction('tasks', 'readwrite');
const store = tx.objectStore('tasks');
await store.add(task);
await tx.done;
console.log('Task added successfully');
};
export default addTask;
여기서 transaction은 데이터베이스 작업 단위를 정의하며, readwrite 모드는 데이터를 읽고 쓸 수 있도록 설정합니다.
데이터 읽기
저장된 데이터를 읽으려면 getAll 메서드를 사용합니다:
const getAllTasks = async () => {
const db = await initDB();
const tasks = await db.getAll('tasks');
return tasks;
};
export default getAllTasks;
위 코드는 tasks 오브젝트 스토어에 저장된 모든 데이터를 배열 형태로 반환합니다.
데이터 업데이트
기존 데이터를 업데이트하려면 put 메서드를 사용합니다:
const updateTask = async (task) => {
const db = await initDB();
const tx = db.transaction('tasks', 'readwrite');
const store = tx.objectStore('tasks');
await store.put(task);
await tx.done;
console.log('Task updated successfully');
};
export default updateTask;
여기서 put 메서드는 새로운 데이터를 추가하거나 기존 데이터를 덮어씁니다.
데이터 삭제
데이터를 삭제하려면 delete 메서드를 사용합니다:
const deleteTask = async (id) => {
const db = await initDB();
const tx = db.transaction('tasks', 'readwrite');
const store = tx.objectStore('tasks');
await store.delete(id);
await tx.done;
console.log('Task deleted successfully');
};
export default deleteTask;
이 코드는 id를 기준으로 데이터를 삭제합니다.
React 컴포넌트에서 활용하기
이제 위에서 만든 IndexedDB 유틸리티를 React 컴포넌트에서 활용해 보겠습니다. 예를 들어, To-Do 리스트를 구현한다고 가정하겠습니다:
import React, { useEffect, useState } from 'react';
import addTask from './addTask';
import getAllTasks from './getAllTasks';
import deleteTask from './deleteTask';
const TodoApp = () => {
const [tasks, setTasks] = useState([]);
const [taskName, setTaskName] = useState('');
useEffect(() => {
const fetchTasks = async () => {
const allTasks = await getAllTasks();
setTasks(allTasks);
};
fetchTasks();
}, []);
const handleAddTask = async () => {
if (taskName.trim()) {
await addTask({ name: taskName });
setTaskName('');
const allTasks = await getAllTasks();
setTasks(allTasks);
}
};
const handleDeleteTask = async (id) => {
await deleteTask(id);
const allTasks = await getAllTasks();
setTasks(allTasks);
};
return (
<div>
<h1>To-Do List</h1>
<input
type="text"
value={taskName}
onChange={(e) => setTaskName(e.target.value)}
placeholder="Add a new task"
/>
<button onClick={handleAddTask}>Add</button>
<ul>
{tasks.map((task) => (
<li key={task.id}>
{task.name}
<button onClick={() => handleDeleteTask(task.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
};
export default TodoApp;
이 컴포넌트는 IndexedDB와 상호작용하여 데이터를 CRUD(생성, 읽기, 업데이트, 삭제)합니다.
결론
IndexedDB는 복잡한 데이터 저장 및 검색이 필요한 애플리케이션에서 강력한 도구로 활용될 수 있습니다. React와 함께 사용하면 클라이언트 측 데이터 관리를 더욱 효율적으로 할 수 있습니다. 이번 글에서는 IndexedDB의 기본 개념과 React에서의 활용 방법을 살펴보았습니다. 이를 바탕으로 다양한 애플리케이션에서 IndexedDB를 활용해 보세요!
'React' 카테고리의 다른 글
React에서 File API 사용하기 (0) | 2024.12.17 |
---|---|
React에서 Web Worker 사용하기 (0) | 2024.12.17 |
React에서 Cache API 사용하기 (0) | 2024.12.17 |
React에서 Web Storage API 사용하기 (0) | 2024.12.17 |
React에서 다국어 지원 구현하기 (0) | 2024.12.17 |