IndexedDB - team-yaza/mozi-client GitHub Wiki

๊ฐœ์š”

  • IndexedDB๋Š” ๋ธŒ๋ผ์šฐ์ €์— ๋‚ด์—์„œ ์ œ๊ณต๋œ ํŠธ๋žœ์žญ์…˜ ๊ฐ์ฒด ์ €์žฅ์†Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(transactional object store database)์ด๋‹ค.
  • IndexedDB์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์€ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๊ทธ๋ฃนํ™”๋œ๋‹ค. ํŠธ๋žœ์žญ์…˜ ๋‚ด์˜ ๋ชจ๋“  ์ž‘์—…์ด ์„ฑ๊ณตํ•˜๊ฑฐ๋‚˜ ํ˜น์€ ์‹คํŒจํ•œ๋‹ค.
  • IndexedDB๋Š” ๊ฐ์ฒด ์ €์žฅ์†Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋‹ค.
  • ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฐ์ฒด ์ €์žฅ์†Œ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ๊ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋‹ค์ˆ˜์˜ ๊ฐ์ฒด ์ €์žฅ์†Œ๋ฅผ ๊ฐ–๊ณ  ๊ฐ๊ฐ์˜ ์ €์žฅ์†Œ๋Š” ๋‹ค์ˆ˜์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ–์„ ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค -> ์ €์žฅ์†Œ -> ๊ฐ์ฒด
  • ๊ฐ์ฒด๋Š” JavaScript ๊ฐ์ฒด, ๋ถˆ๋ฆฐ, ์ˆซ์ž, BLOB(Binary Large Object) ๋ฐ JavaScript๊ฐ€ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋ฐ์ดํ„ฐ ํฌ๋งท ์ค‘ ํ•˜๋‚˜์ด๋‹ค.
  • ๊ฐ ๊ฐ์ฒด ์ €์žฅ์†Œ์—๋Š” ํ•œ๊ฐ€์ง€ ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์žˆ๋‹ค. (์‚ฌ์šฉ์ž, ์ฑ„ํŒ…๊ธฐ๋ก, ์˜ˆ์•ฝ ๋‚ด์—ญ๋“ฑ)
  • ๊ฐ์ฒด ์ €์žฅ์†Œ์—๋Š” ํ‚ค(key)-๊ฐ’(value) ์Œ์œผ๋กœ๋œ ๋ ˆ์ฝ”๋“œ๊ฐ€ ๋“ค์–ด์žˆ๋‹ค.
  • ํ‚ค๋Š” ๊ฐ์ฒด ์ €์žฅ์†Œ์˜ ๊ฐœ๋ณ„ ๊ฐ’์„ ์ฐธ์กฐํ•˜๋Š”๋ฐ ์‚ฌ์šฉ. ํ‚ค๋Š” ๋‹จ์ˆœํ•œ ์ˆซ์ž ์‹๋ณ„์ž๊ฐ€ ๋  ์ˆ˜ ์žˆ๊ณ , ๊ฐ’์— ๋Œ€ํ•œ ํŠน์ • ๊ฒฝ๋กœ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.
  • IndexedDB๋Š” ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…(Same-Origin Policy)๋ฅผ ๋”ฐ๋ฅธ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ํŠน์ • ์‚ฌ์ดํŠธ์—์„œ ์ž‘์„ฑ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์— ๋…ธ์ถœ๋  ๊ฒƒ์„ ๊ฑฑ์ •ํ•˜์ง€ ์•Š์•„๋„ ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์— ๋ฐฉ๋ฌธํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์‹œ ๋งํ•˜๋ฉด ์ž์‹ ์˜ ๋„๋ฉ”์ธ ๋‚ด์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์˜ IndexedDB์— ๊ธฐ๋ก๋œ ๋ฐ์ดํ„ฐ๋Š” ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค.
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋ฒ„์ „์„ ๊ฐ–๋Š”๋‹ค. ๊ฐ์ฒด ์ €์žฅ์†Œ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ตฌ์กฐ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ƒˆ๋กœ์šด ๋ฒ„์ „์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜์„ ์—ด์–ด์•ผํ•œ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜์„ ์—ด ๋•Œ upgrade-needed ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ํ˜„์žฌ ๋ฒ„์ „๊ณผ ์ด์ „ ๋ฒ„์ „ ์‚ฌ์ด์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ ๋ฐ˜์˜์€ ์ด ์ด๋ฒคํŠธ ์ค‘์— ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ๋‹ค.
  • ๋Œ€๋ถ€๋ถ„์˜ IndexedDB ์ž‘์—…์€ ๋น„๋™๊ธฐ์ด๋‹ค. API๋Š” ๊ฐ’์ด ์š”์ฒญ๋˜์—ˆ์„ ๋•Œ ํ•ด๋‹น ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š”๋‹ค.๊ฐ’์„ ์š”์ฒญํ•˜๋Š” ๋Œ€์‹  ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ด์•ผํ•œ๋‹ค.
  • IndexedDB๋Š” ์ธ๋ฑ์Šค๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋‹ค. ์ธ๋ฑ์Šค๋ฅผ ๋ถ€์—ฌํ•ด์„œ ์›ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ์‚ฌ์šฉ.
  • IndexedDB๋Š” ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ฐ˜์ด๋‹ค. ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋Š” ์‚ฌ์šฉ์ž์˜ ์—ฐ๊ฒฐ ์ƒํƒœ์— ๊ด€๊ณ„์—†์ด ์ ‘๊ทผ ๋ฐ ์กฐ์ž‘ ๊ฐ€๋Šฅํ•˜๋‹ค.

