시안 btn-page(5402:12368) — 80px 여백, 그룹 하나는 가운데, 버튼은 lg(높이 56)에
최소폭 160. 수제 .actions(가운데 flex + 32px 여백, md 버튼)를 걷어내고 패널이
전부 맡는다. 쇼츠·만화·퀴즈 세 폼이 같은 컴포넌트를 쓴다.
Co-Authored-By: Claude Opus 5
목록 SQL이 rnum(등록일 내림차순)을 ORDER BY RNUM DESC로 다시 뒤집어 옛 글부터
내보내고, LIMIT도 키워드·학교급·파일 조인으로 불어난 행 기준이라 방금 등록한
글이 첫 페이지에 없었다. 페이지 경계에서 잘린 콘텐츠는 키워드 목록도 반쪽으로
온다.
benWord와 같은 우회를 쓴다 — 한 번에 받아(상한 500) 일련번호 내림차순으로 다시
세우고 로컬에서 자른다. 검색어도 서버에 보내지 않는다. 검색 조건이 c.·k. 별칭을
쓰는데 count 쿼리에 별칭이 없어 키워드를 실으면 count가 SQL 오류로 죽는다.
학교·학년·키워드 필터를 모두 로컬로 걸어 총건수도 정확해졌다.
Co-Authored-By: Claude Opus 5
문의는 제목 없이 내용만 온다. 목록의 대표 칸은 내용 발췌(60자 말줄임)로, 답변
팝업의 질문제목 필드는 제거(질문내용 칸이 이미 있다), 삭제 확인 문구는 빈 제목
대신 내용 발췌 30자, 검색 대상에서 제목을 뺀다.
Co-Authored-By: Claude Opus 5
백엔드가 BBS_CD를 코드관리 BBS_FAQ_CD와 조인해 이름(bbsFaqNm)까지 주기 시작했다.
bbsCd는 구분이 아니라 유형이었다 — 구분 배지에 유형 코드를 넣던 매핑을 바로잡고,
FAQ 유형은 서버가 준 이름을 그대로, 1:1 질문유형은 코드로 채운다.
구분은 백엔드에 값이 없어(협의 중) 자리만 두고 '-'로 비운다. 쓰기의 유형도
bbsTypeCd 임시 이름 대신 실제 컬럼(bbsCd)으로 보낸다 — 요청 VO에 필드가 추가되는
즉시 저장까지 동작한다.
노출기간은 조회까지 뚫려 수정 팝업 프리로드가 실값으로 돌고, PUSH_YN은 여전히
SQL 어디에도 없어 앱푸쉬만 남은 결함으로 유지된다.
Co-Authored-By: Claude Opus 5
dev API 앞 프록시가 client_max_body_size 미설정(기본 1MiB)이라 큰 업로드를 봉투
없이 413으로 거절한다(실측: 1,048,000B 통과·1,100,000B 거절). 앱 상한은 100MB라
설정 누락이다 — 인프라 요청 전까지 사유("크기를 넘었습니다")를 화면까지 살린다.
영상 확장자는 백엔드 전역 화이트리스트에 있는 mp4만 남긴다. mov 등을 골라 올리면
크기와 무관하게 서버에서 거절되는데 화면이 미리 막지 못하고 있었다.
Co-Authored-By: Claude Opus 5
예시안 안에 손으로 그린 SVG 도형이 셋 남아 있었다(DemoIcon·DemoStar·DemoCalendar). 이 화면이
곧 사용법 안내라, 버튼·칩·셀렉트 슬롯에 SVG가 들어가 있으면 "아이콘은 이렇게 넣는다"로 잘못
읽힌다 — 실제로 혼동이 생겼다. 셋 다 `fox-ico` 클래스로 바꾼다(CaretRight·Star·CalendarBlank).
호출부 69곳은 그대로다.
폰트 아이콘은 `width`/`height`가 아니라 `font-size`가 크기를 정한다. FoxSelect 힌트 아이콘
15곳의 `style`도 함께 바꿨다.
아이콘 슬롯 prop 주석도 고친다 — "`currentColor`로 그린 SVG여야 한다"가 다섯 컴포넌트에 남아
있어 같은 혼동을 계속 만든다. 마크업 계약을 그대로 적는다.
`DemoThumb`(320×180)만 SVG로 둔다 — 아이콘이 아니라 카드·모달의 사진 자리를 채우는 그림이다.
확인: 예시안의 버튼 아이콘이 "Fox Icons Regular" 16×16으로 그려지고 글리프가 실린다.
칩의 달력도 CalendarBlank로 나온다. 예시안 어디에도 `
`MODULE_BBS`가 저장소 목록에 없어 임시 상수로 빼 두었는데(백엔드가 설정을 못 찾으면 기본
저장소로 조용히 폴백한다) 이제 「게시글 스토리지」로 추가돼 다른 모듈과 같은 자리로 옮긴다.
허용 확장자는 이 저장소만의 목록을 받지 못해 전역 화이트리스트(`Globals.fileUpload.Extensions`)를
그대로 둔다 — 화면이 먼저 막지 않게 하기 위해서다. 저장소 목록이 더 좁으면 백엔드가 사유를
돌려주고 그 문구가 화면에 그대로 나간다. 실제 목록을 받으면 그 한 줄만 바꾼다.
첨부 입력에 `accept`와 확장자 사전 검증이 붙는다 — 지금까지는 아무 파일이나 고를 수 있었고
확장자가 틀리면 백엔드가 사유 없이 실패했다.
Co-Authored-By: Claude Opus 5
findBoardPostById가 있는데 아무도 부르지 않고 목록 행으로 폼을 채우고 있었다.
행은 화면에 떠 있는 동안 낡을 수 있고, 그대로 저장하면 남의 수정을 덮는다.
없어진 게시물이면 얼럿으로 알리고 팝업을 열지 않는다.
Co-Authored-By: Claude Opus 5
백엔드가 toon/video 컨트롤러를 /cntntns 하나로 합치고 CRUD를 열었다. 목록은
searchCntntsType(V·T)으로 갈리고, 단건·등록·수정·삭제가 모두 실제 API를 탄다.
등록은 @RequestBody가 없어 form이라 중첩 목록을 keywordList[0].cntntsKeyword 같은
인덱스 표기로 편다. JSON으로 보내면 한 칸도 바인딩되지 않는다.
학교·학년은 새로 생긴 schulGrdList로 오간다 — 학년마다 한 줄이다.
컷은 upload/list/{moduleId}로 한 첨부에 묶어 올린다. 백엔드가 fileSn을 1,2,3으로
채번해 주므로 컷을 가리키는 건 아이디가 아니라 순번이 됐다. 응답의 fileList로
실제 순번을 받아 미리보기 주소를 만든다.
Co-Authored-By: Claude Opus 5