로컬 DB 개발, IndexedDB와 Dexie.js로 간단하게

김유현·2024년 10월 10일

실무 개선 기록

목록 보기
10/10
post-thumbnail

최근 사내에서 사이드 프로젝트를 진행하게 되었습니다.

해당 프로젝트에서 로컬 DBNoSQL을 사용하려고 했는데,
그 과정 중에서 IndexedDB를 채택하게 된 내용에 대한 글을 작성하려고 합니다.


1. NoSQL이란? RDB와의 차이

많은 데이터베이스 유형이 있지만, 가장 많이 사용되는 두 가지 데이터베이스 유형이 있습니다.
첫 번째가 관계형 데이터베이스 또는 SQL(이하 "RDB")NoSQL이 있습니다.

RDBNoSQL 데이터베이스는 데이터를 저장하고 검색하도록 설계된 두 가지 다른 유형의 데이터베이스입니다.

둘의 차이점은?

  • RDB:

    • 데이터를 테이블로 구성하고 해당 테이블 간의 관계를 정의하는 관계형 모델을 기반으로 합니다.
    • 유연하게 설계되어 광범위한 사용 사례를 지원하지만 다른 유형의 데이터베이스보다 설정 및 관리가 더 복잡할 수 있습니다.
    • 예로는 MySQL, Oracle, PostgreSQL이 있습니다.
  • NoSQL:

    • 데이터베이스는 유연하고 확장 가능하도록 설계되었으며, 테이블에 깔끔하게 맞지 않는 대량의 데이터(비정형)를 처리하는 데 적합합니다.
    • 실시간 웹 애플리케이션이나 빅데이터 분석과 같이 데이터가 빠른 속도로 생성되는 상황에서 자주 사용됩니다.
    • 예로는 MongoDB, Cassandra, Couchbase가 있습니다.

추가로 차이점들이 여럿 있지만 현재 포스팅에서 서술하기에는 꽤 많은 양이기에 간략하게나마 설명드리고, 관련하여 참고한 블로그 링크을 공유드립니다.


2. IndexedDB(NoSQL) or SQLite(RDB)

위 두 가지 DB중에 하나를 선택하기로 했습니다.
왜냐하면 프로젝트에서는 다음 조건을 만족해야 했습니다.

  1. 오프라인 모드에서도 지원
  2. 비교적 데이터 양이 적을 예정
  3. 웹 브라우저 서비스에서만 운영

1순위 후보가 1, 2, 3번 모두에 적합한IndexedDB였는데
추가로 고려할 만한 사항이 있다면...

개발하기 편한가? => API가 직관적이고 편리하게 구성되어있는가 였는데..
적어도 제가 생각했을 땐 그렇지 않았습니다..ㅜ(꽤 복잡함..)

그래서 SQLite도 고려해봐야 하나..했지만!

Dexie.js라는 Wrapper 라이브러리를 함께 사용하면
기존에 불편했던 API 단점을 보완하여 보다 직관적인 API를 제공하고, 코드의 간결성과 유지보수성을 크게 개선할 수 있었습니다.

오픈소스 라이브러리 만세


3. 실제 사용 예시(단일 IndexedDB와 Dexie.js)

3-1. 기본 IndexedDB 코드:

  • IndexedDB는 트랜잭션 관리, 오브젝트 스토어 접근 등 다소 복잡한 절차가 필요합니다. 아래는 IndexedDB를 사용해 데이터를 추가하고 검색하는 기본 코드입니다.

이 코드는 매우 비동기적이며, 각각의 작업(데이터 추가, 검색 등)에 대해 콜백이 필요합니다. 코드가 점점 복잡해질수록 유지보수하기가 어려워집니다.

3-2. Dexie.js를 사용한 코드

  • Dexie.js를 사용하면 IndexedDB와 동일한 기능을 훨씬 간결하고 직관적인 코드로 작성할 수 있습니다. 특히 프로미스 기반의 API를 제공비동기 처리가 깔끔해집니다.

4. 실제 프로젝트 사용 예시(Angular 프레임워크)