Pattern

IndexedDB ์ž‘์—…์˜ ๊ธฐ๋ณธ ํŒจํ„ด์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์—ฐ๋‹ค.
  2. ๊ฐ์ฒด ์ €์žฅ์†Œ์— ์ฝ๊ธฐ ํ˜น์€ ์“ฐ๊ธฐ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•œ๋‹ค.
  3. ๊ฐ์ฒด ์ €์žฅ์†Œ๋ฅผ ์—ฐ๋‹ค.
  4. ๊ฐ์ฒด ์ €์žฅ์†Œ์—์„œ ํ•„์š”ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.(๊ฐ์ฒด ๊ฒ€์ƒ‰, ๊ฐ์ฒด ์ถ”๊ฐ€, ๊ฐ์ฒด ์‚ญ์ œ ๋“ฑ)
  5. ํŠธ๋žœ์žญ์…˜์„ ์™„๋ฃŒํ•œ๋‹ค.

1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜ ์—ด๊ธฐ

const request = window.indexedDB.open("my-database", 1);
request.onerror = function (event) {
  console.log("Database error:", event.target.error);
};

request.onsuccess = function (event) {
  const db = event.target.result;
  console.log("Database", db);

  console.log("Object store names: ", db.objectStoreNames);
};

window.indexedDB.open() ํ˜ธ์ถœ์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋Œ€์‹  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜์„ ์—ด๊ธฐ ์œ„ํ•œ IDBRequest ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ์š”์ฒญ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ €์—์„œ ์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ค๋ฉด ๋ธŒ๋ผ์šฐ์ € ๋‚ด์— my-database๋ผ๋Š” ์ด๋ฆ„์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ์—ด๋ฆฐ๋‹ค. ์ดํ›„ success ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. success ์ด๋ฒคํŠธ ์ฝœ๋ฐฑ์—์„œ๋Š” ์—ด๋ฆฐ IDBDatabase ๊ฐ์ฒด ๋ฐ ํ•ด๋‹น ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ํฌํ•จ๋œ ๊ฐ์ฒด ์ €์žฅ์†Œ ๋ชฉ๋ก์„ ์ฝ˜์†”์— ๊ธฐ๋กํ•œ๋‹ค.

์„œ๋น„์Šค ์›Œ์ปค์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ IndexedDB๋„ ๋ฒ„์ „์„ ๊ฐ–๋Š”๋‹ค. ๊ฐ์ฒด ์ €์žฅ์†Œ ์ถ”๊ฐ€, ๋ณ€๊ฒฝ, ์‚ญ์ œ์™€ ๊ฐ™์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๋ฒ„์ „์„ ์ƒ์„ฑํ•ด์•ผํ•œ๋‹ค.

IndexedDB.open()์˜ ๋‘๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋˜๋Š” ๋ฒ„์ „ ๋ฒˆํ˜ธ๋ฅผ ์ฆ๊ฐ€์‹œ์ผœ ์ƒˆ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฒ„์ „์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊ธฐ์กด ๋ฒ„์ „๋ณด๋‹ค ํฐ ๋ฒ„์ „๋ฒˆํ˜ธ๋ฅผ ๊ฐ์ง€ํ•˜๋ฉด upgrade needed ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

