최종 확인: 2026-07-22
| 항목 | 값 |
|---|---|
| 서비스 URL | https://my-bookstations.vercel.app/ |
| 상태 | ✅ 정상 |
| 호스팅 | Vercel (프론트 + /api/search) + Cloudflare Workers (library-checker) |
| DB | Supabase (Postgres) — Auth · RPC · Edge Function 포함 |
CF Cron이 3일마다 Supabase keep_alive RPC 호출. 이 Worker가 멈추면 7일 후 무료티어 DB가 정지되어 서비스 전체가 중단된다 |
|
| 인증 | Supabase Auth (이메일/비밀번호 + OAuth) |
| 외부 API | 알라딘 TTB, 도서관 4종(광주시립·경기교육청 등), Gemini |
| 부속 Worker | https://library-checker.byungwook-an.workers.dev |
| 배포 방식 | library-checker/** 변경 시 GitHub Actions → CF 자동 배포 (프론트는 Vercel 자동) |
| 필요 환경변수 | VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY, ALADIN_TTB_KEY(서버 전용), VITE_ALADIN_TTB_KEY(로컬 개발 전용) |
알라딘 TTB 키는 프로덕션에서 서버(
api/search.ts) 경유로만 사용되며 클라이언트 번들에 포함되지 않는다.VITE_ALADIN_TTB_KEY는 로컬 Vite 프록시 전용이다.
도서 검색 및 도서관 재고 확인 서비스
알라딘 API와 연동하여 도서를 검색하고, 여러 도서관의 재고 현황을 실시간으로 확인할 수 있는 웹 애플리케이션입니다. 개인 서재 관리 기능을 통해 관심 도서를 체계적으로 관리할 수 있습니다.
- 원스톱 도서 서비스: 검색부터 재고 확인, 개인 관리까지 한 곳에서
- 실시간 재고 확인: 여러 도서관의 재고 상태를 동시에 확인
- 개인화된 서재 관리: 독서 상태, 별점, 태그, 즐겨찾기 등 체계적인 도서 관리
- 편리한 접근성: 직관적인 UI/UX로 누구나 쉽게 사용
- 알라딘 API 연동: 제목, 저자, 출판사, 전자책별 검색 및 페이지네이션 지원
- 검색 결과 필터링: '[세트]'로 시작하는 도서를 자동으로 제외하여 검색 결과의 정확성 향상
- 상세 정보 제공: 도서 정보, 가격, ISBN, 전자책 유무, 알라딘 구매 링크 등 상세 정보 표시
- 키워드 통합 검색: 단일 키워드로 여러 도서관의 소장 자료를 한 번에 검색하는 기능
- 실시간 통합 조회: 종이책(광주 시립도서관), 전자책(경기도 교육청 통합 도서관), 전자책(광주 시립도서관 구독형), 전자책(경기도 전자도서관 API) 재고를 한 번의 요청으로 동시에 확인
- 커스텀 검색어: 기본 검색어로 조회가 어려운 도서의 경우, 사용자가 직접 검색어를 지정하여 조회 정확도 향상
- 정확도 높은 재고: "정보없음" 데이터 제외(광주 시립) 등 정확한 정보 제공
- 도서관 바로가기: 재고 확인 셀 클릭 시, 해당 도서관의 도서 검색 결과 페이지로 바로 이동
- 재고 새로고침: 클릭 한 번으로 최신 재고 상태 업데이트
- 종이책: 광주 중앙, 송정, 오포, 퇴촌 도서관 및 기타 시립도서관
- 전자책: 경기도 교육청 통합전자도서관, 성남교육도서관
- 전자책: 광주 시립도서관 구독형(교보문고) 및 소장형
- 전자책: 경기도 전자도서관 (소장형+구독형 통합)
- 내 서재: 관심 도서를 개인 서재에 저장 및 관리
- 독서 기록: 읽음 상태(읽지 않음/읽는 중/완독) 및 별점(1-5점) 기록
- 🏷️ 커스텀 태그: 사용자 정의 태그 생성/편집/삭제 및 태그 기반 필터링
- ❤️ 좋아하는 책: 하트 아이콘으로 즐겨찾기 표시 및 필터링
- 📝 한 줄 메모: 책별로 최대 50자의 간단한 메모 기록 및 수정
- 🔍 서버 기반 검색: 페이지네이션과 무관하게 DB 전체를 대상으로 제목, 저자별 실시간 검색
- 다양한 정렬: 추가순, 제목순, 저자순, 출간일순, 별점순, 읽음순 정렬
- ⚡ 페이지네이션: 사용자 설정(25/50/100/200권)에 따라 초기 데이터를 부분 로딩하여 렌더링 성능 95% 개선
- 대량 작업: 여러 책을 선택하여 태그 일괄 변경, 삭제 등 대량 작업 지원
- 일괄 재고 갱신: 내 서재의 모든 책 재고 정보를 한 번에 업데이트 (최신순/오래된순/범위지정, 일시정지/재개/취소 가능)
- 데이터 내보내기: 서재 데이터를 CSV 파일로 내보내기 (파일명에 날짜 자동 포함)
- 표시 옵션: 독서 상태, 별점, 태그, 메모, 도서관 재고, 좋아요 아이콘 표시 여부 설정
- 🌙 테마 시스템: 다크/라이트/시스템 테마 선택
- 📱 모바일 최적화: 반응형 디자인으로 모든 기기에서 최적화된 경험 제공
- 기본값 설정: 관리자를 통한 신규 사용자 기본 설정값 관리
- Google 소셜 로그인: 간편한 Google 계정 연동
- 이메일 회원가입/로그인: 이메일과 비밀번호를 통한 인증
- 계정 관리: 비밀번호 변경, 프로필 관리
- 안전한 회원탈퇴: 2단계 확인 절차를 통한 계정 삭제 (Supabase Admin API 연동)
- 의견 보내기: 프로필 메뉴에서 간편한 피드백 전송
- 보안 강화: Supabase Edge Function을 통해 안전하게 피드백 처리
- 관리자 전용 페이지: 이메일 기반 권한 관리 시스템
- 주요 기능: 대량 도서 조회, API 테스트 도구, 개발 노트, 신규 사용자 기본값 설정 등
- React 19 & TypeScript
- Vite: 빠른 개발 서버 및 빌드
- Tailwind CSS Play CDN + 커스텀 CSS:
index.html의 Tailwind CDN과index.css의 디자인 토큰·공통 클래스를 함께 사용 - Lucide React: 일관성 있는 아이콘 시스템
- Zustand: 경량 상태 관리 (인증, 도서, UI, 설정별 분리)
- Supabase: PostgreSQL 데이터베이스, 인증, 실시간 동기화
- Supabase Edge Functions: 서버리스 로직 (피드백 처리)
- Cloudflare Workers: 도서관 재고 크롤링 및 키워드 검색 API
- Vercel Serverless Functions: Aladin API 프록시 처리
- Zod: 런타임 타입 검증으로 외부 API 응답 안정성 확보
- Node.js 18 이상
- pnpm
- Git
- 저장소 클론
git clone <repository-url> cd my_bookstation
- 의존성 설치
pnpm install
- 환경 변수 설정 (
.env.local파일 생성)VITE_SUPABASE_URL=your_supabase_url VITE_SUPABASE_ANON_KEY=your_supabase_anon_key VITE_ALADIN_TTB_KEY=your_aladin_ttb_key
- 개발 서버 실행
pnpm dev
- 브라우저에서 확인:
http://localhost:5173
- 🐛 데이터 유실 방지: API가 비정상 응답을 반환할 때 기존 재고 정보가
undefined로 초기화되던 심각한 버그를 수정했습니다. 이제 API 실패 시 기존 데이터를 안전하게 유지합니다. - 🔄 상태 동기화: 검색이나 필터로 표시된 책에 대해 '좋아요', 태그 추가/삭제 등 상태 변경이 즉시 반영되지 않던 문제를 해결했습니다. 모든 데이터 소스를 포괄하는 조회 로직을 적용하여 UI 일관성을 확보했습니다.
- 🎨 태그 시스템 UX 개선: 모든 뷰(책 목록, 상세 모달, 일괄 관리)에서 태그가 '색상 > 인기도 > 이름순'으로 일관되게 정렬되도록 수정했으며, 태그 추가/삭제 시 필터의 카운트가 실시간으로 업데이트되도록 개선했습니다.
- ⚡️ API 응답 캐싱: Cloudflare Cache API를 도입하여 반복적인 재고 조회 요청에 대한 응답 속도를 수 초에서 수십 밀리초 단위로 비약적으로 단축했습니다.
- 💡 직관적 에러 피드백: 재고 조회 실패 시 상세 모달에서 "조회중..."이 무한 반복되던 버그를 해결하고, 에러 상태를 명확히 표시하도록 UX를 개선했습니다.
- 🎯 조회 정확도 향상: 사용자가 직접 도서관 검색어를 지정하는 '커스텀 검색어' 기능 추가.
- 🛠️ 유지보수성 개선: 여러 컴포넌트에 흩어져 있던 도서관 바로가기 URL 생성 로직을 단일 함수로 중앙화하여 일관성을 확보하고 버그를 수정했습니다.
- 관리자 권한 시스템: 이메일 기반의 안전한 관리자 권한 부여.
- 회원탈퇴 기능: Supabase Admin API를 연동한 2단계 확인 절차로 안전성 강화.
- Race Condition 버그 수정: 사용자 설정 생성 시 발생하던 동시성 문제를 해결하여 안정성 확보.
- ⚡️ 데이터 안정성 극대화: API의 일시적인 실패에도 기존의 유효한 재고 정보가 유실되지 않도록 데이터베이스 스키마를 리팩토링하고 "선택적 폴백(Fallback)" 데이터 업데이트 전략을 도입했습니다. 이제 한번이라도 조회에 성공한 재고 정보는 API 오류에도 안전하게 보존됩니다.
- 🎨 UX 일관성 확보: 내 서재 목록에서는 항상 안정적인 마지막 재고 정보를 표시하고(실패 시 빨간색 X), 상세 모달에서만 현재의 갱신 실패 상태를 알려주도록 역할을 분담하여 사용자 경험을 크게 개선했습니다.
- ⚙️ TypeScript 전환: Cloudflare Worker(백엔드) 코드를 TypeScript로 전면 전환하여 타입 안정성을 확보하고 런타임 에러 발생 가능성을 크게 줄였습니다.
- 🚀 API 응답 캐싱: Cloudflare Cache API를 도입하여 반복적인 재고 조회 요청에 대한 응답 속도를 수 초에서 수십 밀리초 단위로 99% 이상 단축했습니다.
- 🛡️ 크롤링 안정성 강화: 도서관 서버의 봇 탐지 정책에 대응하기 위해, 실제 브라우저 헤더를 정교하게 모방하는 2단계 요청 방식을 도입하고 세션 만료 시 자동 복구 로직을 구현하여 크롤링 성공률을 대폭 향상시켰습니다.
- 🐛 데이터 무결성 보장: 책 정보 업데이트(개별/일괄) 시
id,note등 중요 데이터가 누락되거나 손상되던 근본적인 버그를 해결하여 데이터 일관성을 확보했습니다. - 🔄 상태 동기화: 검색이나 필터로 표시된 책에 대해 '좋아요', 태그 추가/삭제 등 상태 변경이 즉시 반영되지 않던 문제를 해결하여 UI 일관성을 확보했습니다.
- Cloudflare Worker의 광주시 계열 조회는 종이책(KOLAS)과 시립 소장형 전자책을 병렬로 호출하지 않습니다.
- 순서는
광주시 종이책 -> 시립 소장형 전자책이며, 두 조회의 합산 예산은 15초입니다. - 각 조회는 최대 10초까지만 기다립니다. 종이책 조회가 지연되어 남은 예산이 1초 미만이면 시립 소장형 전자책은 생략하고 기존 저장 재고를 유지합니다.
- 시립 구독형 전자책, 경기도 교육청, 경기도 전자도서관 조회는 기존처럼 별도 흐름으로 진행됩니다.
- 태그 정의(이름, 색상, 목록)는 계정별
user_settings.settings.tagSettings.tags[]에 저장됩니다. - 책별 수동·레거시 태그는
user_library.book_data.customTags[], 자동 규칙 결과는user_library.book_data.autoTags[]에 저장됩니다. - 화면 표시와 Supabase RPC의 태그 집계·필터는 두 배열을 병합해 사용합니다.
- 태그 사용 권수는
get_tag_counts_for_user, 태그 필터링은get_books_by_tagsRPC를 사용합니다. - 두 RPC의 병합 SQL 정본은
supabase/20260705_auto_tags_rpc.sql이며, 운영 적용은 별도 승인과 검증이 필요합니다. - 상세 구조와 관련 코드는 개발 가이드의
태그 데이터 모델섹션을 확인합니다.
public/manifest.webmanifest와public/icon-192.png·icon-512.png·icon-maskable-512.png로 홈 화면 추가 시 전용 아이콘과 standalone(전체화면) 실행을 지원합니다.- PWA 메타 태그(
manifest,theme-color,apple-touch-icon등)는index.html<head>에 있습니다. public/파일은 빌드 시dist/루트로 복사되어 Vercel에서 절대경로(/manifest.webmanifest등)로 서빙됩니다.- Service Worker·오프라인·푸시는 적용 범위가 아닙니다(온라인 검색 서비스 특성상 제외).
프로젝트에 기여하고 싶으시다면 이슈를 통해 버그 리포트나 기능 제안을 해주시거나, Pull Request를 통해 코드 기여를 해주세요.
이 프로젝트는 MIT 라이선스 하에 배포됩니다.
made by planninghighway 2025