Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ coverage
*.tsbuildinfo
*.pem

# Firebase Service Account (보안 민감 정보)
firebase-service-account.json

### CLAUDE ###
#/docs

Expand Down
12 changes: 11 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ deploy/
|------|------|
| Runtime | Node.js 22, TypeScript 5.x |
| Bot | discord.js v14, feedsmith (RSS 파서), pg-boss (PostgreSQL 잡 큐), Sentry (에러 모니터링) |
| Web | Next.js 16 App Router, React 19, shadcn/ui, Tailwind CSS v4, Tiptap (리치 에디터), sonner (토스트), Framer Motion (랜딩 애니메이션), Sentry (에러 모니터링) |
| Web | Next.js 16 App Router, React 19, shadcn/ui, Tailwind CSS v4, Tiptap (리치 에디터), sonner (토스트), Framer Motion (랜딩 애니메이션), Firebase (FCM 푸시 알림), Sentry (에러 모니터링) |
| DB | Supabase PostgreSQL + Drizzle ORM (Transaction Pooler, `prepare: false`) |
| Auth | Supabase Auth (Discord OAuth) + `@supabase/ssr` |
| 배포 | AWS EC2 Docker (bot), Vercel (web), Supabase (DB + Auth) |
Expand Down Expand Up @@ -104,6 +104,14 @@ pnpm --filter @blog-study/bot rss-collect # 수동 RSS 수집 (봇 없이)
| `packages/web/src/app/api/admin/bot-operations/[operationId]/route.ts` | 봇 작업 트리거 프록시 (web → bot HTTP API, 30s 타임아웃) |
| `packages/web/src/app/(admin)/admin/rounds/page.tsx` | 회차 관리 페이지 (CRUD + 현재 회차 설정) |
| `packages/web/src/app/api/profile/withdraw/route.ts` | 유저 자체 탈퇴 API |
| `packages/web/src/lib/firebase/admin.ts` | Firebase Admin SDK (lazy 초기화, `getAdminMessaging()`) |
| `packages/web/src/lib/firebase/client.ts` | Firebase 클라이언트 (FCM 토큰 요청, 포그라운드 메시지) |
| `packages/web/src/lib/push.ts` | FCM 푸시 전송 (`sendPushToMember`, `sendPushToMembers`) |
| `packages/web/src/hooks/use-push-notification.ts` | 푸시 알림 훅 (권한 관리, 토큰 복원, 구독/해제) |
| `packages/web/src/components/settings/push-notification-settings.tsx` | 알림 설정 UI (타입별 토글 + 테스트 전송) |
| `packages/web/src/app/api/push/test/route.ts` | 테스트 푸시 알림 API (레이트 리밋 5/min) |
| `packages/web/src/app/api/notification-preferences/route.ts` | 알림 타입별 설정 CRUD API |
| `packages/web/public/firebase-messaging-sw.js` | FCM 서비스 워커 (백그라운드 알림 수신) |
| `packages/bot/src/scripts/rss-collect.ts` | 수동 RSS 수집 스크립트 (봇 없이 독립 실행) |
| `packages/bot/src/scripts/setup-channels.ts` | 디스코드 채널 일괄 생성 스크립트 |
| `packages/bot/src/scripts/list-channels.ts` | 서버 채널 구조 조회 스크립트 |
Expand Down Expand Up @@ -208,6 +216,8 @@ pnpm --filter @blog-study/bot rss-collect # 수동 RSS 수집 (봇 없이)
- `NEXT_PUBLIC_SENTRY_DSN` (Sentry 에러 모니터링, web 전용)
- `SENTRY_DSN` (Sentry 에러 모니터링, bot 전용)
- `SENTRY_AUTH_TOKEN` (소스맵 업로드, Vercel/CI에서만 설정)
- `FIREBASE_PROJECT_ID`, `FIREBASE_PRIVATE_KEY`, `FIREBASE_CLIENT_EMAIL` 등 (Firebase Admin, 서버용)
- `NEXT_PUBLIC_FIREBASE_*` (Firebase 클라이언트, `API_KEY`/`AUTH_DOMAIN`/`PROJECT_ID`/`MESSAGING_SENDER_ID`/`APP_ID`/`VAPID_KEY`)

**env 파일 위치** (2곳):
- `.env.local` — 루트 (shared/bot용)
Expand Down
27 changes: 26 additions & 1 deletion docs/26-03-06-schema-summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
| `CurationCategory` | `conference`, `article` | 큐레이션 분류 |
| `ActivityScoreType` | `blog_post`, `board_post`, `post_comment`, `board_comment`, `admin_manual`, `post_view` | 활동 점수 |
| `BoardCategory` | `notice`, `suggestion`, `review`, `knowledge`, `daily`, `etc` | 게시판 카테고리 (const object) |
| `NotificationType` | `board_comment`, `board_reply`, `post_comment`, `post_reply`, `board_notice` | 알림 유형 (const object) |

## 테이블

Expand Down Expand Up @@ -133,6 +134,28 @@
| `deleted_at` | timestamptz | nullable (soft delete) |
| 인덱스: `post_id`, `member_id`, `parent_id` |

### fcm_tokens
| 컬럼 | 타입 | 비고 |
|------|------|------|
| `id` | uuid PK | defaultRandom |
| `member_id` | uuid FK → members | not null |
| `token` | text | not null |
| `device_info` | text | nullable |
| `last_used_at` | timestamptz | defaultNow |
| unique constraint: `(member_id, token)` |
| 인덱스: `member_id` |

### notification_preferences
| 컬럼 | 타입 | 비고 |
|------|------|------|
| `id` | uuid PK | defaultRandom |
| `member_id` | uuid FK → members | not null |
| `type` | varchar(30) | NotificationType, not null |
| `enabled` | boolean | default true |
| `updated_at` | timestamptz | defaultNow |
| unique constraint: `(member_id, type)` |
| 인덱스: `member_id` |

### keywords, curation_sources, curation_items
- `keywords`: keyword(unique) + frequency + last_updated
- `curation_sources`: url(unique) + name + category + rss_url + tags[] + is_active
Expand All @@ -155,8 +178,10 @@ members ──< board_posts (member_id)
members ──< board_comments (member_id)
board_posts ──< board_comments (post_id)
board_comments ──< board_comments (parent_id, self-ref)
members ──< fcm_tokens (member_id)
members ──< notification_preferences (member_id)
```

## 타입 Export

모든 테이블에 `Type`/`NewType` export 있음 (예: `Member`/`NewMember`, `Post`/`NewPost`, `BoardPost`/`NewBoardPost`, `BoardComment`/`NewBoardComment`)
모든 테이블에 `Type`/`NewType` export 있음 (예: `Member`/`NewMember`, `Post`/`NewPost`, `BoardPost`/`NewBoardPost`, `BoardComment`/`NewBoardComment`, `FcmToken`/`NewFcmToken`, `NotificationPreference`/`NewNotificationPreference`)
Loading
Loading