request.onupgradeneeded = function (event) {
  const db = event.target.result;

  db.createObjectStore("customers", { keyPath: "passport_number" });
};

์ด ์ฝ”๋“œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ upgrade needed ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ์ฆ‰์‹œ ์‹คํ–‰๋œ๋‹ค. upgrade needed ์ด๋ฒคํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  customers๋ผ๋Š” ์ด๋ฆ„์˜ ์ƒˆ ๊ฐ์ฒด ์ €์žฅ์†Œ๋ฅผ ์ƒ์„ฑ. ๋˜ํ•œ ์—ฌ๊ถŒ๋ฒˆํ˜ธ๋ฅผ ์ €์žฅ์†Œ์˜ ๊ฐ ๊ฐ์ฒด์— ๋Œ€ํ•œ ๊ณ ์œ  ํ‚ค๋กœ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด keyPath๋ฅผ ์‚ฌ์šฉ.

2~4. ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘ -> ๊ฐ์ฒด ์ €์žฅ์†Œ ์—ด๊ธฐ -> ๊ฐ์ฒด ์ €์žฅ์†Œ์—์„œ ํ•„์š”ํ•œ ์ž‘์—… ์ˆ˜ํ–‰

request.onsuccess = function (event) {
  const db = event.target.result;

  const customerData = [
    {
      passport_number: "6651",
      first_name: "John",
      last_name: "Doe",
    },
    {
      passport_number: "6652",
      first_name: "Jane",
      last_name: "Doe",
    },
  ];

  const customerTransaction = db.transaction("customers", "readwrite");

  customerTransaction.onerror = function (error) {
    console.log("Error: ", error.target.error);
  };

  const customerStore = customerTransaction.objectStore("customers");

  for (let i = 0; i < customerData.length; i++) {
    customerStore.add(customerData[i]);
  }
};

์œ„ ์ฝ”๋“œ๋Š” ์ƒˆ๋กœ์šด readwrite ํŠธ๋žœ์žญ์…˜์„ ์ƒ์„ฑํ•˜๊ณ  ์ž‘์—…์˜ ๋ฒ”์œ„๋ฅผ customers ๊ฐ์ฒด ์ €์žฅ์†Œ๋กœ ์ง€์ •ํ•œ๋‹ค. ๋˜ํ•œ ํŠธ๋žœ์žญ์…˜ ์—๋Ÿฌ๋ฅผ ์ˆ˜์‹ ํ•ด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ด๋ฅผ ์ฝ˜์†”์— ๊ธฐ๋กํ•œ๋‹ค. ๋‹ค์Œ์œผ๋กœ ์ƒ์„ฑ๋œ ํŠธ๋žœ์žญ์…˜์˜ objectStore() API๋ฅผ ํ˜ธ์ถœํ•ด customers ๊ฐ์ฒด ์ €์žฅ์†Œ๋ฅผ ์—ด๊ณ , ๊ฐ์ฒด ์ €์žฅ์†Œ์˜ add() API๋ฅผ ํ˜ธ์ถœํ•ด ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

IndexedDB์—์„œ ์ˆ˜ํ–‰๋˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์ž‘์—…์€ ํŠธ๋žœ์žญ์…˜์ด๋‹ค. ๊ฐ์ฒด ์ €์žฅ์†Œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— ์ƒˆ ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•ด์•ผํ•œ๋‹ค. ํŠธ๋žœ์žญ์…˜์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ์ฒด์—์„œ transaction()์„ ํ˜ธ์ถœํ•˜์—ฌ, ์ฒซ๋ฒˆ์งธ ์ธ์ž๋กœ ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์‹œ์ž‘๋œ๋‹ค.

