반응형
회사에서 내가 개발하고 있는 파트였던 콘텐츠 찜하기 기능을 구현하기 위해 localStorage를 찾다가 IndexedDB라는것을 발견했다. 이에 내용을 정리한다.
1. IndexedDB란?
IndexedDB는 웹 브라우저에서 동작하는 객체 지향 데이터베이스이다.
이 데이터베이스는 key-value 쌍의 형태로 데이터를 저장하며, 웹 애플리케이션과 관련된 다양한 데이터를 안전하게 보관한다.
세션 정보, 사용자 설정, 복잡한 사용자 데이터 등을 클라이언트 측에서 효율적으로 관리할 수 있다.
1-1. 주요 사용 사례
- 대용량 데이터 처리
- 온라인과 오프라인 데이터 동기화
- 복잡한 데이터 쿼리
- 예시로, 웹 메일 클라이언트, 클라이언트-사이드 데이터베이스, 웹 기반 게임 등이 있다.
1-2. 장점
- 비동기 데이터 액세스: UI가 데이터베이스 작업 중에 멈추지 않는다.
- 복잡한 쿼리 수행 가능: 다양한 쿼리를 효율적으로 처리한다.
- 색인을 통한 효율적인 데이터 검색: 필요한 데이터를 빠르게 찾을 수 있다.
- 트랜잭션 지원: 데이터의 일관성을 보장한다.
- 이러한 장점들은 웹 애플리케이션에서 오프라인에서도 데이터를 유지하고 동적으로 처리하는 데 매우 유용하다.
1-3. JavaScript API
- IndexedDB는 JavaScript API를 통해 웹 애플리케이션에서 다룰 수 있다.
- 이 API를 사용하면 데이터베이스를 생성하고, 데이터를 CRUD(생성, 읽기, 업데이트, 삭제) 작업을 할 수 있다.
// 데이터베이스 열기
var request = indexedDB.open('MyDatabase', 1);
// 데이터베이스가 성공적으로 열렸을 때의 이벤트 핸들러
request.onsuccess = function(event) {
var db = event.target.result;
// ... (데이터 작업 수행)
};
1-4. 웹 브라우저의 개발자 도구
- 웹 브라우저의 개발자 도구를 통해서도 IndexedDB 데이터베이스를 직접 확인하고 관리할 수 있다. 이는 데이터베이스의 상태를 확인하고 디버깅할 때 매우 유용하다.
- 대부분의 모던 브라우저에서는 개발자 도구의 'Application' 또는 'Storage' 탭에서 IndexedDB 데이터베이스를 볼 수 있다.
2. 왜 IndexedDB를 사용해야 하는가?
- 성능: 클라이언트 사이드에서 데이터를 다룰 수 있어 서버 요청을 줄일 수 있다.
- 비동기 처리: 비동기 API를 통해 UI 블로킹을 피할 수 있다.
- 대용량 데이터: 상대적으로 큰 양의 데이터를 로컬에 저장할 수 있다.
- 쿼리 능력: 간단한 쿼리를 클라이언트 측에서 수행할 수 있어 서버 부하를 줄일 수 있다.
// 가상의 SpringBoot+Java 코드에서 IndexedDB 사용을 위한 간단한 로직
// IndexedDB는 자바스크립트에서 주로 사용되기 때문에 이 부분은 주로 프론트엔드에서 처리됩니다.
// 하지만 백엔드에서 이를 고려한 API 설계가 가능합니다.
public class IndexedDBService {
// IndexedDB 관련 로직
}
3. IndexedDB는 어디에 사용되는가?
3-1. 사용예시 설명
- 오프라인 웹 애플리케이션: 네트워크 연결이 없을 때도 데이터를 로컬에서 불러올 수 있다.
- 데이터 캐싱: 자주 사용되는 쿼리 결과나 중요 정보를 로컬에 저장해 빠르게 접근한다.
- 세션 관리: 사용자 설정, 임시 저장 데이터 등을 관리한다.
// 예를 들어, 서버에서 클라이언트에게 IndexedDB 사용을 권장하는 로직
@RestController
public class MyController {
@GetMapping("/useIndexedDB")
public ResponseEntity<?> useIndexedDB() {
// 로직
return ResponseEntity.ok("IndexedDB를 사용하세요.");
}
}
3-2. IndexedDB를 실제로 적용 중인 사례
- 구글 맵: 오프라인 지도 데이터 저장
- Slack: 메시지와 사용자 정보 등을 로컬에 저장해 빠른 접근을 가능하게 함
- 프로젝트 관리 도구: Trello 같은 앱에서는 드래그 앤 드롭 상태, 설정 등을 저장한다.
IndexedDB는 클라이언트 사이드에서 주로 사용되지만, 백엔드 개발자가 이해하고 있으면 더 효율적인 시스템을 설계할 수 있다. 예를 들어, RESTful API를 설계할 때 IndexedDB를 사용할 수 있는 클라이언트 측 구조를 고려하면 좋다.
4. 어떻게 IndexedDB를 사용하는가?
4-1. 데이터베이스 열기
- IndexedDB는 데이터베이스를 열고 특정 버전을 설정하는 과정을 거친다.
let db;
let request = indexedDB.open("myDatabase", 1); // 데이터베이스 이름과 버전을 지정합니다.
request.onerror = function(event) {
console.log("Database error: " + event.target.errorCode); // 에러 핸들링
};
request.onsuccess = function(event) {
db = request.result; // 성공 시 데이터베이스 인스턴스를 저장합니다.
};
4-2. 객체 저장소 생성하기
- IndexedDB에서는 테이블 대신 객체 저장소(Object Store)를 사용한다.
request.onupgradeneeded = function(event) {
let db = event.target.result;
let objectStore = db.createObjectStore("myStore", { keyPath: "id" }); // 'id'를 키로 가지는 객체 저장소를 생성합니다.
};
4-3. 데이터 쓰기
- put 메서드를 사용하여 데이터를 저장한다.
let transaction = db.transaction(["myStore"], "readwrite"); // 읽기/쓰기 트랜잭션을 생성합니다.
let objectStore = transaction.objectStore("myStore");
let request = objectStore.put({id: 1, name: "Hello IndexedDB!"}); // 데이터를 삽입하거나 갱신합니다.
4-4. 데이터 읽기
- get 메서드를 사용하여 데이터를 읽는다.
let transaction = db.transaction(["myStore"]);
let objectStore = transaction.objectStore("myStore");
let request = objectStore.get(1); // id가 1인 데이터를 가져옵니다.
4-5. 데이터 삭제
- delete 메서드를 사용하여 데이터를 삭제한다.
let transaction = db.transaction(["myStore"], "readwrite"); // 읽기/쓰기 트랜잭션을 생성합니다.
let objectStore = transaction.objectStore("myStore");
let request = objectStore.delete(1); // id가 1인 데이터를 삭제합니다.
4-6. 데이터 검색
- getAll 메서드를 사용하여 모든 데이터를 검색한다.
let transaction = db.transaction(["myStore"]);
let objectStore = transaction.objectStore("myStore");
let request = objectStore.getAll(); // 모든 데이터를 가져옵니다.
request.onsuccess = function(event) {
console.log(request.result); // 가져온 데이터를 출력합니다.
};
5. IndexedDB 성능 최적화와 관리 방법
웹 애플리케이션을 개발하면서 클라이언트 측에서 데이터를 저장하고 관리할 필요가 있는 경우가 많다.
이런 상황에서 IndexedDB는 효율적인 선택이 될 수 있다.
이 포스트에서는 IndexedDB의 성능을 최적화하는 방법과 데이터 삭제, 정렬 방법 등을 설명하겠다.
5-1. 성능 최적화를 위한 인덱스 생성
- 데이터 검색 성능을 향상시키기 위해 인덱스를 적절히 설정하는 것이 중요하다.
- 객체 저장소(object store)의 특정 속성에 인덱스를 생성하면, 해당 속성을 기준으로 빠르게 검색할 수 있다.
// 'age' 속성에 인덱스를 생성
var objectStore = db.createObjectStore("myObjectStore", { keyPath: "id" });
objectStore.createIndex("age", "age", { unique: false });
5-2. 인덱스를 활용한 데이터 검색
- 이렇게 생성된 인덱스를 통해, 데이터를 빠르게 검색할 수 있다.
- 다음 예제는 'age' 인덱스를 통해 30세 이상의 모든 데이터를 검색하는 코드이다.
var transaction = db.transaction("myObjectStore");
var objectStore = transaction.objectStore("myObjectStore");
var index = objectStore.index("age");
var keyRange = IDBKeyRange.lowerBound(30);
var request = index.getAll(keyRange);
6. IndexedDB의 데이터 정렬 방법
IndexedDB는 데이터를 저장하고 검색할 때 다양한 정렬 방법을 제공한다.
6-1. 자동 정렬: 키를 기준으로 데이터가 자동으로 정렬된다.
let store = db.transaction("myObjectStore", "readwrite").objectStore("myObjectStore");
let data = { key: 1, name: "Alice" };
store.add(data);
6-2. JSON 속성에 따른 정렬: JavaScript의 Array.sort() 메서드를 사용하여 원하는 속성에 따라 정렬한다.
// 자바스크립트 Array.sort()를 활용한 예제
let transaction = db.transaction("myObjectStore");
let store = transaction.objectStore("myObjectStore");
let request = store.getAll();
request.onsuccess = function() {
let sortedData = request.result.sort((a, b) => a.name.localeCompare(b.name));
console.log(sortedData);
};
6-3. 키 또는 인덱스에 따른 정렬: 생성된 인덱스를 활용하여 데이터를 정렬할 수 있다.
// 인덱스를 활용한 정렬 예제
let transaction = db.transaction("myObjectStore");
let store = transaction.objectStore("myObjectStore");
let index = store.index("name");
let request = index.getAll();
request.onsuccess = function() {
console.log(request.result);
};
주의사항: 코드를 실제 구현시에는 에러 처리나 트랜잭션 관리 등에 대한 추가적인 고려가 필요할 수 있다.
7. IndexedDB의 원하는 데이터 필터링 방법
7-1. 인덱스를 사용한 필터링
- 데이터베이스 스키마를 설계할 때, 필터링에 사용될 속성에 인덱스를 만든다. 그런 다음, 인덱스를 사용하여 필터링 조건에 맞는 데이터를 검색한다.
예제 코드
- 아래의 코드는 'age' 속성에 대한 인덱스를 사용하여 30살 이상의 데이터만을 검색하는 예제이다.
// 'age' 인덱스를 사용하여 30 이상의 데이터만 검색
var transaction = db.transaction(["myObjectStore"]);
var objectStore = transaction.objectStore("myObjectStore");
var index = objectStore.index("age");
var keyRange = IDBKeyRange.lowerBound(30);
var request = index.openCursor(keyRange);
주의 사항
- 인덱스를 사용할 경우에는 데이터베이스 스키마 설계 시점에서 미리 인덱스를 설정해야 한다.
7-2. 커서를 사용한 수동 필터링
- 인덱스가 없거나 복잡한 필터링이 필요한 경우에는 커서를 사용하여 수동으로 필터링을 수행한다. 커서를 사용하면 데이터베이스의 객체 저장소를 순회하며 각 아이템을 개별적으로 검사할 수 있다.
예제 코드
- 아래의 코드는 'age' 속성이 30 이상인 아이템만 results 배열에 추가하는 예제이다.
// 커서를 사용하여 'age'가 30 이상인 데이터만 검색
var transaction = db.transaction(["myObjectStore"]);
var objectStore = transaction.objectStore("myObjectStore");
var request = objectStore.openCursor();
var results = [];
request.onsuccess = function(event) {
var cursor = event.target.result;
if (!cursor) {
return;
}
if (cursor.value.age >= 30) {
results.push(cursor.value);
}
cursor.continue();
};
주의 사항
- 커서를 사용하는 방법은 유연성이 높지만, 성능이 느릴 수 있다. 필터링 조건이 많거나 데이터가 큰 경우에는 성능에 영향을 줄 수 있다.
2023.10.19 - [Git] - Git 커밋 못했을때 잔디심는 방법(mac)
반응형
'기타 > WEB, DB, GIT' 카테고리의 다른 글
Jenkins 깃허브 훅 설정 - GitHub hook trigger for GITScm Polling 설정하기 (0) | 2023.10.26 |
---|---|
Github Access Token발급받는 방법 (2) | 2023.10.26 |
GitHub에 다른일자 잔디심기 (macOS) (1) | 2023.10.19 |
Web개발 기초 - HTTP 구조 (0) | 2023.08.16 |
Port 8080 was already in use: tomcat 8080포트 종료하는 방법 (0) | 2023.08.16 |