SQLite를 Rails 애플리케이션에 통합할 때 고려해야 할 주요 차이점과 문제점, 그리고 해결 방안은 다음과 같습니다.
SQLite의 본질적인 특성과 운영 문제
- 인메모리 및 단일 파일 구조: SQLite는 웹 서버 프로세스 내에 내장되며 모든 데이터가 단일 파일에 저장되어 DB 연결 오류를 줄입니다. 하지만 컨테이너 환경에서 임시 파일 시스템에 저장될 경우 재시작 시 데이터가 소실됩니다.
- 해결책: AWS EBS, Fly.io Volumes와 같은 영구 스토리지에 DB 파일을 저장하고 자동 스냅샷을 설정해야 합니다.
- 단일 파일에 모든 데이터 집중: 모델, 캐시, ActiveJob 큐 등이 동일 파일에 저장됩니다. 백그라운드 잡이 모델을 업데이트할 때, 웹 서버와 워커가 동일 파일에 접근해야 하므로 워커를 별도 컨테이너로 분리하는 기존 스케일링 방식이 어렵습니다.
- 해결책: 워커를 웹 프로세스와 동일 VM 내의 별도 프로세스 또는 웹 프로세스 내 스레드로 실행해야 하며, 소규모 앱에서는 스레드 방식이 효율적입니다.
스케일링 및 동시성 관리
- 수평 스케일링의 한계: SQLite는 단일 파일 기반이므로 수평 스케일링이 불가능하며, CPU 코어와 RAM이 많은 단일 서버의 수직 스케일링에 의존해야 합니다.
- 동시 쓰기 경합: 다수의 프로세스나 스레드가 동시에 단일 DB 파일에 쓰기 작업을 시도할 경우 경합이 발생합니다.
- WAL(Write-Ahead Log) 모드: 쓰기 작업을 WAL 파일에 순차적으로 기록하고, 읽기 작업은 DB 파일에서 동시에 여러 개가 가능하도록 하여 읽기 동시성을 개선합니다. WAL 사용 시 백업 및 복구 시 여러 파일을 함께 관리해야 합니다.
- 다중 SQLite 파일 활용: ActiveRecord, 캐시, 백그라운드 잡 등 용도별로 별도의 SQLite 파일을 사용하면 각 시스템 간의 경합을 줄이고 성능을 최적화할 수 있습니다.
배포 및 복제 솔루션
- 단일 서버 의존성: 서버 다운 시 전체 서비스가 중단되며, 컨테이너 환경에서는 무중단 배포가 어렵습니다. 다만, 디버깅 및 문제 해결이 단일 서버에 집중되어 간소화되는 장점도 있습니다.
- 데이터베이스 마이그레이션:
sequel
gem이나duckdb
CLI 툴을 통해 SQLite와 다른 DB 간의 전환을 지원합니다. - Litestream: WAL 기반으로 변경 사항을 S3 호환 스토리지에 스트리밍하여 재해 복구를 지원합니다.
- LiteFS: FUSE 기반 파일 시스템을 사용하여 다중 SQLite DB에 MySQL/Postgres와 유사한 분산 복제 기능을 제공하지만, 분산 시스템 고유의 복잡성과 트레이드오프를 수반합니다.