Tailwind가 프로젝트에서 빠진 뒤에도 클래스만 남아 아무 스타일도 받지 못하던 자리들이
있었고, 전역 스피너는 만들어만 두고 어디서도 호출하지 않았다. 두 손질이 같은 파일들을
건드려 한 커밋으로 둔다.
Tailwind 제거:
- components/ui의 옛 Tailwind 레이어 16개 삭제. 그중 field·icon-button만 실제로 쓰여
각각 FoxTextArea·FoxFormLabel과 @fox 아이콘 버튼 마크업으로 옮기고 지웠다.
- error.tsx 다섯 곳이 같은 모양이라 PageError로 모은다(PageLoading과 같은 이유).
- 홈·Empty 레이아웃·게시판 첨부 링크는 module.scss로, 행 관리 버튼 묶음은 FoxButtonGroup로.
- 테마 토글은 FoxIconButton을 쓰지 못한다 — label이 필수라 aria-label이 늘 붙고, 그러면
테마별로 바뀌는 안쪽 글자를 스크린리더가 읽지 못한다. @fox 아이콘 버튼의 마크업 계약을
그대로 따라 같은 스타일을 받게 했다.
스피너 호출:
- useBlockingAction — 스피너를 켠 채 도는 transition. 삭제처럼 확인 얼럿이 닫힌 뒤
진행돼 표시가 행 아이콘 하나뿐이던 자리 11곳에 붙였다. 버튼이 스스로 "저장 중"을
보여주는 자리(중복확인·주소검색·엑셀 업로드)는 그대로 뒀다.
- 스피너 막도 토스트와 같은 이유로 popover(top layer)에 얹는다 — 모달 안에서 시작한
동작도 덮어야 한다.
- loading.tsx를 (basic) 한 곳으로 모은다. 다섯 화면에만 있던 것을 모든 하위 화면이
받도록 하고, 새 화면을 추가해도 자동으로 따라오게 한다.
Co-Authored-By: Claude Opus 5
Fox*Icon 컴포넌트 141곳을 fox-ico 클래스로 바꾸고 옛 SVG 모듈을 지웠다.
아이콘 상자 규칙에는 상자 크기를 그대로 둔 채 font-size만 더했다 — 손으로 그린
인라인 svg가 든 자리도 같이 쓰이기 때문이다.
사이드바 메뉴 아이콘의 화이트리스트가 사라졌다. 폰트는 통째로 하나라 이름이 늘어도
번들이 커지지 않아, 백엔드가 주는 kebab 이름을 PascalCase로 바꿔 붙이기만 하면 된다.
@fox 13.3MB → 6.4MB.
Co-Authored-By: Claude Opus 5
유형을 프론트 상수 표(SIGNUP/PAYMENT/…)로 치환하고 있었다. 그 표를 지우고 공통코드
`BBS_FAQ_CD`를 조회해 상세코드명으로 옮긴다 — 1:1문의 진행상태(BBS_ANS_CD), 학교·학년
(COM_SCHUL_CD·GRD_CD)과 같은 방식이다.
목록의 「유형」 열과 등록·수정 팝업의 유형 선택지, Server Action의 허용 코드 검증이 모두 같은
응답을 본다. 페이지가 한 번 조회해 목록으로 내리고, Server Action은 저장 직전에 다시 조회한다
(화면이 보낸 코드를 그대로 믿지 않기 위해서다).
목록 URL의 `type` 필터만 예외로 뒀다 — `parseBoardPostQuery`는 도메인 계층이라 코드 조회를 할 수
없어 FAQ에서는 값을 그대로 받는다. 모르는 코드면 결과가 비는 것으로 끝나고, 저장 검증은 위에서
코드표로 한다.
코드가 한 건도 없으면 유형 칸을 그리지 않고 검증도 요구하지 않는다 — 빈 셀렉트를 보여 주고
"유형을 선택해 주세요"로 막으면 저장할 방법이 없어진다.
확인: 임시 페이지로 목록의 FAQ01→회원가입&로그인 치환, 표에 없는 코드(ZZZ99)는 코드 그대로
노출, 등록 팝업 선택지가 코드명으로 뜨고 고르면 hidden 필드에 코드값(FAQ01)이 실리는 것을
확인한 뒤 지웠다.
Co-Authored-By: Claude Opus 5
상태를 프론트 상수 표(`WAIT`/`ING`/`DONE`)로 치환하고 있었다. 그 표를 지우고 공통코드
`BBS_ANS_CD`를 조회해 코드명으로 옮긴다 — 꾸미기 아이템 카테고리(`ITEM_CATE_CD`)와 같은 방식이다.
목록의 "상태" 열과 답변 팝업의 진행상태 선택지, Server Action의 허용 코드 검증이 모두 같은
응답을 본다. 페이지가 한 번 조회해 목록으로 내리고, Server Action은 저장 직전에 다시 조회한다
(화면이 보낸 코드를 그대로 믿지 않기 위해서다 — 아이템 카테고리와 같은 근거).
`ANSWER_STATUS_DONE`만 상수로 남는다. "답변완료일 때만 FO 노출·답변일 표시"라는 판단이 특정
코드값을 알아야 하는데 BBS_ANS_CD의 실제 값을 아직 확인하지 못해 TODO로 표시해 두었다.
Co-Authored-By: Claude Opus 5
두 가지가 어긋나 있었다.
**분류 필터가 탭이었다.** 시안은 `chip-area`에 `chip` 세 개(전체·노출·미노출)다.
`FoxTab`을 `FoxChipArea` + `FoxChip type="action"`으로 바꿨다 — `check` 계열은 켜졌을 때
체크 아이콘이 붙는데, 시안의 "전체"와 "노출"이 둘 다 42px로 같아 아이콘이 없는 계열이다.
초기화 버튼도 시안이 28×28이라 `size="md"`(40)에서 `sm`으로 내렸다.
**검색 대상에 구분이 없었다.** 시안은 닫힌 상태가 "구분"인데 공지사항의 검색 대상이 제목
하나뿐이었다. 구분을 첫 항목으로 넣어 기본값이 되게 하고, 검색값은 코드가 아니라 표기 라벨로
견준다(사용자가 "공통"을 치면 걸리게).
확인: 초기화 버튼 28×28, chip-area x=36, 칩 43/43/56×28, 체크 아이콘 없음, 검색 대상 "구분" —
시안 치수와 1px 안에서 일치한다.
Co-Authored-By: Claude Opus 5
`board-post-columns.tsx`가 `'use client'` 모듈인데 서버 컴포넌트인 page가 거기 함수를 직접
호출했다 — 클라이언트 모듈의 non-component export는 서버에서 참조 프록시라 부르면 던진다
("Attempted to call faqColumns() from the server"). 공지·FAQ·1:1문의 세 화면이 모두 같았다.
컬럼을 클라이언트에서 만들도록 옮겼다. `boardPostColumns(boardType, page, pageSize)` 하나가
세 팩토리를 갈라 주고, `BoardPostList`가 이미 받고 있던 boardType·currentPage·pageSize로 직접
부른다. page는 columns prop을 넘기지 않는다.
옮기지 않고 `'use client'`만 떼는 방법은 안 된다 — 컬럼의 `render`가 함수라 서버에서 만들어
클라이언트로 넘기는 것 자체가 RSC 경계를 못 넘는다. 만드는 쪽을 클라이언트로 옮겨야 한다.
확인: FAQ 목록을 클라이언트에서 렌더해 컬럼 8개(번호·구분·유형·제목·작성자·등록일·사용여부·
관리)가 서고 콘솔 오류가 없다.
Co-Authored-By: Claude Opus 5
시안 관리자페이지(QsFVFFUKGH68xAPVkF3SJ9) A_BOA 목록 5227:5058 · 등록 팝업 5227:5848.
공지사항·1:1문의·FAQ 세 화면이 같은 뼈대를 쓴다.
stngId를 실제 값으로 바꿨다. 종전 TEMP_STNG_ID_* 임시값이라 목록이 늘 비어 있었다
(/api/v1/common/bbs/stng/list 응답, typeSe가 셋 다 'NOT'이라 구분에 쓸 수 없어 하드코딩).
목록 — FoxListContainer + 시안의 필터 줄(새로고침 아이콘 + 전체/노출/미노출 알약 탭).
구분은 FoxBadge(neutral), 사용여부는 FoxStatusIndicator, 첨부는 클립 아이콘, 관리는 테두리
아이콘 버튼. 세 화면이 열 정의만 다르고 나머지는 공유한다.
등록·수정 팝업 — FoxModal(md=560, 시안 폭)에 구분·제목·내용(FoxTextArea)·첨부파일
(FoxFileUpload default)·상단고정·게시기간·사용여부·앱푸쉬. 공지사항 전용 항목은 그 게시판에서만
그린다. 죽은 components/ui 대신 전부 @fox다.
옛 표·툴바·필터바 컴포넌트 5개는 지웠다(참조 0).
@fox: FoxTextArea에 requirement 추가 — 다른 폼 컴포넌트와 같은 규약.
TODO(백엔드): 구분(bbsCd)은 조회로만 오고 등록·수정 요청 VO에 필드가 없어 저장되지 않는다.
TODO: 게시기간이 네이티브 date 입력이다 — 시안은 YYYY.MM.DD 형식의 전용 필드이고 @fox에
날짜 선택 조각이 없다.
TODO: 목록 정렬이 백엔드 고정(등록일 오름차순)이라 "최근등록순" 셀렉트가 표시만 한다.
검증 — 시안 대조 실측: 모달 560px, 첨부 [파일선택] 버튼 100px 정상 노출, 목록 8열·필터 알약·
페이지네이션 정상.
Co-Authored-By: Claude Opus 5