ํŠธ๋žœ์žญ์…˜์˜ ๋ฒ”์œ„๋Š” ํŠธ๋žœ์žญ์…˜์ด ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด ์ €์žฅ์†Œ ์ด๋ฆ„ ํ˜น์€ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๊ฐ์ฒด ์ €์žฅ์†Œ ์ด๋ฆ„์„ ํฌํ•จํ•œ ๋ฐฐ์—ด์ด๋‹ค. ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„๋ฅผ ์ •์˜ํ•˜์—ฌ, IndexedDB๊ฐ€ ์„œ๋กœ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜ ์‚ฌ์ด์˜ ๊ฒฝ์Ÿ ์ƒํƒœ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‘๊ฐœ ํ˜น์€ ๊ทธ ์ด์ƒ์˜ readwrite ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„๊ฐ€ ๊ฒน์น˜๋Š” ๊ฒฝ์šฐ ๊ฐ ํŠธ๋žœ์žญ์…˜์€ ํ์— ๋“ค์–ด๊ฐ€ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰๋œ๋‹ค. ๋งŒ์ผ ์„œ๋กœ๋‹ค๋ฅธ ๋ฒ”์œ„๋ฅผ ๊ฐ–๋Š” readwrite ํŠธ๋žœ์žญ์…˜์ด๊ฑฐ๋‚˜ readonly ํŠธ๋žœ์žญ์…˜์ธ ๊ฒฝ์šฐ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋‹ค.

ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์‹คํ–‰ํ•˜๋Š” ์ž‘์—…๋“ค์€ ๋งˆ์น˜ ํ•˜๋‚˜์˜ ์ž‘์—…์ธ ๊ฒƒ์ฒ˜๋Ÿผ ๋ชจ๋‘ ์„ฑ๊ณตํ•˜๊ฑฐ๋‚˜, ๋ชจ๋‘ ์‹คํŒจํ•˜๋Š” ์›์ž์„ฑ์ด ๋ณด์žฅ๋œ๋‹ค.

๋ฐ์ดํ„ฐ ์ฝ๋Š” ๊ฒƒ์—๋Š” ์„ธ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

  1. ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ ๊ฐ์ฒด๋ฅผ ์š”์ฒญ
  2. ์ปค์„œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅ์†Œ์˜ ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ์ˆœํšŒ
  3. ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•ด ๋” ์ž‘์€ ๋ฐ์ดํ„ฐ ๊ทธ๋ฃน์œผ๋กœ ๊ฒ€์ƒ‰

๋จผ์ € ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ์ฒด ์ €์žฅ์†Œ์—์„œ ๋‹จ์ผ ๊ฐ์ฒด๋ฅผ ์ฝ์–ด๋ณด์ž.

const request = window.indexedDB.open("my-database", 2);
request.onsuccess = function (event) {
  const db = event.target.result;
  const customerTransaction = db.transaction("customers");
  const customerStore = customerTransaction.objectStore("customers");
  const request = customerStore.get("7227");

  request.onsuccess = function (event) {
    const customer = event.target.result;
    console.log(customer);
  };
};

๊ฐ์ฒด ์ €์žฅ์†Œ์—์„œ get()์„ ํ˜ธ์ถœํ•˜์—ฌ ์ฐพ๊ณ ์žํ•˜๋Š” ๊ณ ๊ฐ ๊ฐ์ฒด์™€ ์ผ์น˜ํ•˜๋Š” ํ‚ค๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. get()์€ ๋น„๋™๊ธฐ์  ์ž‘์—…์ด๊ธฐ ๋–„๋ฌธ์— ๊ฒฐ๊ณผ๋ฅผ ์ฆ‰์‹œ ๋ฐ˜ํ™˜ํ•˜์ง€๋Š” ์•Š์ง€๋งŒ, ์š”์ฒญ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ์š”์ฒญ์— ๋Œ€ํ•œ onsuccess ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜์—ฌ ์ž‘์—…์ด ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์š”์ฒญํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ IndexedDB ๋ฉ”์„œ๋“œ๋ฅผ ์„œ๋กœ ์—ฐ๊ฒฐํ•˜๋ฉด ๋” ์งง๊ณ  ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ ์ž‘์„ฑ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

request.onsuccess = function (event) {
  event.target.result
    .transaction("customers")
    .objectStore("customers")
    .get("6651").onsuccess = function (event) {
    const customer = event.target.result;
    console.log(customer);
  };
};

๋ฒ„์ „ ๊ด€๋ฆฌ

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์€ ํŠน์ • ๋ฒ„์ „์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ทธ ๋‹ค์Œ ์ƒ์œ„ ๋ฒ„์ „์œผ๋กœ ์˜ฌ๋ฆฌ๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ์ž‘์—… ๋ชจ์Œ์ด๋‹ค. ์›์น™์ ์œผ๋กœ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋„ ๊ฐ๊ฐ์˜ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ์„œ ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ์€ IndexedDB์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

