검색 K
밝은/어두운 배경
밝은/어두운 배경
게시물 정보
Neon(PostgreSQL) DB를 사용합니다. 파트 1·2가 공유하는 테이블입니다.
| 테이블 | 역할 |
|---|---|
users | 사용자 계정 (folderName + 비밀번호 해시) |
registered_feeds | 활성/비활성 RSS 피드 레지스트리 |
feed_requests | 피드 등록 신청 내역 |
withdraw_requests | 피드 철회 신청 내역 |
scraper_lock | 스크래퍼 실행 중 락 (단일 행) |
users 사용자 인증 정보를 저장합니다. folderName이 계정 식별자입니다.
| 컬럼 | 타입 | 설명 |
|---|---|---|
folder_name | text PK | 계정 식별자 겸 VitePress 폴더명 |
password_hash | text | bcrypt 해시 (cost 12) |
email | text | 신청 결과 수신 이메일 |
비밀번호 해시 생성: tsx scripts/hash-password.ts <비밀번호>
registered_feeds 파트 1 스크래퍼가 읽는 피드 레지스트리입니다. 파트 2 API가 쓰고, 파트 1이 읽습니다.
| 컬럼 | 타입 | 설명 |
|---|---|---|
feed_id | text PK | {folderName}-{uuid 앞 8자} |
folder_name | text | 계정 식별자 |
feed_url | text | RSS 피드 URL |
feed_title | text | 표시 이름 (sanitizeFeedTitle 처리 후 저장) |
source_link | text | 원본 웹사이트 URL |
scope | text | 수집 범위. all(기본) · today · 3days · weekly |
include_image | boolean | 대표 이미지 추출 여부 (기본 false) |
meta_display | boolean | 발행일·저자·카테고리 Markdown 표시 여부 (기본 false) |
logo_name | text | 로고 이미지 파일명 (선택) |
active | boolean | false이면 스크래퍼 수집 제외 |
withdrawn_at | timestamptz | 철회 처리 시각. IS NOT NULL → 고아 파일 정리 대상 |
registered_at | timestamptz | 등록 시각 (재활성화 시 갱신) |
consecutive_failures | int | 연속 fetch 실패 횟수 |
last_failure_at | timestamptz | 마지막 실패 시각 |
last_success_at | timestamptz | 마지막 성공 시각 |
유니크 제약: (folder_name, feed_url) — 동일 계정의 동일 URL 중복 방지.
재활성화 처리: 철회 후 재신청 승인 시 approveFeedRequest()가 ON CONFLICT DO UPDATE로 active = true, withdrawn_at = NULL로 복구합니다.
feed_requests 피드 등록 신청의 전체 이력을 관리합니다.
| 컬럼 | 타입 | 설명 |
|---|---|---|
id | serial PK | |
batch_id | uuid | 같은 요청으로 신청된 피드 묶음 식별자 |
folder_name | text | 신청 계정 |
feed_url | text | 신청 RSS URL |
feed_title | text | 신청 피드 이름 |
source_link | text | 원본 웹사이트 URL |
scope | text | 요청한 수집 범위 |
user_email | text | 결과 수신 이메일 |
review_token | text | 일회성 운영자 링크 토큰 |
applicant_message | text | 신청자 메모 (배치 전체 동일) |
status | text | pending · approved · rejected · withdrawn |
rejected_reason | text | 반려 사유 (REJECT_LABELS 변환 후 저장) |
requested_at | timestamptz | 신청 시각 |
reviewed_at | timestamptz | 처리 시각 |
token_used_at | timestamptz | 토큰 소진 시각. IS NULL이면 미처리 |
result_sent_at | timestamptz | 결과 이메일 발송 시각. 중복 발송 방지용 |
reminder_count | int | 재알림 발송 횟수 |
last_reminded_at | timestamptz | 마지막 재알림 발송 시각 |
부분 인덱스 uq_active_request: status IN ('pending', 'approved')인 행에서 (folder_name, feed_url) 유니크 보장. 철회 후 재신청을 허용하면서 중복 활성 요청을 방지합니다.
withdraw_requests 피드 철회 신청 내역을 관리합니다.
| 컬럼 | 타입 | 설명 |
|---|---|---|
id | serial PK | |
folder_name | text | 신청 계정 |
feed_url | text | 철회 대상 RSS URL |
feed_title | text | 피드 이름 |
user_email | text | 결과 수신 이메일 |
token | text | 일회성 운영자 링크 토큰 |
status | text | pending · confirmed · rejected |
requested_at | timestamptz | 신청 시각 |
reviewed_at | timestamptz | 처리 시각 |
token_used_at | timestamptz | 토큰 소진 시각 |
scraper_lock 스크래퍼 동시 실행 방지를 위한 단일 행 테이블입니다. id = 1 행만 존재합니다.
| 컬럼 | 타입 | 설명 |
|---|---|---|
id | int PK | 항상 1 |
locked | boolean | 스크래퍼 실행 중이면 true |
locked_at | timestamptz | 락 획득 시각 |
DDL:
CREATE TABLE scraper_lock (
id INT PRIMARY KEY DEFAULT 1,
locked BOOLEAN NOT NULL DEFAULT false,
locked_at TIMESTAMPTZ
);
INSERT INTO scraper_lock VALUES (1, false, NULL);파트 1 스크래퍼가 시작 시 locked = true, 종료 시 locked = false로 갱신합니다. 파트 2 API의 rss-register, rss-withdraw는 scraper 실행 중 신청을 차단합니다.