개요
BookLore는 셀프호스팅 전자책 라이브러리 관리 시스템입니다. Calibre의 현대적 대안으로, 아름다운 UI, 자동 메타데이터 수집, Kobo/KOReader 동기화, OPDS 지원, 내장 리더를 제공합니다. “전자책을 위한 Jellyfin”이라고 불립니다.
| 항목 | 내용 |
|---|---|
| GitHub | https://github.com/booklore-app/booklore |
| 공식 사이트 | https://booklore.org |
| 문서 | https://booklore-app.github.io/booklore-docs |
| 데모 | https://demo.booklore.org |
| 라이선스 | AGPL-3.0 |
| GitHub Stars | 10K+ |
BookLore란?
왜 BookLore인가?
기존 전자책 관리 도구들의 문제점:
- Calibre: 강력하지만 UI가 오래됨, 웹 인터페이스 부족
- Calibre-Web: 기능 제한, 설정 복잡
- 폴더 기반: 메타데이터 없음, 검색 어려움
BookLore는 이 모든 것을 해결합니다:
✅ 현대적이고 깔끔한 UI
✅ 자동 메타데이터 수집 (Goodreads, Amazon, Google Books)
✅ 내장 EPUB/PDF/CBZ 리더
✅ Kobo & KOReader 동기화
✅ OPDS 서버
✅ 멀티 유저 지원
✅ Magic Shelves (스마트 플레이리스트)
✅ BookDrop 자동 가져오기
핵심 철학
"전자책 라이브러리를 위한 Jellyfin/Plex"
- 아름다운 인터페이스
- 자동화된 메타데이터
- 어디서든 접근 가능
- 프라이버시 보장
주요 기능
📚 라이브러리 관리
| 기능 | 설명 |
|---|---|
| Libraries | 책 폴더 경로 기반 라이브러리 |
| Shelves | 커스텀 책장 |
| Magic Shelves | 규칙 기반 자동 컬렉션 |
| 필터 & 검색 | 빠른 전체 텍스트 검색 |
| 시리즈 그룹 | 시리즈 자동 감지 및 그룹화 |
🧠 메타데이터
| 기능 | 설명 |
|---|---|
| 자동 수집 | Google Books, Amazon, Goodreads, Hardcover, Open Library |
| 커버 이미지 | 자동 다운로드 |
| 설명/리뷰 | 책 설명, 커뮤니티 리뷰 |
| 수동 편집 | 모든 메타데이터 직접 편집 |
| ISBN 감지 | EPUB에서 ISBN 자동 추출 |
📖 내장 리더
| 형식 | 지원 |
|---|---|
| EPUB | ✅ 주석, 하이라이트, 북마크 |
| ✅ 스트리밍 읽기 | |
| CBZ/CBR | ✅ 만화/코믹스 |
| MOBI/AZW3 | ✅ |
| FB2 | ✅ |
📱 디바이스 동기화
| 기능 | 설명 |
|---|---|
| Kobo 동기화 | Kobo 기기와 라이브러리 동기화 |
| KEPUB 변환 | EPUB → KEPUB 자동 변환 |
| KOReader 동기화 | 읽기 진행률 양방향 동기화 |
| OPDS | 모든 OPDS 호환 앱 연결 |
| Komga API | Mihon, Komelia 연결 |
👥 멀티 유저
| 기능 | 설명 |
|---|---|
| 계정 관리 | 관리자/사용자 계정 |
| 권한 제어 | 라이브러리별 접근 권한 |
| 개인 노트 | 사용자별 개인 메모 |
| 읽기 진행 | 사용자별 진행률 추적 |
📥 BookDrop
| 기능 | 설명 |
|---|---|
| 자동 감지 | 폴더에 파일 드롭 |
| 메타데이터 추출 | 파일명/내장 데이터에서 추출 |
| 미리보기 & 검토 | 가져오기 전 확인 |
| 일괄 가져오기 | 대량 책 추가 |
🔐 인증
| 방식 | 설명 |
|---|---|
| 로컬 계정 | 기본 JWT 인증 |
| OIDC | Authentik, Authelia, Pocket ID |
| Remote Auth | 리버스 프록시 인증 |
📊 통계 & 차트
| 기능 | 설명 |
|---|---|
| 읽기 통계 | 독서 진행, 완료 |
| Taste Ratings | 취향 평점 |
| Reading Backlog | 읽을 책 백로그 |
| Series Progress | 시리즈 진행률 |
대안 비교
| 기능 | BookLore | Calibre-Web | Kavita | Komga |
|---|---|---|---|---|
| 대상 | 전자책 | 전자책 | 전자책/만화 | 만화/전자책 |
| UI | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 자동 메타데이터 | ✅ 다중 소스 | ✅ 제한적 | ✅ | ✅ |
| 내장 리더 | ✅ EPUB/PDF/CBZ | ✅ | ✅ | ✅ |
| Kobo 동기화 | ✅ | ❌ | ❌ | ❌ |
| KOReader 동기화 | ✅ | ❌ | ❌ | ❌ |
| OPDS | ✅ | ✅ | ✅ | ✅ |
| Magic Shelves | ✅ | ❌ | ❌ | ❌ |
| BookDrop | ✅ | ❌ | ❌ | ❌ |
| 멀티 유저 | ✅ | ✅ | ✅ | ✅ |
| 설치 난이도 | 쉬움 | 중간 | 쉬움 | 쉬움 |
선택 가이드
| 용도 | 추천 |
|---|---|
| 전자책 + Kobo/KOReader | BookLore |
| Calibre 라이브러리 연동 | Calibre-Web |
| 만화/코믹스 중심 | Komga, Kavita |
| 라이트노벨/만화 + 전자책 | Kavita |
시스템 요구 사항
| 항목 | 최소 | 권장 |
|---|---|---|
| CPU | 1 코어 | 2+ 코어 |
| RAM | 1GB | 2GB+ |
| 저장소 | 책 크기에 따라 | – |
| 포트 | 6060 | – |
| 데이터베이스 | MariaDB | MariaDB |
Docker 설치
방법 1: 기본 설치
디렉토리 생성:
mkdir -p ~/booklore/{config/mariadb,data,books,bookdrop}
cd ~/booklore
.env 파일:
# Application
APP_USER_ID=1000
APP_GROUP_ID=1000
TZ=Asia/Seoul
# Database
DATABASE_URL=jdbc:mariadb://mariadb:3306/booklore
DB_USER=booklore
DB_PASSWORD=ChangeMe_BookLore_2025!
# Storage: LOCAL (default) or NETWORK (NFS/SMB)
DISK_TYPE=LOCAL
# MariaDB
DB_USER_ID=1000
DB_GROUP_ID=1000
MYSQL_ROOT_PASSWORD=ChangeMe_MariaDBRoot_2025!
MYSQL_DATABASE=booklore
docker-compose.yml:
services:
booklore:
image: booklore/booklore:latest
container_name: booklore
restart: unless-stopped
depends_on:
mariadb:
condition: service_healthy
ports:
- "6060:6060"
volumes:
- ./data:/app/data
- ./books:/books
- ./bookdrop:/bookdrop
environment:
- TZ=${TZ}
- APP_USER_ID=${APP_USER_ID}
- APP_GROUP_ID=${APP_GROUP_ID}
- DATABASE_URL=${DATABASE_URL}
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
- DISK_TYPE=${DISK_TYPE}
mariadb:
image: lscr.io/linuxserver/mariadb:latest
container_name: booklore-mariadb
restart: unless-stopped
volumes:
- ./config/mariadb:/config
environment:
- PUID=${DB_USER_ID}
- PGID=${DB_GROUP_ID}
- TZ=${TZ}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${DB_USER}
- MYSQL_PASSWORD=${DB_PASSWORD}
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
실행:
docker compose up -d
접속: http://localhost:6060
방법 2: 다중 라이브러리
services:
booklore:
image: booklore/booklore:latest
container_name: booklore
restart: unless-stopped
depends_on:
mariadb:
condition: service_healthy
ports:
- "6060:6060"
volumes:
- ./data:/app/data
# 다중 라이브러리 폴더
- ./books/fiction:/books/fiction
- ./books/nonfiction:/books/nonfiction
- ./books/comics:/books/comics
- ./bookdrop:/bookdrop
environment:
- TZ=Asia/Seoul
- APP_USER_ID=1000
- APP_GROUP_ID=1000
- DATABASE_URL=jdbc:mariadb://mariadb:3306/booklore
- DB_USER=booklore
- DB_PASSWORD=ChangeMe_BookLore_2025!
- DISK_TYPE=LOCAL
mariadb:
image: lscr.io/linuxserver/mariadb:latest
container_name: booklore-mariadb
restart: unless-stopped
volumes:
- ./config/mariadb:/config
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Seoul
- MYSQL_ROOT_PASSWORD=ChangeMe_MariaDBRoot_2025!
- MYSQL_DATABASE=booklore
- MYSQL_USER=booklore
- MYSQL_PASSWORD=ChangeMe_BookLore_2025!
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
방법 3: NFS/SMB 네트워크 스토리지
services:
booklore:
image: booklore/booklore:latest
container_name: booklore
restart: unless-stopped
depends_on:
mariadb:
condition: service_healthy
ports:
- "6060:6060"
volumes:
- ./data:/app/data
- /mnt/nas/books:/books
- ./bookdrop:/bookdrop
environment:
- TZ=Asia/Seoul
- APP_USER_ID=1000
- APP_GROUP_ID=1000
- DATABASE_URL=jdbc:mariadb://mariadb:3306/booklore
- DB_USER=booklore
- DB_PASSWORD=ChangeMe_BookLore_2025!
# NFS/SMB 사용 시 필수
- DISK_TYPE=NETWORK
mariadb:
image: lscr.io/linuxserver/mariadb:latest
container_name: booklore-mariadb
restart: unless-stopped
volumes:
- ./config/mariadb:/config
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Seoul
- MYSQL_ROOT_PASSWORD=ChangeMe_MariaDBRoot_2025!
- MYSQL_DATABASE=booklore
- MYSQL_USER=booklore
- MYSQL_PASSWORD=ChangeMe_BookLore_2025!
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
⚠️
DISK_TYPE=NETWORK은 NFS/SMB 사용 시 필수입니다. 파일 재구성 기능이 비활성화되어 데이터 손상을 방지합니다.
방법 4: OIDC 인증 (Authentik)
services:
booklore:
image: booklore/booklore:latest
container_name: booklore
restart: unless-stopped
depends_on:
mariadb:
condition: service_healthy
ports:
- "6060:6060"
volumes:
- ./data:/app/data
- ./books:/books
- ./bookdrop:/bookdrop
environment:
- TZ=Asia/Seoul
- APP_USER_ID=1000
- APP_GROUP_ID=1000
- DATABASE_URL=jdbc:mariadb://mariadb:3306/booklore
- DB_USER=booklore
- DB_PASSWORD=ChangeMe_BookLore_2025!
- DISK_TYPE=LOCAL
# OIDC 설정
- OIDC_ENABLED=true
- OIDC_ISSUER=https://auth.example.com/application/o/booklore/
- OIDC_CLIENT_ID=your-client-id
- OIDC_CLIENT_SECRET=your-client-secret
- OIDC_REDIRECT_URI=https://books.example.com/auth/oidc/callback
mariadb:
image: lscr.io/linuxserver/mariadb:latest
container_name: booklore-mariadb
restart: unless-stopped
volumes:
- ./config/mariadb:/config
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Seoul
- MYSQL_ROOT_PASSWORD=ChangeMe_MariaDBRoot_2025!
- MYSQL_DATABASE=booklore
- MYSQL_USER=booklore
- MYSQL_PASSWORD=ChangeMe_BookLore_2025!
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
방법 5: Traefik + HTTPS
services:
booklore:
image: booklore/booklore:latest
container_name: booklore
restart: unless-stopped
depends_on:
mariadb:
condition: service_healthy
volumes:
- ./data:/app/data
- ./books:/books
- ./bookdrop:/bookdrop
environment:
- TZ=Asia/Seoul
- APP_USER_ID=1000
- APP_GROUP_ID=1000
- DATABASE_URL=jdbc:mariadb://mariadb:3306/booklore
- DB_USER=booklore
- DB_PASSWORD=ChangeMe_BookLore_2025!
- DISK_TYPE=LOCAL
networks:
- traefik_network
- internal
labels:
- "traefik.enable=true"
- "traefik.http.routers.booklore.rule=Host(`books.example.com`)"
- "traefik.http.routers.booklore.entrypoints=websecure"
- "traefik.http.routers.booklore.tls.certresolver=letsencrypt"
- "traefik.http.services.booklore.loadbalancer.server.port=6060"
mariadb:
image: lscr.io/linuxserver/mariadb:latest
container_name: booklore-mariadb
restart: unless-stopped
volumes:
- ./config/mariadb:/config
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Seoul
- MYSQL_ROOT_PASSWORD=ChangeMe_MariaDBRoot_2025!
- MYSQL_DATABASE=booklore
- MYSQL_USER=booklore
- MYSQL_PASSWORD=ChangeMe_BookLore_2025!
networks:
- internal
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
networks:
traefik_network:
external: true
internal:
driver: bridge
방법 6: Remote Auth (리버스 프록시 인증)
services:
booklore:
image: booklore/booklore:latest
container_name: booklore
restart: unless-stopped
depends_on:
mariadb:
condition: service_healthy
ports:
- "6060:6060"
volumes:
- ./data:/app/data
- ./books:/books
- ./bookdrop:/bookdrop
environment:
- TZ=Asia/Seoul
- APP_USER_ID=1000
- APP_GROUP_ID=1000
- DATABASE_URL=jdbc:mariadb://mariadb:3306/booklore
- DB_USER=booklore
- DB_PASSWORD=ChangeMe_BookLore_2025!
- DISK_TYPE=LOCAL
# Remote Auth (리버스 프록시 인증)
- REMOTE_AUTH_ENABLED=true
- REMOTE_AUTH_HEADER=X-Remote-User
- REMOTE_AUTH_EMAIL_HEADER=X-Remote-Email
mariadb:
image: lscr.io/linuxserver/mariadb:latest
container_name: booklore-mariadb
restart: unless-stopped
volumes:
- ./config/mariadb:/config
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Seoul
- MYSQL_ROOT_PASSWORD=ChangeMe_MariaDBRoot_2025!
- MYSQL_DATABASE=booklore
- MYSQL_USER=booklore
- MYSQL_PASSWORD=ChangeMe_BookLore_2025!
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
환경 변수
애플리케이션
| 변수 | 설명 | 기본값 |
|---|---|---|
TZ | 타임존 | Etc/UTC |
APP_USER_ID | 실행 UID | 1000 |
APP_GROUP_ID | 실행 GID | 1000 |
BOOKLORE_PORT | 웹 포트 | 6060 |
데이터베이스
| 변수 | 설명 |
|---|---|
DATABASE_URL | JDBC 연결 문자열 |
DB_USER | DB 사용자 |
DB_PASSWORD | DB 비밀번호 |
스토리지
| 변수 | 설명 | 기본값 |
|---|---|---|
DISK_TYPE | LOCAL 또는 NETWORK | LOCAL |
⚠️ NFS/SMB 사용 시
DISK_TYPE=NETWORK필수
OIDC
| 변수 | 설명 |
|---|---|
OIDC_ENABLED | OIDC 활성화 |
OIDC_ISSUER | OIDC Issuer URL |
OIDC_CLIENT_ID | 클라이언트 ID |
OIDC_CLIENT_SECRET | 클라이언트 시크릿 |
OIDC_REDIRECT_URI | 콜백 URI |
Remote Auth
| 변수 | 설명 |
|---|---|
REMOTE_AUTH_ENABLED | Remote Auth 활성화 |
REMOTE_AUTH_HEADER | 사용자명 헤더 |
REMOTE_AUTH_EMAIL_HEADER | 이메일 헤더 |
초기 설정
1) 첫 접속
URL: http://localhost:6060
→ 관리자 계정 생성
2) 라이브러리 추가
- Settings → Libraries
- Add Library 클릭
- 경로 입력 (예:
/books또는/books/fiction) - Scan Now
3) BookDrop 활용
# 새 책 추가
cp /path/to/new-books/*.epub ~/booklore/bookdrop/
# BookLore가 자동 감지
# UI → BookDrop에서 검토 및 가져오기
4) 메타데이터 설정
Settings → Metadata Providers:
- Google Books (기본)
- Amazon
- Open Library
- Goodreads (API 키 필요)
- Hardcover
우선순위 설정 가능
사용 가이드
Magic Shelves (스마트 컬렉션)
예시 규칙:
| 이름 | 규칙 |
|---|---|
| 읽을 책 | status = "unread" |
| 올해 완독 | status = "read" AND year = 2025 |
| SF 소설 | genre = "Science Fiction" |
| 시리즈 미완 | series != null AND seriesComplete = false |
KOReader 동기화
설정:
- BookLore: Settings → Integrations → KOReader
- API 토큰 생성
- KOReader: Settings → Cloud Storage → Custom sync server
- URL:
https://books.example.com/api/koreader
동기화 내용:
- 읽기 진행률
- 북마크
- 하이라이트
OPDS 연결
OPDS URL:
https://books.example.com/opds
호환 앱:
- KOReader
- Moon+ Reader
- Librera
- FBReader
- Thorium Reader
Kobo 동기화
- BookLore: Settings → Integrations → Kobo
- 동기화 활성화
- Kobo 기기에서 BookLore 서버 설정
- EPUB → KEPUB 자동 변환
이메일로 책 보내기
- Settings → Email
- SMTP 설정
- 책 상세 페이지 → Share → Send to Email
- Kindle 이메일 주소로 전송 가능
백업 및 복원
데이터 구조
~/booklore/
├── config/mariadb/ # MariaDB 데이터
├── data/ # BookLore 앱 데이터 (설정, 메타데이터, 캐시)
├── books/ # 책 파일
└── bookdrop/ # 가져오기 폴더
백업
# 컨테이너 정지
docker compose down
# 전체 백업
tar -czvf booklore-backup-$(date +%Y%m%d).tar.gz \
config/ data/ books/
# 컨테이너 재시작
docker compose up -d
MariaDB 덤프
docker compose exec mariadb mysqldump -u booklore -p booklore > backup.sql
복원
# 백업 해제
tar -xzvf booklore-backup.tar.gz
# 컨테이너 시작
docker compose up -d
업데이트
cd ~/booklore
# 백업 먼저!
tar -czvf booklore-backup-$(date +%Y%m%d).tar.gz config/ data/
# 최신 이미지
docker compose pull
# 재시작
docker compose down
docker compose up -d
# 로그 확인
docker compose logs -f booklore
트러블슈팅
권한 오류
# UID/GID 확인
id
# .env에서 설정
APP_USER_ID=1000
APP_GROUP_ID=1000
NFS/SMB 파일 이동 실패
environment:
- DISK_TYPE=NETWORK
메타데이터 수집 안 됨
- Settings → Metadata Providers 확인
- 네트워크 연결 확인
- API 키 필요한 경우 (Goodreads 등)
데이터베이스 연결 실패
# MariaDB 상태 확인
docker compose logs mariadb
# healthcheck 확인
docker compose ps
이미지 태그
| 태그 | 설명 |
|---|---|
latest | 최신 안정 버전 |
v1.x.x | 특정 버전 |
활용 사례
1. 개인 전자책 라이브러리
목적: 전자책 체계적 관리
- 소설, 비소설, 기술서 라이브러리 분리
- 자동 메타데이터로 깔끔한 정리
- 내장 리더로 어디서든 읽기
- 읽기 진행률 추적
2. KOReader + BookLore
목적: 이북 리더 연동
- KOReader로 읽기
- 진행률 자동 동기화
- OPDS로 무선 다운로드
- 여러 기기에서 이어 읽기
3. Kobo 전자책 관리
목적: Kobo 기기 활용
- Kobo와 라이브러리 동기화
- EPUB → KEPUB 자동 변환
- 표지/메타데이터 전송
- Kobo 내장 리더 진행률 동기화
4. 가족 라이브러리
목적: 가족 공유
- 멀티 유저 계정
- 라이브러리별 권한
- 개인 책장, 읽기 진행
- 아이들 콘텐츠 분리
5. 만화/코믹스 + 전자책
목적: 통합 라이브러리
- EPUB, PDF, CBZ 모두 지원
- 시리즈 자동 그룹화
- Magic Shelf로 미완 시리즈 추적
- Komga 앱 (Mihon) 연결
마무리
BookLore는 전자책 라이브러리의 새로운 표준입니다. Calibre의 복잡함 없이, 현대적인 UI와 강력한 기능으로 전자책을 관리할 수 있습니다.
핵심 장점
| 장점 | 설명 |
|---|---|
| 현대적 UI | 2025년에 걸맞은 깔끔한 인터페이스 |
| 자동 메타데이터 | Google, Amazon, Goodreads 연동 |
| Kobo/KOReader | 이북 리더 양방향 동기화 |
| OPDS | 모든 리딩 앱 연결 |
| Magic Shelves | 스마트 자동 컬렉션 |
| BookDrop | 드래그 앤 드롭 가져오기 |
| 내장 리더 | EPUB/PDF/CBZ 브라우저 읽기 |
| 멀티 유저 | 가족/팀 공유 |
이런 분께 추천
전자책을 체계적으로 관리하고 싶은 분
Calibre UI가 마음에 안 드는 분
Kobo나 KOReader를 사용하는 분
어디서든 전자책에 접근하고 싶은 분
가족과 전자책을 공유하고 싶은 분
"전자책용 Jellyfin"을 찾는 분