Sitemap
테크리드 오답노트

테크리드 오답노트

“세상에 정답은 없어. 하지만 오답은 있지” 1X년 쌓여가는 테크리드의 오답노트

@dxnlab/idb

10 min readJul 1, 2026

--

https://www.npmjs.com/package/@dxnlab/idb

import { idb, reads, writes } from '@dxnlab/idb'
import migration from './migration'
import { type Item } from './type'

@idb('idb-name', migration)
class IdbConnector {

@writes('items')
public async addItem({items}, item:Item) {
return await items.add(item);
}

@writes('items')
public async setItem({items}, item:Item) {
return await items.put(item);
}

@reads('items')
public async findItem({items}, id) {
return await items.get(id);
}

@reads('items')
public async *listItems({items}) {
return items.valueGenerator();
}

}

const idb = new IdbConnector();

export async function addItem(item:Item) {
return await idb.addItem(item);
}

export async function editItem(item:Item) {
return await idb.setItem(item);
}

export async function findItem(id) {
return await idb.findItem(id);
}

export async function *listItems() {
return idb.listItems();
}

대략 1년 정도 된 것 같습니다. 처음 이 구조를 떠올리고 언젠가는 만들어야지 생각했던 시점부터 말입니다. 개인적으로 머릿속에 구상하는 기능/제품은 많아도, 먹고사니즘을 포함해서 여러 조건이 맞지 않아 — 시기를 놓치고 빛을 보지 못하는 것들이 수두룩 빽빽한데 그나마 이 경우는 운이 좋았다(?)고 할 수 있겠습니다.

뭐, 그렇다고 1년이나 걸려서 만들었다는 의미는 전혀 아닙니다. 참 많은 일들이 있었고 또 여전히 현재 진행중입니다 (ㅎㅎㅎ…)

Technical Aspect

1년 전에도 언급했습니다만 최근 몇 년 사이 js/ts 에 상당한 변화가 있습니다. 그 중에서도 이 프로젝트 @dxnlab/idb 에 포함된 것으로 크게 3 가지를 들겠습니다.

  • IndexedDB
  • TypeScript Decorator (stage3)
  • AsyncGenerator

우선 IndexedDB. 종전까지 localStorage/sessionStorage가 있었다면, 최근 다양한 유형의 webworker 로컬 스토리지가 등장하고 있습니다. 그 중에서도 IndexedDB 는 그 이름대로 쿼리가 가능한 NoSQL 의 역할을 대행합니다. 키 인덱싱이 지원되고, 여타 NoSQL 처럼 일반 오브젝트 저장이 가능하며 —상당한 가용 용량을 자랑합니다. OS/브라우저에 따라 차이는 있으나 통상 로컬 머신 저장 용량의 50% 정도를 최대 한도로 잡는 것 같습니다. 256GB SSD 스토리지가 딸린 컴퓨터라면 대략 100GB 정도.

단점이라면, 은근히 쓰기가 복잡하고 브라우저의 Inspector에 평문으로 노출된다는 점 정도입니다. 서비스워커 기반으로 비동기 리퀘스트 — 핸들러를 조합해서 쓰는데 이게 작성하다 보면 코드의 분량과 비구조화가 만만치 않습니다.

때문에 idb / indexedDB 라는 키워드로 npmjs에 검색해보면 idb를 필두로 유사한 라이브러리들이 적지 않습니다. 처음 IndexedDB를 프로젝트에 접목했을 당시에도 idb 를 잠깐 고려했습니다만, idb는 정말 “minimal wrapper” 여서 장점이 뚜렷하게 보이진 않더군요.

해당 시점에 ES 의 여러 변화를 살펴 보다가, 그때 막 주목 받고 있던 TypeScript의 decorator를 접속시킬 생각을 했습니다.

TypeScript Decorator (stage3). @ 데코레이터 패턴 자체는 Python을 쓰던 사람들에게는 꽤 익숙할겁니다. 특히 이런 DB 처리처럼, 트랜잭션을 감싸는 래퍼가 필요한 경우에 쓰기 좋습니다.

그런데 여기 함정이 있습니다; TypeScript Decorator 자체로 찾아보면 많은 내용에서 tsconf 의 experimentalDecorators 설정을 이야기하는데, experimentalDecorators=true 설정은 지금 말씀드리는 stage3 가 아니라 그 이전, stage2 문법을 활성화 시킵니다. 두 가지는 구문이 완전히 다르고 상호 호환이 불가능합니다. Decorator stage3 문법은 target이 es2015 혹은 그 이후 (esnext)일 때, TypeScript 버전 5.x 이상에서 자동으로 활성화됩니다.

