임동욱 임동욱 08-21
merge: 퀴즈 키워드 복원
@4f6f5193276dc761d72ed4af84a729f35f62972d
app/(protected)/(basic)/contents/_actions.ts
--- app/(protected)/(basic)/contents/_actions.ts
+++ app/(protected)/(basic)/contents/_actions.ts
@@ -173,7 +173,6 @@
     schoolCode: readString(formData, 'schoolCode'),
     grades: readGrades(formData),
     points: readString(formData, 'quizPoint'),
-    title: readString(formData, 'quizTitle'),
     level: readString(formData, 'level'),
     keywords: readKeywords(formData),
     question: readString(formData, 'question'),
app/(protected)/(basic)/contents/quizzes/_components/quiz-form.tsx
--- app/(protected)/(basic)/contents/quizzes/_components/quiz-form.tsx
+++ app/(protected)/(basic)/contents/quizzes/_components/quiz-form.tsx
@@ -29,6 +29,7 @@
 import { ContentFormActions } from '../../_components/content-form-actions';
 import { ContentFormRow } from '../../_components/content-form-row';
 import { ContentGradeField } from '../../_components/content-grade-field';
+import { ContentKeywordField } from '../../_components/content-keyword-field';
 import { ContentVisibilityField } from '../../_components/content-visibility-field';
 import styles from '../../_components/content-form.module.scss';
 
@@ -70,7 +71,6 @@
         {isEdit && <input type="hidden" name="quizSn" value={item.quizSn} />}
         {/* 화면에 입력 칸이 없는 값이라 그대로 돌려보내 지워지지 않게 한다(도메인 주석 참조). */}
         <input type="hidden" name="quizPoint" value={item?.points ?? ''} />
-        <input type="hidden" name="quizTitle" value={item?.keywordText ?? ''} />
 
         {isEdit && (
           <ContentFormRow label="콘텐츠ID">
@@ -103,6 +103,10 @@
           {errors.level && <FoxHelperText type="danger" message={errors.level} />}
         </ContentFormRow>
 
+        <ContentFormRow label="키워드">
+          <ContentKeywordField error={errors.keywords} />
+        </ContentFormRow>
+
         <ContentFormRow label="질문" required>
           <FoxTextArea
             name="question"
app/(protected)/(basic)/contents/quizzes/_components/quizzes-list.tsx
--- app/(protected)/(basic)/contents/quizzes/_components/quizzes-list.tsx
+++ app/(protected)/(basic)/contents/quizzes/_components/quizzes-list.tsx
@@ -56,6 +56,12 @@
       render: (row) => formatQuizLevelLabel(row.level),
     },
     {
+      key: 'keywords',
+      header: '키워드',
+      width: 200,
+      render: (row) => formatContentText(row.keywordText),
+    },
+    {
       key: 'question',
       header: '질문',
       width: 360,
lib/data/repositories/content-quiz-repository.ts
--- lib/data/repositories/content-quiz-repository.ts
+++ lib/data/repositories/content-quiz-repository.ts
@@ -224,13 +224,12 @@
 /**
  * 이슈: 정답 노출 문구(기획 "기본 3종 + 기타")를 담을 필드가 백엔드에 없다. 화면은 값을 받지만
  *   저장되지 않는다 — 컬럼이 생기면 여기에 실어 보낸다.
- * 이슈: 키워드가 기획에서 빠져 `QUIZ_TITLE`을 채울 입력이 없다. 수정 SQL이 이 칸을 무조건
- *   덮어써서 안 보내면 지워지므로, 조회해 온 값을 그대로 돌려보낸다(`quizPoint`와 같은 처리).
+ * 이슈: 키워드가 별도 테이블이 아니라 `quizTitle` 한 칸이라 쉼표로 이어 붙인다.
  */
 function buildQuizPayload(values: QuizFormValues): QuizWritePayload {
   return {
     ...(values.points === '' ? {} : { quizPoint: values.points }),
-    quizTitle: values.title,
+    quizTitle: values.keywords.map((item) => item.keyword).join(', '),
     quizLev: values.level,
     quizQuestion: values.question,
     quizExplan: values.explanation,
lib/domain/content-form.ts
--- lib/domain/content-form.ts
+++ lib/domain/content-form.ts
@@ -82,12 +82,8 @@
    * 백엔드 UPDATE가 `QUIZ_POINT = #{quizPoint}`로 무조건 덮어써서, 안 보내면 지워진다.
    */
   points: string;
-  /**
-   * 기존 QUIZ_TITLE. 키워드가 기획에서 빠져 화면에 입력 칸이 없지만, 수정 SQL이
-   * `QUIZ_TITLE = #{quizTitle}`로 무조건 덮어써서 안 보내면 지워진다(`points`와 같은 이유).
-   */
-  title: string;
   level: string;
+  keywords: ContentKeyword[];
   question: string;
   answer: string;
   answerMessageCode: string;
@@ -289,11 +285,14 @@
     answerMessageText = '';
   }
 
+  const keywords = normalizeKeywords(values.keywords);
+  validateKeywords(keywords, errors);
+
   if (Object.keys(errors).length > 0) {
     return { ok: false, errors };
   }
   return {
     ok: true,
-    values: { ...values, question, explanation, answerMessageText },
+    values: { ...values, question, explanation, answerMessageText, keywords },
   };
 }
lib/domain/content-query.ts
--- lib/domain/content-query.ts
+++ lib/domain/content-query.ts
@@ -68,8 +68,10 @@
     { value: 'title', label: '제목' },
     { value: 'keyword', label: '키워드' },
   ],
-  // 키워드는 기획에서 빠졌다 — 질문만 남는다.
-  quiz: [{ value: 'question', label: '질문' }],
+  quiz: [
+    { value: 'question', label: '질문' },
+    { value: 'keyword', label: '키워드' },
+  ],
   comic: [
     { value: 'name', label: '콘텐츠명' },
     { value: 'keyword', label: '키워드' },
Add a comment
List