Web SQL DataBase API 사용법

Jay·2022년 12월 13일
1

Web SQL 실습 사이트를 만드는 오픈 소스 프로젝트에 참여하여 HTML5 Web SQL DataBase API로 쿼리 실행 기능을 구현하였습니다.

프로그래밍 순서는 다음과 같습니다.

  1. 데이터베이스 오픈
  2. 트랜젝션 시작
  3. SQL 실행
  4. 실행결과 처리

아래는 Web SQL Database API를 사용한 로직 코드입니다.

// WebSQL 데이터베이스 생성
const database = openDatabase(
  'University',
  '1.0',
  'chrome dabase test',
  2 * 1024 * 1024
);

// WebSQL 테이블 생성
const createTable = (tableName, tableData) => {
  if (!tableName) return '테이블 이름이 없습니다.';
  if (!tableData) return '테이블 데이터가 없습니다.';

  const columns = [];

  for (let column in tableData[0]) {
    if (column.includes('/')) {
      columns.push(column.split('/').join(''));
    } else {
      columns.push(column.split(' ').join(''));
    }
  }

  return new Promise((resolve, reject) => {
    database.transaction(
      (tx) => {
        tx.executeSql(`DROP TABLE IF EXISTS ${tableName}`);
        tx.executeSql(
          `CREATE TABLE IF NOT EXISTS ${tableName}(${String(columns)})`,
          []
        );
      },
      [],
      () => {
        resolve();
      },
      () => {
        reject();
      }
    );
  });
};

// WebSQL 데이터 추가
const insertData = (tableName, tableData) => {
  if (!tableName) return '테이블 이름이 없습니다.';
  if (!tableData) return '테이블 데이터가 없습니다.';

  return new Promise((resolve, reject) => {
    database.transaction(
      (tx) => {
        for (let row of tableData) {
          const columns = [];
          const values = [];
          const substitute = [];

          for (let column in row) {
            if (column.includes('/')) {
              columns.push(column.split('/').join(''));
            } else {
              columns.push(column.split(' ').join(''));
            }
            values.push(row[column]);
            substitute.push('?');
          }

          tx.executeSql(
            `INSERT INTO ${tableName}(${String(columns)}) VALUES (${String(
              substitute
            )})`,
            values,
            (tx, result) => {},
            (tx, result) => {}
          );
        }
      },
      [],
      () => {
        resolve();
      },
      () => {
        reject();
      }
    );
  });
};

const fetchJSON = async (table) => {
  try {
    const response = await fetch(
      `https://raw.githubusercontent.com/websqldb/SQooL/main/data/${table}.json`
    );

    const result = await response.json();

    return result;
  } catch (err) {
    alert(`네트워크 에러가 발생했습니다.`);
  }
};

// 초기 세팅용 함수
const initSetting = async (tables) => {
  for (let table of tables) {
    // json 파일 fetch
    const data = await fetchJSON(table);
    // WebSQL 테이블 생성, data 추가
    createTable(table, data).then(insertData(table, data));
  }
};

const deleteTable = (tableName) => {
  if (!tableName) return '테이블 이름이 없습니다.';

  return new Promise((resolve, reject) => {
    database.transaction(
      (tx) => {
        tx.executeSql(`DROP TABLE IF EXISTS ${tableName}`);
      },
      []
    );
  });
};

const arr = [
  'student',
  'subject',
  'professor',
  'major',
  'grade',
  'scholarship',
  'tuition',
  'mileage',
  'invalid_data',
];

initSetting(arr);

const $editor = document.querySelector('.code > textarea');
const $table = document.querySelector('.sec-result > table');
const $run_button = document.querySelector('.btn-run');

$run_button.addEventListener('click', async (e) => {
  e.preventDefault();

  const data = await handleWebSQL($editor.value);
  renderTable(data);
});

const handleWebSQL = (text) => {
  return new Promise((resolve, reject) => {
    database.transaction((tx) => {
      tx.executeSql(
        text,
        [],
        (tx, result) => {
          resolve(result.rows);
        },
        () => {
          reject();
        }
      );
    });
  });
};

const cleanTable = () => {
  while ($table.firstChild) {
    $table.removeChild($table.firstChild);
  }
};

const renderTable = (data) => {
  // 테이블 자식 요소 제거
  cleanTable();

  // 테이블 내부 엘리먼트 생성
  const $tbody = document.createElement('tbody');

  // 효율 및 안전성을 위해 createElement 사용
  // 테이블 헤더 데이터 추가
  const $tr = document.createElement('tr');
 
  for (let column in data[0]) {
    const $th = document.createElement('th');
    
    $th.textContent = column;
    $tr.appendChild($th);
  }
  $tbody.appendChild($tr);

  // 테이블 바디 데이터 추가
  for (let row of data) {
    const $tr = document.createElement('tr');
    for (let value in row) {
      const $td = document.createElement('td');
      $td.textContent = row[value];
      $tr.appendChild($td);
    }
    $tbody.appendChild($tr);
  }

  // 테이블에 추가
  $table.appendChild($tbody);
};

이슈
컬럼명에 특수문자가 들어가거나 첫 글자가 숫자일 경우 값을 읽어오지 못하는 이슈가 있었습니다. 데이터의 유효성을 검사하는 함수와 유효한 값으로 바꾸어지는 convert 함수를 만들어 처리하였습니다.

주의
Web SQL DataBase API는 더 이상 지원되지 않는 기능입니다. 이 API를 경험하며 SQL문장을 파싱 처리하는 기능이 정말 강력하다고 느꼈는데 아쉽습니다. W3C에서는 Web DataBase가 필요하시다면 locaStorage, sessionStorage, indexdDb와 같은 Web Storage API를 사용하는 것을 권장하고 있습니다. 저희 오픈소스 사이트도 다음 기술로 마이그레이션할 예정입니다

0개의 댓글