node:sqlite 를 실서비스에 써보고
이 사이트의 로또 회차 데이터는 국가별로 1,000회차씩, 총 수천 행을 들고 있습니다. 처음엔 JSON 파일에 통째로 넣었는데, 회차가 쌓이면서 매 요청마다 파일 전체를 파싱하는 게 아까웠습니다.
도입 이유
better-sqlite3 같은 네이티브 모듈은 배포 환경마다 빌드가 걸립니다. 반면 node:sqlite 는 런타임에 이미 들어있어서 이런 문장이면 끝입니다.
const { DatabaseSync } = await import("node:sqlite");
const db = new DatabaseSync("data/lotto/lotto.db");
db.exec("PRAGMA journal_mode = WAL");
주의한 것
- 폴백을 남겼습니다. 운영 Node 버전을 확신할 수 없어서,
import가 실패하면 조용히 JSON 백엔드로 내려갑니다. - WAL 모드. 읽기가 잦고 쓰기가 드문 워크로드라, 갱신이 읽기를 막지 않도록 했습니다.
- 트랜잭션으로 묶기. 1,000행을 한 건씩 커밋하면 디스크 동기화가 1,000번 일어납니다.
BEGIN/COMMIT으로 감쌌더니 눈에 띄게 빨라졌습니다.
한계
정적 빌드(scripts/build.js)로 뽑는 페이지는 빌드 시점의 스냅샷입니다. 동적 CRUD 가 필요하면 Node 서버 쪽에서 돌아야 합니다. 이 블로그도 같은 전제로 만들었습니다.
같은 패턴을 이 블로그에 그대로 옮겼습니다. lib/blog/db.js 는 lib/lotto/db.js 와 구조가 같습니다.