관리자 앱은 백엔드를 서버(Server Component·Action)에서만 부르므로 브라우저 Network 탭에는
안 잡힌다. Node 24부터 인스펙터 Network 도메인이 undici fetch를 잡으므로(20은 안 됨 — 확인)
`next dev --inspect`에 `--experimental-network-inspection`을 얹어 chrome://inspect의
라우터 서버 타깃에서 본다. 클라이언트 직접 호출로 바꾸는 것은 토큰 노출이라 하지 않는다.
Co-Authored-By: Claude Opus 5
PUT /api/v1/common/ntcn/{ntcnSn}을 규약대로 붙인다. 누르는 즉시 낙관적으로 읽음 표시
(표시선·배지 감소)를 하고 이동한 뒤 router.refresh()로 서버 목록에 되맞춘다.
백엔드 컨트롤러가 아직 경로변수 ntcnSn과 readYn을 VO에 담지 않아 어느 행도 갱신되지
않고 200만 돌아온다 — 그래서 지금은 새로 고치면 안 읽음으로 돌아온다. 백엔드가
setNtcnSn(ntcnSn)·setReadYn("Y") 두 줄을 채우면 프론트 수정 없이 동작한다.
Co-Authored-By: Claude Opus 5
한줄 소개·카테고리·영업시간·휴무일·노출 순서·추가 이미지는 INSERT/UPDATE에 실려 저장되지만
(dev 앱용 API로 영업시간·휴무일·이미지 id 저장 확인) 관리자 단건 SELECT에 그 컬럼이 없어
화면에선 비어 보이고, 그대로 저장하면 빈 값으로 덮어써진다. 컬럼이 추가될 때까지 경고를
둔다.
Co-Authored-By: Claude Opus 5
상세가 없는 가맹점도 목록에 서므로 상세 화면은 언제나 행에서 들어온다 — 업체명 선택 상자와
/new 화면, 그 선택지를 만들던 전 페이지 훑기를 지운다. 업체(가맹점)는 BizPlay 미러라
[+ 업체 등록]은 시안 자리만 지키고 비활성이다(사용자 확정). 표의 대표이미지는 인라인
흐름에 두어 셀 가운데에 선다.
Co-Authored-By: Claude Opus 5
목록은 백엔드 페이지를 그대로 쓰고(전 페이지 훑기는 등록 화면의 가맹점 선택지에만 남긴다),
상세가 없는 행의 [수정]은 그 가맹점을 고정한 상세 화면으로 가서 거기서 처음 만든다
(사용자 확정). 등록 화면으로 되돌리던 리다이렉트와 그 경로 도우미는 지운다.
Co-Authored-By: Claude Opus 5
제목·경로 표시·구성을 「가맹몰 상세 정보」 하나로 두고, 저장 액션은 리다이렉트 대신 결과를
돌려준다. 처음 저장하면 토스트를 띄우고 그 가맹점 주소로만 옮겨 가 화면은 그대로이고
(바로 메뉴 추가 가능), 이후 저장은 그 자리에서 새로고침한다(사용자 확정). 이미지 칸은
저장으로 파일 id가 바뀌면 다시 마운트해 서버 값과 맞춘다.
Co-Authored-By: Claude Opus 5
dev 로그로 확인 — POST /common/file/upload/MODULE_VOUCHER(·/list)가 68~95KB PNG에도
500을 돌려줘 상세 등록이 막혔다. 저장소 설정 표에 바우처 행이 없고 코드상 기본 저장소
(FILE_STORAGE) 폴백도 dev DB에 행이 없어 거기서 터진다. 한 장은 콘텐츠 섬네일
저장소(MODULE_CONTENT_THUMB), 여러 장 묶음은 4컷만화 저장소(MODULE_TOON_CONTENT)를
빌려 쓴다 — 바우처 행이 생기면 file-module.ts의 두 ID만 바꾼다.
Co-Authored-By: Claude Opus 5
[+ 업체 등록]은 /system/merchant-details/new로 간다 — 업체명 자리에서 상세가 없는 가맹점을
고르면 연락처·주소가 채워지고 나머지는 같은 폼이다(사용자 확정). 행의 [수정]은 언제나 수정
화면이 되도록 목록에는 상세가 등록된 가맹점만 세운다 — 백엔드 목록에 그 조건이 없어
Repository가 전 페이지를 받아 거르고 화면 쪽 페이지로 자른다(TODO 백엔드). 상세가 없는
가맹점의 수정 주소로 들어오면 등록 화면으로 보내 미리 골라 둔다.
Co-Authored-By: Claude Opus 5
/api/v1/mngr/voc/product 계약을 origin/develop 22f67cb로 재확인했다 — 등록은 가맹점만
있으면 받지만 목록·단건·수정·삭제는 상세와 INNER JOIN이라 상세 저장이 먼저여야 한다.
등록 저장 뒤 목록으로 나가면 [수정]을 다시 눌러야 메뉴를 붙일 수 있었으므로, 등록만
같은 화면(수정 모드)에 남긴다. 목록 SQL에 ORDER BY가 없어 노출 순서 오름차순으로
정렬한다.
Co-Authored-By: Claude Opus 5
알림에 대상 컬럼이 없어(TB_COM_NTCN: 제목·내용·읽음뿐) 제목으로 가른다 — 지금 쌓이는
알림은 학습자 1:1문의 등록 하나라 1:1문의 게시판(/boards/inquiries)으로 보낸다. 누르면
드롭다운을 닫고, 링크는 hover·focus 표시를 갖는다. 모르는 알림은 종전처럼 누를 수 없다.
내용 줄은 두 줄로 잘라 요약처럼 보이게 하고 전체는 title로 남긴다. 다만 백엔드가
내용을 고정 문구("학습자가 1:1 문의 게시판에 게시글을 등록하였습니다")로 넣고 있어
실제 게시글 요약은 CmmBbsServiceImpl.insert가 ntcnCn에 글 본문을 실어 줘야 나온다.
Co-Authored-By: Claude Opus 5
타일 아래 「추가 이미지 N」 캡션과 휴지통 아이콘을 지우고 「삭제」 글자(xsm 텍스트 버튼)만
둔다. 「추가 이미지」 캡션은 맨 끝 [+ 추가] 타일 아래에만 붙고, 타일 안은 시안대로
"+ 추가" 한 줄이라 N/11 카운트도 뺀다.
Co-Authored-By: Claude Opus 5
가맹몰 추가 이미지는 타일 자체를 잡아 좌우로 옮기고 하단 [저장] 한 번에 반영하는 방식이다
(사용자 확정). 왼쪽 위 손잡이 버튼을 지우고 li가 draggable·tabindex=0이 되어 마우스는
타일을, 키보드는 초점을 둔 항목을 방향키로 옮긴다. 본문 안 버튼·입력에서 올라오는 키는
받지 않는다.
Co-Authored-By: Claude Opus 5
MngrVocDetailVo는 MngrVocVo를 상속해 useYn을 갖는다 — 등록·수정·조회 모두 실리므로
결함이 아니었다(origin/develop 22f67cb 재확인). 남은 결함은 셋: 단건 SELECT의 상세 컬럼
누락, 등록일 검색 조건 미사용, 바우처 사용 필드 부재. hasDetail 주석도 c5ad833 이후
상태로 맞춘다.
Co-Authored-By: Claude Opus 5
기획 BO-MAL-003(2805:1760)은 등록일시·등록자·최종 수정·현재 상태 네 쌍을 나란히 두는데,
FoxDescriptionList가 세로로 쌓고 줄마다 구분선을 그어 어긋났다. 목록에 inline 변형
(layout="inline")을 더해 쌍을 가로로 놓고 구분선을 뺀다. 이름은 label-sm·subtle, 값은
body-sm으로 시안 실측(12/13px)을 따르고, 쌍 사이 60px는 토큰에 없어 gap-11로 맞춘다.
Co-Authored-By: Claude Opus 5
FoxPageHeader에 description을 더한다 — 가맹몰 시안(FOX-PAY_2.0 2805:635)이 제목 아래
한 줄을 두는데 원 시안(page-tit-area)엔 그 자리가 없었다. 글자는 FoxHeadingGroup의
설명과 같은 토큰(body-md · font-neutral-subtle)이고 FoxListContainer가 그대로 넘긴다.
문구는 시안 그대로다 — 목록(BO-MAL-001) / 등록(BO-MAL-002) / 수정(BO-MAL-003) /
메뉴 등록·수정(BO-MAL-004).
Co-Authored-By: Claude Opus 5
가맹몰 상세 등록 화면의 카드들이 title/description을 넘기는데도 children이 있으면
FoxCard가 머리말을 버려 시안(FOX-PAY_2.0 2805:635)의 카드 제목·설명이 보이지 않았다.
contents를 header(gap 2)·body로 나누고 그 사이를 gap 5로 띄운다. 제목·설명만 있는
기존 카드는 모양이 같다.
Co-Authored-By: Claude Opus 5
상단에 [+ 업체 등록]을 두고, 행 관리는 상세 유무와 관계없이 [수정][비활성|노출][삭제] 세 개로
통일한다(사용자 확정 — 동작보다 시안 우선). 상세는 기존 가맹점에만 붙어 여기서 업체를 만들
수 없으므로 [업체 등록]은 가맹점 관리로 가라는 안내만 띄운다. 상세 없는 행의 [비활성]·[삭제]는
백엔드가 NOT_FOUND로 거절해 사유가 토스트로 올라온다.
Co-Authored-By: Claude Opus 5