Angular 프레임워크를 활용해 서비스 레이어에서 데이터베이스 관리 기능과 비즈니스 로직을 분리하여 코드의 재사용성과 유지보수성을 높였습니다.

4.1 dexie.service.ts 파일

아래 코드에서는
1) DexieService의 일반화

  • DexieService가 특정 테이블에 의존하는게 아닌, 호출하는 서비스에서 테이블 이름과 데이터를 전달받아 처리합니다.

ex) 게시판 서비스에서 게시글 타입을 Generic으로 전달받아서 해당 테이블 관련 로직을 처리할 수 있습니다. 4.2 참고

이 방식으로 작업하면 각 테이블 관련 서비스에서 타입을 Generic으로 전달받아 해당 테이블 관련 로직을 DexieService에서 처리할 수 있습니다.

4.2 실제 예시) board.service.ts 파일


5. 추가 조사 내용(추후 대비해야할 만한 문제들)

1. 인덱싱 기능을 사용 가능한가?

  • 이유: 데이터가 많이 쌓였을 때 조회에 시간을 많이 소요하지 않기 위해서
  • 조사 결과: 테이블을 정의할 때 컬럼(index라고 부름)를 명시적으로 정의해주면 indexedDB 내부에서 자동으로 인덱싱처리를 해줌.
  • 관련 Dexie.js 공식 문서

2. 특정 필드(예: title)로 검색 쿼리가 가능한가?

  • 이유: ID로만 검색이 가능하다면 조회가 복잡해질 수 있음
  • 조사 결과:
    • Dexie.js를 사용하면 특정 필드에 대해 where() 메서드를 통해 검색 쿼리를 작성할 수 있습니다.
    • Dexie.js에서는 SQL의 LIKE 연산자처럼 부분 일치중간에 포함된 단어를 검색하는 기능은 기본적으로 제공되지 않습니다. 참고 이슈 - LIKE 연산자 부재
    • 대체 방법: filter() 메서드 사용 SQL의 LIKE 연산자와 동일한 기능이 없기 때문에, filter() 메서드를 통해 중간에 포함된 단어 또는 부분 일치 검색을 수행할 수 있습니다. 하지만 이 방법은 인덱스를 사용하지 않으므로 성능에 영향을 미칠 수 있습니다.

3. DB 데이터를 브라우저에서 간편하게 import/export 할 수 있는가?

  • 이유: 데이터를 옮기는 과정에서 수월하게 처리하기 위함
  • 조사 결과: IndexedDB Exporter 확장 프로그램
    IndexedDB Exporter는 Chrome 확장 프로그램으로, IndexedDB 데이터를 간편하게 JSON 형식으로 내보낼 수 있는 기능을 제공합니다.

6. 결론

1. 온/오프라인 모드 + 웹 브라우저 서비스 + NoSQL을 고려하고 있다면 IndexedDB를 추천.

2. IndexedDB 기본 API가 사용하기 불편하다면 Wrapper 라이브러리를 이용해서 API를 좀 더 직관적이게 만들고, 코드를 간결하게 유지할 수 있다.

실제로 사용할 때, 데이터베이스 로직과 비즈니스 로직을 분리하여 작성함으로써 확장성과 유지보수성을 높일 수 있다.


마무리하며
이번 글에서는 IndexedDB를 선택하게 된 이유와 사용 과정에서 Dexie.js의 장점을 설명해 보았습니다. IndexedDB는 웹 환경에서 오프라인 데이터를 저장하기에 훌륭한 선택이지만, 기본 API는 다소 복잡할 수 있죠. 이때 Dexie.js와 같은 라이브러리를 사용하여 복잡한 부분을 해결하고 개발을 더 간편하게 할 수 있습니다.

여러분의 프로젝트에서도 IndexedDB와 같은 로컬 DB를 고려하고 있다면, 이번 경험이 작은 도움이 되었기를 바랍니다. 실무에서 적용하면서 겪은 문제와 해결책을 공유하는 것에 큰 가치를 두고 있으며, 여러분의 피드백이나 추가적인 경험도 언제든지 환영합니다. 감사합니다

profile
FRONTEND DEVELOPER

0개의 댓글