왜 bookclub app 인가?

나는 책읽는 걸 좋아한다. 책 읽는 행위를 넘어 활자를 읽는 모든 행위를 좋아한다. (심지어는 거리에 있는 간판을 읽는 것도 좋아한다) 그런 내가 매년 새해 다짐으로 꼭 한 줄씩 채워넣는 게 있는데, ‘책을 읽고 짧은 생각과 질문 작성하기’이다. 책을 읽고 나서 기록을 남기거나 누군가와 이야기를 나누지 않으면 너무 빨리 휘발되는 느낌이 들어서다.
그래서 기록 + 토론 정리에 특화된 독서 모임 앱을 만들어보기로 했다.
원래 올해 목표가 수익을 창출할 수 있는 toy project를 만드는 것이었는데, 수익 창출을 목표로 하는 건 아니고 나와 내 친구들이 함께 나눌 수 있는 정도의 수준부터 시작하려고 한다. 우선 app의 이름은 bookclub app 이라고 하였지만 이름은 차차 생각해보는 걸로..!
MVP 범위 정하기
사이드 프로젝트에서 가장 중요한 건 스코프 관리다. 만들고 싶은 기능은 끝이 없지만, 출시를 못 하면 의미가 없다. 원칙을 하나 세웠다.
기능을 줄이되, 구조는 확장 가능하게
만들 것 (MVP)
- 인증 - 이메일/소셜 로그인
- 책 + 개인 기록 - 책 검색/등록, 하이라이트, 메모, 내 서재
- 모임 - 생성, 초대 코드로 참여, 이번 달 책 지정
- 토론 보드 - 모임별 질문 스레드, 댓글, 모임장 수기 요약
만들지 않을 것
- AI 자동 요약 / 녹음 회의록
- 독서 통계 리포트
- 독서 메이트 매칭
- 소셜 피드 / 팔로우
이런 기능들은 2차 스코프로 미뤘다. 나중에 붙이기 쉬운 구조만 지금 잡아두면 된다.
기술 스택 선정
혼자 개발하는 사이드 프로젝트에서 가장 중요한 건 생산성이다. 최대한 적은 코드로, 빠르게, iOS와 Android를 동시에 커버해야 한다.
| 영역 | 선택 | 이유 |
|---|---|---|
| 런타임 | Expo (managed workflow) | iOS/Android 동시 빌드, OTA 업데이트 |
| 언어 | TypeScript (strict) | 타입 안정성 |
| 라우팅 | Expo Router | 파일 기반 라우팅, 딥링크 쉬움 |
| 상태관리 | Zustand | 가볍고 boilerplate 없음 |
| 서버 상태 | TanStack Query | 캐싱, 동기화, mutation 패턴 |
| 백엔드 | Supabase | Auth + Postgres + Storage + Realtime |
| 스타일 | StyleSheet.create | MVP는 UI 라이브러리 없이 기본으로 |
| 책 검색 | 카카오 책 검색 API | 국내 서비스 기준 안정적 |
왜 Supabase인가
별도 백엔드 서버를 만들지 않기로 했다. Supabase 하나로 인증, 데이터베이스, API, 보안(RLS)을 전부 해결할 수 있다. PostgreSQL 기반이라 나중에 다른 곳으로 마이그레이션도 가능하다. 이 부분은 다음 글에서 자세히 다룬다.
의존성 추가 원칙
- 추가 전에 필요성을 한 번 더 검토. 직접 짜는 게 더 간단하면 그렇게.
- UI 라이브러리(NativeBase, Tamagui 등) 도입 금지. 기본 컴포넌트로 시작.
- 상태관리는 Zustand 하나만.
폴더 구조 설계
확장성을 위해 도메인별 feature 폴더 구조를 채택했다.
app/ # Expo Router. 라우트만.
├── (auth)/ # 비로그인 사용자
├── (tabs)/ # 탭 네비게이션
├── book/[id].tsx
└── club/[id]/
src/
├── features/ # 도메인별 모듈
│ ├── auth/
│ ├── books/
│ ├── clubs/
│ └── discussions/
│ ├── api.ts # Supabase 호출
│ ├── hooks.ts # TanStack Query 훅
│ ├── types.ts
│ └── components/ # 도메인 전용 UI
├── components/ # 공용 UI (Button, Input)
├── lib/ # 외부 서비스 클라이언트
├── stores/ # Zustand
├── hooks/ # 공용 훅
├── types/ # 전역 타입
└── utils/
핵심 원칙:
app/은 얇게. 비즈니스 로직 없이features/의 훅을 호출만.- 도메인별 완결.
features/clubs/안에서 clubs 관련 코드가 전부 끝남. - Supabase 호출은 반드시
api.ts를 통해서. 화면에서 직접 DB 호출 금지.
새 기능 추가 순서
기능을 추가할 때는 항상 이 순서를 따른다:
types.ts에 타입 정의- Supabase 마이그레이션 (필요시)
api.ts에 데이터 함수hooks.ts에 TanStack Query 훅components/에 UIapp/에 라우트 연결
타입부터 시작하면 나머지 코드를 짤 때 자동완성의 도움을 받을 수 있고, api → hooks → UI 순서로 쌓으면 각 레이어가 아래 레이어에만 의존하게 된다.
다음 글에서는
Supabase를 백엔드로 사용하는 방법을 정리한다. 테이블 설계, RLS(Row Level Security) 정책, Auth 연동까지.
이 시리즈는 독서 모임 앱 “북클럽”을 만드는 과정을 기록합니다.
- [bookclub 개발기] #1 MVP 기획과 기술 스택 선정 (현재 글)
- [bookclub 개발기] #2 Supabase로 백엔드 한 방에 해결하기