o2o-site-AEO/solution/frontend/src/api
Mina Choi 11d30bb3d1 [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제
여러 줄 주석이 설명보다 경위(예전·실측·지적)를 적고 있어 읽는 사람이 결론을 찾기 어려웠다.

- ts·tsx·js·mjs·css·py 478개: 여러 줄 주석은 첫 문장 한 줄로, 과거형·날짜 문장은 삭제
- 주석 위치는 TypeScript 파서·파이썬 tokenize/ast 로 찾는다 — 문자열 안의 # · /* 는 건드리지 않는다
- eslint·ts·noqa·type: ignore 같은 지시 주석은 그대로 둔다

파이썬 275개 정리 전후 AST 동일, TS 298개 주석 뺀 토큰 동일(빈 JSX 주석 10곳만 차이).
site·frontend·admin tsc, site vitest 105 passed

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 16:05:19 +09:00
..
generated [feat] solution/backend,frontend: 개발자 전용 사이트관리·유저관리 — 조회 전용 경량 화면 2026-09-28 15:53:02 +09:00
mutator [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
index.ts [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
pollJob.ts [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
README.md 문서: 앱을 가른 뒤 낡아진 서술을 고치고, 개발과 무관해진 기록을 지운다 2026-08-31 16:58:09 +09:00

api

api/
├── index.ts              ★ 화면이 import 하는 단 하나의 입구
├── generated/            orval 산출물 — 손대지 않는다
├── mutator/custom-fetch.ts  모든 호출이 지나는 길목(토큰·에러·baseURL·434 재발급)
└── pollJob.ts            잡 폴링(수집·비전·생성·빌드 공용)

화면은 @/api 하나만 본다.

import {useListPlaces, useTransitionFact, startBuild, pollJob} from '@/api';
import type {PlaceData, FactStatus} from '@/api';

재생성

백엔드 OpenAPI 가 바뀌면 다시 뽑는다. generated/ 를 손으로 고치지 않는다.

# 레포 루트에서. 백엔드가 떠 있을 때
npm run orval

# 서버 없이 (스펙 파일을 먼저 뽑는다)
cd solution/backend && .venv/bin/python scripts/export_openapi.py
cd ../.. && ORVAL_INPUT=solution/backend/openapi.json npm run orval

생성되는 것 — 태그(도메인)별 훅과 모델.

태그 훅
auth useLogin useRefreshToken useMe useUpdateMe
place useListPlaces useCreatePlace useGetPlace useUpdatePlace useVerifyCandidates useVerifyPlace useListUnits useCreateUnit useListLinks useCreateLink useConfirmLink useStartCollect useStartVision useStartCopy
fact useGetSchema useListFacts useUpsertFact useTransitionFact
job useGetJob useJobOps useRequeueJob
site useGetSite useStartBuild useListVersions useListLogs useChangeStatus
faq useListFaqs useCreateFaq useTransitionFaq
media useListMedia
local-content usePublish useSyncFestivals useUpdateContent useEndContent — 내부 운영 전용

orval.config.ts 의 operationName 이 FastAPI 의 list_places_v1_place_list_get 를 listPlaces 로 되돌린다 — 백엔드는 무수정이다.

규약 세 가지

1. 거절도 HTTP 200 이다. 도메인 거절은 result.success=false + result.desc(ErrorType 이름)로 온다. React Query 는 성공으로 보므로 onSuccess 안에서 직접 봐야 한다. 안 보면 저장 안 된 값이 저장된 것처럼 보인다.

onSuccess: (res) => {
  if (res.result?.success === false) return notifyApiError({data: res});
  ...
}

문구 변환은 @/lib/errorMessages 한 곳에 있다(PLACE_NOT_VERIFIED → "동일 업소 검증을 먼저…").

2. 응답의 None 필드는 키째 사라진다(백엔드 RemoveNoneResponse). 게다가 백엔드가 기본값을 준 필드는 OpenAPI 에서 required 가 아니라 생성 타입이 전부 optional 이다 — undefined 를 각오하고 쓴다.

3. 몇 분 걸리는 일은 잡이다. 수집·비전·생성·빌드는 job_id 를 받고 폴링한다. 루프는 pollJob() 하나뿐이다 — 화면마다 다시 쓰지 않는다.

const started = await startCollect(placeId, {});
const outcome = await pollJob(started.job_id!, {signal, onTick: (job) => ...});
// outcome.kind: done | dead | timeout | aborted | unreachable

★ done 은 "잡이 끝났다"이지 "성공했다"가 아니다. 빌드는 게이트에 막혀도 정상 종료하고 job.result.gate.passed 가 false 로 온다 — 판정은 features/publish/usePublishSite.ts 가 읽는다.