request.onupgradeneeded = function (event) {
  const db = event.target.result;
  const oldVersion = event.oldVersion;

  if (oldVersion < 2) {
    db.createObjectStore("cusomers", {
      keyPath: "passport_number",
    });
  }

  if (oldVersion < 3) {
    db.createObjectStore("employees", {
      keyPath: "employee_id",
    });
  }
};

์œ„ ๋ฉ”์„œ๋“œ๋Š” ์ด์ „ ๋ฒ„์ „ ๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ด ๋ชจ๋“  ๋ฒ„์ „์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ฐ€์žฅ ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ๊ฐ€์ ธ์˜ค๋„๋ก ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฒ„์ „ 1์—์„œ ๊ฐ€์žฅ ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ์˜ฎ๊ธฐ๋Š”๋ฐ๋Š” ์œ ์šฉํ•˜์ง€๋งŒ ์ˆ˜์‹ญ๊ฐœ์˜ ๋ฒ„์ „์„ ์œ ์ง€ํ•˜๊ธฐ๋Š” ์–ด๋ ต๋‹ค. ๋ฒ„์ „๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ณ  ํ•„์š”์— ๋”ฐ๋ผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

request.onupgradeneeded = function (event) {
  const db = event.target.result;

  if (!db.objectStoreNames.contains("customers")) {
    db.createObjectStore("customers", {
      keyPath: "passport_number",
    });
  }
};

์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณ€๊ฒฝ ์ „์— ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•œ์ง€ ํ•ญ์ƒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฐ์ฒด ์ €์žฅ์†Œ๋งŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ธ๋ฑ์Šค์ธ ๊ฒฝ์šฐ์—๋งŒ ์ธ๋ฑ์Šค๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

์ปค์„œ๋กœ ๊ฐ์ฒด ์ฝ๊ธฐ

get()์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด ์ €์žฅ์†Œ์—์„œ ๋‹จ์ผ ๊ฐ์ฒด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด์•˜๋‹ค. ์•ˆํƒ€๊น๊ฒŒ๋„ ์ด ๋ฐฉ๋ฒ•์€ ์ •ํ™•ํ•œ ํ‚ค๋ฅผ ์•Œ๊ณ  ๋‹จ์ผ ๊ฐ์ฒด๋ฅผ ๊ฒ€์ƒ‰ํ•  ๋•Œ์—๋งŒ ์ž‘๋™ํ•œ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐ์ฒด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ปค์„œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

์ปค์„œ๋ž€? SQL ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ต์ˆ™ํ•˜๋‹ค๋ฉด SELECT * FROM table ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰์‹œ์ผœ ์ปค์„œ๋ฅผ ์˜คํ”ˆํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•  ๊ฒƒ์ด๋‹ค. ์ด ์ฟผ๋ฆฌ๊ฐ€ WHERE์ด๋‚˜ LIMIT์œผ๋กœ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ปค์„œ๋„ ์ธ๋ฑ์Šค๋‚˜ ๋ฐ”์šด๋”๋ฆฌ๋กœ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋‹ค. SQL์—์„œ ๋ฐ˜ํ™˜๋œ ๊ฒฐ๊ณผ์™€ ๋‹ฌ๋ฆฌ, ์ปค์„œ๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์ง€๋Š” ์•Š๋‹ค. SQL์—์„œ ๋ฐ˜ํ™˜๋œ ๊ฒฐ๊ณผ์™€ ๋‹ฌ๋ฆฌ ์ปค์„œ๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์ง€๋Š” ์•Š๋‹ค. ์ด๊ฒƒ์€ ๋‹จ์ˆœํžˆ ๊ฐ์ฒด ์ €์žฅ์†Œ์— ์กด์žฌํ•˜๋Š” ์‹ค์ œ ๊ฐ์ฒด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ ๋ชฉ๋ก์ด๋‹ค. ์ปค์„œ๋Š” ๊ฐ์ฒด ์ €์žฅ์†Œ์— ์กด์žฌํ•˜๋Š” ํ•˜๋‚˜์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉฐ, continue()ํ˜น์€ advance()๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๋‹ค์Œ์œผ๋กœ ๋„˜์–ด๊ฐ„๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ๋“ค๊ณ  ์žˆ์„ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์—†์ด๋„ ์šฉ๋Ÿ‰์ด ํฐ ๊ฐ์ฒด์ €์žฅ์†Œ๋ฅผ ์ˆœํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์ œ ์ปค์„œ๋ฅผ ์—ด์–ด๋ณด์ž.