초기에 AI로 몇 가지 끄적거려 봤을 때 난감했던 부분이 이 지점입니다. 샘플이 많지 않아서 그런지, 잠깐 아차하면 Stage2 의 문법으로 덮어 쓰고 있더군요.

stage3 문법은 기존의 stage2 보다 훨씬 더, 익숙한 Python 의 @ Decorator 구문과 흡사한 방식으로 작동합니다. 작년, 막 이 기능을 습작하던 초기에는 stage 2 문법이 너무 복잡해서 꽤나 애를 먹기도 했습니다만. stage3 로 넘어오자 많은 부분들이 간단하게 해결됐습니다.

AsyncGenerator 셋 중에서는 개중 가장 오래된(?) 기법입니다. 반복자(Iterator) 패턴 대신 생성자(Generator) 패턴을 적용하는데, js의 비동기(Async)에 대한 생성자를 접목하면서 병렬 처리와… 일단 빠릅니다. 빠르고요, 특히 모든 기능들이 비동기일 수 밖에 없는 Service Worker 기반의 기능에 붙이기가 좋습니다. 관련된 내용을 찾다보면 “요새 모든 코드가 AsyncGenerator 밖에 없다” 는 푸념이 나올 정도입니다. 뭐 사실… js/ts 가 아니라도 yield coroutine 은 요새 꽤 흔하니까요.

Get 테크리드 오답노트’s stories in your inbox

Join Medium for free to get updates from this writer.

Generator 구문은 함수명에 *(Asterisk)를 붙입니다. 이를테면:

// anonymous 생성자 선언
const generator = function* (){
for (const it of arguments) {
// yield 로 이벤트 루프를 빠져나갑니다
yield it;
}
}

// 생성자 사용
for(const gen of generator()) {
console.log(gen);
}

이런 식입니다. 그 밖에도 Iterator를 반환하는 방법도 있습니다만 사실 잘 쓸 것 같지는 않구요.

이때 Generator 함수가 비동기(Async)로 Promise 인스턴스를 양도(yield)하면 비동기 생성자(AsyncGenerator) 입니다. 개인적으로 Sync Generator 는 기존의 Iterator에 비해 전혀 차이가 없어 용도가 애매한 반면, Asnyc 환경에서는 구조/성능에서 극단적인 차이를 가져올 수 있다고 전망하고 있습니다.

Business Aspect

dxnlab/idb 프로젝트는 사실 개인적인 용도가 가장 깊습니다. 앞서 설명한 것과 마찬가지로 IndexedDB는 여러 장점이 있으나, 그 데이터가 평문으로 노출될 수 있다는 단 하나의 단점 때문에 널리 활용되기에는 한계가 있습니다.

하지만 평문으로 노출이 되어도 상관 없는 정보들이라면 어떨까?

이 프로젝트는 물론, idb 를 처음 접하던 시기에 이 블로그에서 데이터의 소유와 존재; 유통 단가가 바꾸는 데이터/지식의 비즈니스 변화에 대해 설명한 적이 있습니다. 가령 이렇게 생각해 볼까요: ‘만약 필요한 대부분의 데이터를, 고정된 서버에 저장하는 것이 아니라, 로컬 또는 외부 클라우드를 기반으로 필요한 분량만 그때그때 받아서 처리하는 방식으로 웹 서비스의 판도가 바뀐다면?’

지금은 서비스 유지/운영에 상당한 비용이 들어갑니다. 잘은 몰라도 데이터의 저장과 이리저리 옮기는 트래픽 비용이 절반은 넘을 겁니다. 개중 상당수 데이터는 사실, 사일로 마이크로서비스 탓에 분절/중첩 되어 있거나, 외부에 공개되어 있거나, 혹은 과거에 대한 로컬 기록이거나, 합니다.

결국 어떤 기능이던 데이터를 옮기거나 연산하는데, 지금의 서비스는 거의 전부가 데이터를 /안전한/ 내부로 가져와서 구조화하고 쌓고 적절하게 배분하는 데 중점을 두고 있습니다. 실상, 필요한 시점에 적절한 데이터가 반드시 존재한다고 가정하면 — 흔히 이야기하는 비즈니스 로직 Business Logic, 즉 서비스의 핵심 기능은 데이터의 저장이나 구조화와 전혀 연관이 없는데도 말입니다. 모든 데이터를 자체적으로 ‘소유’해야만 비즈니스 로직을 시작할 수 있다. 나는 이것이 현재 데이터 비즈니스가 안고 있는 구조적인 한계점이라 생각합니다.

