콘텐츠로 이동
✍️ 수정가능누구나 고쳐도 됩니다. 고치면 하단 frontmatter의 갱신일·작성자·변경요약을 남겨 주세요.작성 Claude · 2026-06-04 · v12 재편·raw 컴파일·인간화

오픈챌린지 개발 명세 (FRD)

요지

오픈챌린지는 별도 도메인이 아니라 challenge 도메인의 공개(PUBLIC) 경로다. 풀이 상태머신·채점·AI 위임 같은 핵심 백엔드는 챌린지식-풀이와 그대로 공유하고, 여기서는 공개 유입에서만 다른 부분(공개 API 표면, 집계 규칙, visibility)만 따로 정리한다.

상위 PRD

기획(5화면, 비로그인 전환, 집계·랭킹 정책)은 prd v3이며, 바뀌면 이 문서도 갱신한다.

기술 접근 · 아키텍처

visibility

Challenge.visibility = PUBLIC (오픈챌린지) vs STUDYROOM(스터디룸 한정). 오픈은 studyRoomId = null, 운영자 시드. 초기 MVP는 모든 문제 AI 지원(isAiSupported=true).

집계 규칙

엔티티 필드 자체는 challenge가 기준이고, 여기서는 공개 채널에서 숫자를 어떻게 세는지를 정한다. 핵심은 "끝까지 푼 것만 센다"이다 — 들어와서 도중에 나간 건 통계에 넣지 않는다.

  • participantCount = COMPLETED 기준(실제 완료만 카운트). passRate = COMPLETED 중 정답 비율.
  • ANSWER_SELECTED는 DB 저장 X, UI 상태로만 관리 → 제출(answer PATCH) 시 확정.
  • 다시 풀기: 새 attempt 생성. ChallengeReview: COMPLETED만 작성, 추천순 정렬, 추천 중복 방지. 타 사용자는 최신 COMPLETED 풀이만 노출(피드 품질), 본인은 전체 이력.
  • UserRanking(배치 집계): 1순위 연속 참여일수 → 2순위 참여 횟수 → 3순위 정답률(COMPLETED only). KST 기준, 하루 미참여 시 streak reset, Grace Day 없음.

예외·검증

답을 고르지 않으면 제출할 수 없고, 로그인이 만료되면 재로그인 후 풀던 attempt를 복구한다. 도중에 나가면 UNRESOLVED로, 문제가 없으면 빈 화면으로, 정답률 표본이 부족하면 "집계 중"으로 처리한다. 한 명이라도 푼 문제는 수정·삭제 없이 비노출만 한다.

API · 데이터 모델

엔티티는 challenge가 기준이고, 여기서는 공개 유입에 필요한 API 표면(리스트·상세·결과·랭킹·어드민)만 정리한다.

동작 메서드·경로 요청/쿼리 응답 핵심
문제 리스트 GET /challenges subject, difficulty, sort(최신/인기/정답률) 카드 목록 + participantCount·passRate
문제 상세 GET /challenges/:id 문제 이미지·choices·메타·isAiSupported
attempt 생성 POST /challenge-attempt challengeId {attemptId, status}
답 제출 PATCH /challenge-attempt/:id/answer selectedAnswer {isCorrect, correctAnswer, participantCount, passRate}
다른 사람 풀이 GET /challenge-reviews/:challengeId sort=recommend 풀이 목록(베스트 고정)
풀이 작성 POST /challenge-review content (COMPLETED only) review
AI 만족도 POST /challenge-feedback rating·comment(opt) 저장
사용자 랭킹 GET /challenge-ranking streakDays·challengeCount·correctRate
어드민 POST /admin/challenge, PATCH /admin/challenge/:id/hide, DELETE /admin/challenge/:id (참여자 발생 시 삭제 불가)
  • 공개 리스트/상세는 /api/public/** permitAll — 비로그인 접근. attempt·제출·풀이 작성·만족도는 인증 필요(비로그인 시작 시 로그인 유도 = 전환 지점).
  • 응답 목표: 리스트 < 200ms, 상세 < 300ms (Redis 캐시 후보).

의존성 · 영향 범위

챌린지 도메인(challenge)을 기반으로 하고, 풀이 단계(상태머신·채점·AI 위임)는 챌린지식-풀이와, 막혔을 때의 AI 코칭은 사고력-답변구조와 흐름을 공유한다.

트래픽이 변수다. 6월 모의고사 시즌에 한꺼번에 몰릴 수 있는데, 1차 MVP는 단일 인스턴스를 가정하되 모니터링 알림 임계를 미리 걸어 둔다. 2026-05-26 기준 백엔드·프런트 MVP는 완성됐고, 드로잉·성능(Lighthouse)·모바일 최적화가 후속 과제로 남아 있다.

테스트 계획

공통 전략은 qa-playbook을 따른다. 이 기능의 핵심은 로그인 경계와 집계 정확성이다 — 비로그인은 리스트·상세까지만 보이고 attempt·제출·만족도는 401로 막혀 로그인으로 유도되어야 하며, participantCount·passRate가 COMPLETED 기준으로만 늘어야 한다. 한 명이라도 푼 문제의 수정·삭제 차단(비노출만), 답 미선택 제출 차단도 확인한다.

작업 분해

완료 추적은 GitHub 이슈에서 한다. 방향 전환의 근거는 ADR-0009에 있고, 비로그인 공개 엔드포인트의 Security 정책은 별도 ADR로 정할 예정이다.