const request = window.indexedDB.open("my-database", 3);

request.onsuccess = function (event) {
  const db = event.target.result;
  const customerTransaction = db.transaction("customers");
  const customerStore = customerTransaction.objectStore("customers");
  const customerCursor = customerStore.openCursor();

  customerCursor.onsuccess = function (event) {
    const cursor = event.target.result;
    if (!cursor) return;

    console.log(cursor.value.first_name);
    cursor.continue();
  };
};

์ €์žฅ์†Œ์— ์ €์žฅ๋œ ๊ณ ๊ฐ ์ฝ”๋“œ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ๋Œ๋ฉฐ ์ฝ˜์†”์— ์ด๋ฆ„์ด ์ถœ๋ ฅ๋œ๋‹ค.

onsuccess์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ์—์„œ๋Š” ์ปค์„œ๋ฅผ ํ†ตํ•ด ํ˜„์žฌ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ๊ฐ์ฒด์˜ first_name์˜ ๊ฐ’์„ ๋กœ๊ทธ๋กœ ๋‚จ๊ธฐ๊ณ , ์ปค์„œ๊ฐ€ ๋‹ค์Œ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก continue() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. ์ปค์„œ๊ฐ€ ์•ž์œผ๋กœ ์ด๋™ํ•  ๋•Œ๋งˆ๋‹ค onsuccess ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•ด ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋˜๊ณ  ๋‹ค์Œ ๊ณ ๊ฐ์˜ ์ด๋ฆ„์„ ๋กœ๊ทธ๋กœ ๋‚จ๊ธด๋‹ค.

๊ฐ์ฒด ์ €์žฅ์†Œ๊ฐ€ ๋น„์–ด์žˆ๋”๋ผ๋„ ์ปค์„œ๋Š” ์•ž์œผ๋กœ ์ด๋™ํ•  ๋•Œ๋งˆ๋‹ค onsuccess ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์ด๋•Œ ์ปค์„œ(event.target.result)๋Š” null์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค. onsuccess ํ•จ์ˆ˜๊ฐ€ ์ปค์„œ์— ์ ‘๊ทผํ•˜๊ธฐ ์ „์— ์ปค์„œ๊ฐ€ null์„ ๊ธฐ๋ฆฌํ‚ค๊ณ  ์žˆ์ง€ ์•Š์€์ง€ ๊ผญ ํ™•์ธํ•ด์•ผํ•œ๋‹ค.

์œ„๋กœ Bubbling๋˜๋Š” IndexedDB ์—๋Ÿฌ ์ฒ˜๋ฆฌ

IndexedDB์˜ ์—๋Ÿฌ ์ด๋ฒคํŠธ๋Š” ์œ„๋กœ ์ „ํŒŒ๋œ๋‹ค.

์ปค์„œ ์˜คํ”ˆ ์š”์ฒญ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ์ƒ๊ธฐ๋ฉด ํ•ด๋‹น ์š”์ฒญ์˜ onerror ํ•ธ๋“ค๋Ÿฌ์— ์˜ค๋ฅ˜๊ฐ€ ์žกํž ๊ฒƒ์ด๋‹ค. ๋งŒ์ผ ํ•ด๋‹น ์š”์ฒญ์— ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ onerror ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ •์˜๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด ์˜ค๋ฅ˜๋Š” ํŠธ๋žœ์žญ์…˜ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ์— ์žกํžˆ๋„๋ก ์ „ํŒŒ๋  ๊ฒƒ์ด๋‹ค. ํŠธ๋žœ์žญ์…˜๋„ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋ฉด, ์—๋Ÿฌ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ์ฒด์˜ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ์— ์žกํžˆ๋„๋ก ์œ„๋กœ ์ „ํŒŒ๋„๋ฆฌ ๊ฒƒ์ด๋‹ค.

์ด๋Ÿฌํ•œ ์ž‘๋™ ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด ๋งค ์š”์ฒญ ๋ฐ ํŠธ๋žœ์žญ์…˜๋งˆ๋‹ค ๋ณ„๋„์˜ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ •์˜ํ•˜๋Š” ๋Œ€์‹ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ์ฒด์—์„œ ํ•˜๋‚˜์˜ ์—๋Ÿฌ ํ•ธ๋“œ๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•ด ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.