[DP-411] 퀴즈 이력 목록/상세 API + 제출 시 답안 저장#135
Merged
github-actions[bot] merged 1 commit intodevelopV2from Apr 24, 2026
Merged
Conversation
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


작업 내용
퀴즈 이력 조회 및 결과 상세 API를 구현하고, 제출 시 문제별 선택 답안을 저장하는 기능을 추가합니다.
DB 스키마 변경
신규 테이블
quiz_attempt_answers:제출 API 확장
POST /contents/{contentId}/quiz/submit—QuizSubmitRequest에answers배열 추가 (하위 호환: nullable){ "level": "JUNIOR", "score": 2, "totalQuestions": 3, "passed": false, "answers": [ { "questionId": "q-1", "selectedOptionId": "opt-2", "answerText": null, "isCorrect": false }, { "questionId": "q-2", "selectedOptionId": "opt-1", "answerText": null, "isCorrect": true } ] }퀴즈 이력 목록 API (신규)
GET /users/me/quiz-history?sort=newest&page=0&size=10contentId + level기준 최신 attempt만 반환sort=newest(기본) /sort=oldest서버사이드 정렬preview: DynamoDBai_quizzes에서 첫 번째 문제 텍스트 배치 조회 (없으면 null){ "success": true, "data": { "content": [ { "attemptId": "uuid", "contentId": "uuid", "contentTitle": "React hooks 완전 정복", "thumbnail": "https://...", "preview": "useActionState 훅의 주요 역할은 무엇인가요?", "level": "JUNIOR", "score": 2, "totalQuestions": 3, "passed": false, "attemptedAt": "2026-04-20T10:00:00Z" } ], "page": 0, "size": 10, "totalElements": 5, "totalPages": 1 } }퀴즈 결과 상세 API (신규)
GET /quiz-history/{attemptId}quiz.questions: DynamoDB에서 contentId+level로 조회myAnswers: PostgreSQLquiz_attempt_answers에서 조회pointsEarned:point_logs에서 해당 콘텐츠의 AI_QUIZ_PASS 적립 합계{ "success": true, "data": { "attemptId": "uuid", "contentId": "uuid", "score": 2, "totalQuestions": 3, "passed": false, "pointsEarned": 0, "quiz": { "questions": [ { "id": "q-1", "type": "multiple_choice", "question": "Spring DI란 무엇인가요?", "options": [{ "id": "opt-1", "text": "의존성 주입" }, { "id": "opt-2", "text": "데이터 조회" }], "correctOptionId": "opt-1", "explanation": "DI는 Dependency Injection의 약자입니다.", "correctAnswer": "" } ], "passingCount": 2 }, "myAnswers": [ { "questionId": "q-1", "selectedOptionId": "opt-2", "answerText": null, "isCorrect": false } ] } }신규 파일
QuizAttemptAnswer.javaQuizAttemptAnswerRepository.javaQuizHistoryController.javaQuizHistoryItemResponse.javaQuizHistoryListResponse.javaQuizResultResponse.java수정 파일
QuizSubmitRequest.javaanswers필드 추가 (nullable, 하위 호환)QuizAttemptRepository.javaAiQuizRepository.javabatchFindFirstQuestions배치 조회 메서드 추가AiQuizService.javaAiSummaryService.javafromAiServerLevel역변환 메서드 추가ErrorCode.java테스트 커버리지
AiQuizServiceQuizHistoryItemResponseQuizHistoryControllerAiQuizServiceTest 신규 케이스 (7개)
quiz_attempt_answers저장 확인sort=oldest→ createdAt ASC 정렬 적용QuizHistoryControllerTest (4개)