만약 외부에서 안정적으로 수급할 수 있는 원본 데이터, 혹은 고정된 로컬에서만 참조하는 데이터를 서버에서 다루지 않는다고 생각하면 — 적지 않은 서비스는 데이터베이스 중심이 아닌, 데이터 프로세싱 중심으로 바뀝니다. 서비스의 유지/운영이 훨씬 간소해지는 것은 부가적이고 말입니다.

게다가 보안과 개인정보 보호 측면에서도 훨씬 낫습니다. 뭐가 있을까요. 예를 들어 개인적으로 관심이 많은 데이터 시각화 솔루션 (Tableau 나 Looker, PowerBI와 Flourish 같은)을 볼까요. 대부분의 데이터 시각화 솔루션은 내/외부의 데이터베이스를 연결해서, 내부 자료형으로 구조화 한 뒤에, 다종 다양한 차트/그래프에 필터를 입혀 대시보드 리포트의 형태로 서빙합니다.

원하는 결과가 대시보드 리포트라면. 그리고 대시보드 리포트를 구성하기 위해 필요한 데이터가 로컬 파일이던, 외부 데이터베이스던 해당 시점에 가져 올 수만 있다면, 그 방법만 지정되어 있다면 그 수 많은 데이터 시각화 솔루션은 대시보드를 위한 데이터를 주기적으로 갱신/캐싱할 필요가 없습니다.

빅데이터 쿼리라면 (지금도 느린데) 캐싱 없이 느려지지 않겠는가? 대시보드 만들 때 raw DB 내용을 일일이 다 노출시키는 경우가 얼마나 됩니까? 필요한 내용만 적당한 위치에 캐싱해 둘 수 있다면, 실제로 그 서비스가 갖고 있어야만 할 데이터의 분량은 생각보다 얼마 되지 않습니다. 개인적으로는 대부분의 서비스에 DB가 필요 없는 수준까지 갈 것으로 봅니다.

이러한 비즈니스의 변화를 따라가려면 결국 로컬 브라우저에서 과거와는 비교도 되지 않을 만큼 다량의 데이터를 적절하게 구조화해서 처리하는게 필요한데, idb가 바로 그 단초라 기대하고 있습니다. 다른 모든 제품의 마중물이라 보아도 틀림이 없을듯 합니다.

dxnlab

아주 오래 전에 개인 브랜드의 일환으로, dxn 이라는 이름을 떠올렸습니다. 스스로 꽤 오랫동안 관심을 두고 있던 — Data/Dynamics by Network 의 약자라는 나름(?)의 소신은 있습니다만, 이제는 그저 식별 코드 정도로 생각합니다. 그 이상이 되면 부끄러울 것 같습니다. 여러 전차로 개인 브랜드를 소심하게 시작하게 되었습니다. 그리고 그 이름을 달고 첫 제품인 dxnlab/idb 가 더더욱 소심하게, 세상에 나왔습니다. 어쨌거나 지금은 첫 제품이 세상에 나왔다는 사실 자체에 의의를 두려고 합니다. 굵직한 한 획을 그으려면 한참 더 많은 시행착오가 필요할테니, 말입니다.

두려움을 안고 한 발 앞으로 가고 있습니다. 계속.

덧. 개발 환경에서 Syntax Error 로 실행이 안 된다면 —

Decorator 구문은 TypeScript에서만 허용되고, 현재 ES 엔진 대다수가 지원하지 않습니다! 때문에 단순 Transpile 기반으로 실행되는 (대표적으로 Vite) 개발 환경에서는 @ 구문부터 오류가 발생하는데요. 관련 내용은 https://github.com/dxnlab/idb#vite--oxc 에서 설명하고 있습니다. 좀 번거롭지만, babel 을 통해서 아예 번들링해서 실행하면 문제가 없습니다. 달리 말해, 빌드하면 구문 문제는 사라집니다!

--

--

테크리드 오답노트
테크리드 오답노트

Written by 테크리드 오답노트

“세상에 정답은 없어. 하지만 오답은 있지” 1X년 쌓여가는 테크리드의 오답노트