Skip to content

도메인: Watchlist (관심종목)

개요

사용자가 관심 종목을 등록/삭제하고 알림 설정을 관리한다. 슬롯 정책 V6: users.slot_capacity 한도 내에서 자유롭게 추가/삭제 (cooldown / 일일 카운터 없음).

데이터 모델 (핵심 테이블)

dartbrief.watch_stocks

컬럼타입설명
idBIGSERIAL PK
user_idBIGINT FK → users.idON DELETE CASCADE
corp_codeVARCHAR(8)DART 고유 회사 코드
corp_nameVARCHAR(255)회사명 (stocks 테이블에서 복사, 비정규화)
stock_codeVARCHAR(6)종목코드 (nullable)
notify_enabledBOOLEAN알림 활성화 여부 (기본 true)
created_atTIMESTAMP(6)등록 시각

UNIQUE: (user_id, corp_code) 인덱스: user_id, corp_code

dartbrief.users.slot_capacity

컬럼기본값제약
slot_capacity3CHECK >= 3

동작 플로우

종목 추가 (idempotent — 2026-05-08, PR #57)

mermaid
flowchart TD
    A[POST /api/v1/watchlist<br/>body: corp_code] --> B[Has user_id, corp_code]
    B --> X{이미 보유?}
    X -- yes --> Y[INSERT ... ON CONFLICT DO UPDATE<br/>RETURNING 기존 row]
    Y --> H[201 Created + WatchStock<br/>idempotent no-op]
    X -- no --> C[GetCapacityStatus]
    C --> D{remaining <= 0?}
    D -- yes --> E[409 Conflict<br/>슬롯 한도 초과]
    D -- no --> F[INSERT watch_stocks<br/>SELECT from stocks WHERE corp_code]
    F --> G{stocks에 corp_code 없음?}
    G -- pgx.ErrNoRows --> I[400 Bad Request]
    G -- 성공 --> H

왜 capacity 검사 전에 Has 체크? lazy auth 게이트 통과 직후 자동 add 시 사용자가 이미 보유한 종목 (예: 게이트 직전 선택한 chip 이 그 사용자의 기존 watchlist 에 이미 존재) 을 재추가하는 경로에서 capacity 가 가득 차 있으면 409 → "선택했는데 추가 실패" 부조리. 이미 보유 = 결과 상태가 이미 사용자 의도와 일치 하므로 capacity 검사 건너뛰고 idempotent no-op 반환.

종목 삭제

mermaid
flowchart TD
    A[DELETE /api/v1/watchlist/:corpCode] --> B[DELETE watch_stocks<br/>WHERE user_id AND corp_code]
    B --> C{RowsAffected = 0?}
    C -- yes --> D[404 Not Found]
    C -- no --> E[204 No Content]

용량 조회

mermaid
flowchart TD
    A[GET /api/v1/watchlist/capacity] --> B[SELECT slot_capacity, COUNT watch_stocks<br/>FROM users WHERE id = userID]
    B --> C[{ capacity, used, remaining }]

룰 / 정책

슬롯 정책 V6 (현재)

항목
기본 슬롯 한도3
최소 한도 (DB CHECK)3 (환불 후에도 3 미만 불가)
cooldown없음 (폐기)
일일 카운터없음 (폐기)
free/paid 구분 노출없음 (사용자에게 익명화)
슬롯 증가 방법결제 → slot_capacity 증가 (미구현, 보류 중)
환불 시slot_capacity 감소 + 가장 오래된 종목 자동 제거 (미구현)

알림 설정

종목별로 notify_enabled 플래그로 관리. 기본값 true. PATCH /api/v1/watchlist/{corpCode}/notify로 토글.

종목 데이터 소스

추가 시 dartbrief.stocks 테이블에서 corp_code로 조회해 corp_name, stock_code를 복사 저장 (비정규화). stocks에 없는 corp_code는 등록 불가.

Edge case

케이스동작
capacity 초과 신규 추가 시도409 Conflict + { message, capacity, used }
없는 corp_code 추가stocks INSERT SELECT → 0 rows → 400 Bad Request
이미 등록된 종목 재등록idempotent 201 (기존 row 반환, capacity 가득 차도 OK) — PR #57 변경
없는 종목 삭제RowsAffected=0 → 404 Not Found
사용자 탈퇴ON DELETE CASCADE → watch_stocks 자동 삭제
remaining 음수GetCapacityStatus에서 max(0, cap-used) 처리

관련 API

엔드포인트설명
GET /api/v1/watchlist관심종목 목록 (created_at DESC)
GET /api/v1/watchlist/capacity슬롯 용량 현황
POST /api/v1/watchlist종목 추가
DELETE /api/v1/watchlist/{corpCode}종목 삭제
PATCH /api/v1/watchlist/{corpCode}/notify알림 활성화/비활성화