Files
hyungi_document_server/migrations/186_study_questions.sql
Hyungi Ahn 4b7156061e feat(study): 문제은행 + 복습모드 (study_questions)
study_topic 워크스페이스에 4지선다 문제은행 자산 트랙 추가. 기사시험 필기
대비 시나리오 — 빠른 반복 입력 + 과목별 균등 추출 복습 + 정오답 누적.

데이터 모델 (migrations 186~190):
- study_questions: study_topic 1:N, soft delete, is_active 토글, correct_choice
  SMALLINT CHECK 1~4
- study_question_attempts: 답 제출 1행 누적. study_question_id FK는 ON DELETE
  RESTRICT (이력 보존 원칙 — hard delete 실수로 풀이 기록 소실 차단)

설계 원칙:
- 문제 삭제는 API 에서 soft delete only. attempts FK RESTRICT 로 DB 레벨도 보호
- correct_choice 변경 시 기존 attempts.is_correct 재계산 안 함 (시점 사실 보존)
- 복습 default = 과목별 target_per_subject(20) 무작위 균등 추출. 한 과목이
  부족하면 가용한 만큼만
- wrong_only=true 정의 = 가장 최근 attempt 가 오답인 문제 (latest-wrong, ever-wrong 아님)
- 출제 응답에서 정답·해설 비공개. 답 제출 시점에만 노출
- subject/scope 강한 enum 미사용 (자유 텍스트, 자동완성은 후속)

API: /api/study-topics/{id}/questions, /review/questions, /api/study-questions/{id},
/attempt. 통합뷰(/study-topics/{id}) 응답에 sections.questions / stats.question_count
추가. 기존 question_set_count 는 후속 PR(회차/모의고사 묶음)용으로 보존.

프론트: /study/topics/[id]에 문제 섹션 + "새 문제"/"복습 시작" 진입.
/questions/new (저장 후 계속 입력 + sessionStorage persistent),
/questions/[qid]/edit (정답 변경 시 attempts 재계산 안 됨 안내 배너),
/review (시작 옵션 → 풀이 → 마지막 요약).

후속 PR 예정: 오답노트/취약 과목 리포트, AI 해설/클러스터링, spaced
repetition, 이미지 OCR 입력, CSV import, study_question_sets 묶음.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:00:37 +09:00

36 lines
1.6 KiB
SQL

-- 186_study_questions.sql (1/5)
-- study_topic 아래 4지선다 문제은행. 기사시험 필기 대비.
--
-- 핵심:
-- - study_topic_id 1:N (한 주제에 N 문제, 워크스페이스 컨테이너 PR-1 연장).
-- - subject/scope 는 느슨한 분류 (강한 enum 미사용). 자유 텍스트 + 자동완성은 후속.
-- - correct_choice 는 SMALLINT CHECK 1~4. 객관식 외 형식(주관식·OX·다답) 은 본 PR 범위 밖.
-- - is_active 는 향후 출제 제외 토글 (예: 잘못 입력한 문제 임시 비활성). soft delete(deleted_at)와 별개.
-- - polymorphic study_topic_items 영구 금지 (PR-1 가드레일). 자산 타입별 조인 테이블 없음 — 본 테이블은 study_topic_id 직접 FK.
CREATE TABLE IF NOT EXISTS study_questions (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
study_topic_id BIGINT NOT NULL REFERENCES study_topics(id) ON DELETE CASCADE,
question_text TEXT NOT NULL,
choice_1 TEXT NOT NULL,
choice_2 TEXT NOT NULL,
choice_3 TEXT NOT NULL,
choice_4 TEXT NOT NULL,
correct_choice SMALLINT NOT NULL CHECK (correct_choice BETWEEN 1 AND 4),
subject VARCHAR(120),
scope VARCHAR(200),
exam_name VARCHAR(120),
exam_round VARCHAR(120),
explanation TEXT,
source_note TEXT,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);