refactor: 퀴즈 수정 화면이 단건 조회 API를 쓴다
단건 조회가 없어 수정 화면이 목록을 500건까지 받아 와 그 안에서 찾고
있었다. 백엔드가 GET /api/v1/mngr/cntntns/quiz/{quizSn}을 열었으므로
스캔을 걷어낸다. 500건을 넘는 퀴즈가 쌓여도 수정 화면이 빈 화면이 되지
않는다.
같은 개편에서 등록 INSERT의 값 목록과 keyProperty도 고쳐져, 파일 머리말의
결함 목록에서 함께 지운다. 검색어가 키워드를 보지 않는 것과 난이도 필터가
SQL에 없는 것은 그대로다.
Co-Authored-By: Claude Opus 5
@8934963de1932970f4e73a74b581fd0760e0bc7f
--- lib/data/repositories/content-quiz-repository.ts
+++ lib/data/repositories/content-quiz-repository.ts
... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 |
* |
| 12 | 12 |
* ``` |
| 13 | 13 |
* GET /api/v1/mngr/cntntns/quiz/pagination 학교·학년·난이도·검색어 |
| 14 |
+ * GET /api/v1/mngr/cntntns/quiz/{quizSn} 단건
|
|
| 14 | 15 |
* POST /api/v1/mngr/cntntns/quiz 어노테이션 없음 → form(중첩 목록은 인덱스 표기) |
| 15 | 16 |
* PUT /api/v1/mngr/cntntns/quiz/{quizSn} @RequestBody(JSON)
|
| 16 | 17 |
* DELETE /api/v1/mngr/cntntns/quiz/{quizSn} soft delete(DEL_YN)
|
... | ... | @@ -21,23 +22,13 @@ |
| 21 | 22 |
* 같은 모양이라 화면 쪽 취급도 같다. |
| 22 | 23 |
* |
| 23 | 24 |
* ⚠️ 백엔드 결함(보고함, 미수정) |
| 24 |
- * 1. **등록 INSERT의 컬럼 수와 값 수가 다르다** — 컬럼은 11개인데 값은 10개고 `USE_YN` 자리가 |
|
| 25 |
- * 비어 있다. 지금은 등록이 SQL 오류로 끝난다. 프론트는 `useYn`을 정상적으로 보내고 있으므로 |
|
| 26 |
- * 백엔드가 값 목록만 맞추면 그대로 동작한다. |
|
| 27 |
- * 2. 등록 INSERT의 `keyProperty`/`keyColumn`이 `cntntsSn`/`CNTNTS_SN`이다(이 테이블은 `QUIZ_SN`). |
|
| 28 |
- * 채번된 키가 VO에 담기지 않아 학교·학년 매핑이 `quiz_sn` 없이 저장된다. |
|
| 29 |
- * 3. 단건 조회 API가 없다 — 매퍼·서비스에는 `selectOne`이 있는데 컨트롤러가 열지 않았다. |
|
| 30 |
- * 그래서 수정 화면은 목록에서 찾는다(아래 `fetchQuizDetail`). |
|
| 31 |
- * 4. 검색어가 질문·정답만 본다(`QUIZ_ANSWER`·`QUIZ_QUESTION`). 화면의 「키워드」 검색은 |
|
| 25 |
+ * 1. 검색어가 질문·정답만 본다(`QUIZ_ANSWER`·`QUIZ_QUESTION`). 화면의 「키워드」 검색은 |
|
| 32 | 26 |
* `QUIZ_TITLE`을 봐야 하는데 조건에 없어 결과가 비어 온다. |
| 33 |
- * 5. 난이도 필터가 SQL에 없다 — `searchLevelCd`를 받지만 `searchWhere`가 쓰지 않는다. |
|
| 27 |
+ * 2. 난이도 필터가 SQL에 없다 — `searchLevelCd`를 받지만 `searchWhere`가 쓰지 않는다. |
|
| 34 | 28 |
* 화면 선택지는 기획대로 두고 값만 실어 보낸다. |
| 35 | 29 |
*/ |
| 36 | 30 |
|
| 37 | 31 |
const QUIZ_PATH = '/api/v1/mngr/cntntns/quiz'; |
| 38 |
- |
|
| 39 |
-/** 목록에서 단건을 찾을 때 한 번에 받아올 최대 행 수(단건 조회 API가 없다 — 결함 3). */ |
|
| 40 |
-const DETAIL_SCAN_LIMIT = 500; |
|
| 41 | 32 |
|
| 42 | 33 |
function isRecord(value: unknown): value is Record<string, unknown> {
|
| 43 | 34 |
return value !== null && typeof value === 'object'; |
... | ... | @@ -123,7 +114,7 @@ |
| 123 | 114 |
return {
|
| 124 | 115 |
searchSchulGradeCd: query.school, |
| 125 | 116 |
searchGradeCd: query.grade, |
| 126 |
- // 백엔드 SQL이 아직 쓰지 않는다(결함 5). 화면 선택지는 기획대로 두고 값만 보낸다. |
|
| 117 |
+ // 백엔드 SQL이 아직 쓰지 않는다(결함 2). 화면 선택지는 기획대로 두고 값만 보낸다. |
|
| 127 | 118 |
searchLevelCd: query.level, |
| 128 | 119 |
searchKeyword: keyword, |
| 129 | 120 |
pageIndex, |
... | ... | @@ -189,24 +180,27 @@ |
| 189 | 180 |
}; |
| 190 | 181 |
} |
| 191 | 182 |
|
| 192 |
-/** TODO: 단건 조회 API(결함 3)가 열리면 이 스캔을 `GET {base}/{quizSn}` 호출로 교체한다. */
|
|
| 193 | 183 |
export async function fetchQuizDetail(quizSn: string): Promise<QuizItem | null> {
|
| 194 |
- const { items } = await requestList(
|
|
| 184 |
+ const accessToken = await getSessionAccessToken(); |
|
| 185 |
+ |
|
| 186 |
+ const result = await backendFetch<unknown>( |
|
| 187 |
+ `${QUIZ_PATH}/${encodeURIComponent(quizSn)}`,
|
|
| 195 | 188 |
{
|
| 196 |
- school: '', |
|
| 197 |
- grade: '', |
|
| 198 |
- level: '', |
|
| 199 |
- searchField: '', |
|
| 200 |
- keyword: '', |
|
| 201 |
- sort: 'created', |
|
| 202 |
- page: 1, |
|
| 203 |
- pageSize: 10, |
|
| 204 |
- }, |
|
| 205 |
- 1, |
|
| 206 |
- DETAIL_SCAN_LIMIT |
|
| 189 |
+ method: 'GET', |
|
| 190 |
+ accessToken: accessToken ?? undefined, |
|
| 191 |
+ cache: 'no-store', |
|
| 192 |
+ canHaveNullData: true, |
|
| 193 |
+ } |
|
| 207 | 194 |
); |
| 208 | 195 |
|
| 209 |
- return items.find((item) => item.quizSn === quizSn) ?? null; |
|
| 196 |
+ if (!result.ok) {
|
|
| 197 |
+ throw new BackendRequestError(result); |
|
| 198 |
+ } |
|
| 199 |
+ if (result.data === null || result.data === undefined) {
|
|
| 200 |
+ return null; |
|
| 201 |
+ } |
|
| 202 |
+ |
|
| 203 |
+ return toQuizItem(result.data); |
|
| 210 | 204 |
} |
| 211 | 205 |
|
| 212 | 206 |
type QuizWritePayload = {
|
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?