Install
Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/ivystation/wp-qna-board/releases/download/v0.5.3/wp-qna-board.zipUpdates itself. It ships its own updater, so new versions appear under Dashboard → Updates.
Q&A 게시판 (WP Q&A Board)
비회원 작성 가능한 Q&A 게시판. CPT(inquiry) + WP 기본 비밀번호 보호 + 쿠키·IP 24시간 본인 세션 + 관리자 답변 댓글. KBoard 마이그레이션 WP-CLI 커맨드 포함.
Description
KBoard 같은 자체 테이블 기반 게시판을 WordPress 표준 자산만으로 대체하기 위한 재사용 플러그인.
- Custom Post Type
inquiry등록 (/inquiry/슬러그, REST 노출) - 택소노미
inquiry_category(활성화 시 5개 카테고리 자동 시드: 어학연수 / 대학·대학원 / 조기유학 / 비자 / 기타) - 비회원이 이름·이메일·비밀번호로 글 작성
- WP 내장
post_password로 비밀글 보호 (본문·첨부·댓글 일괄 마스킹) - 본인 인증: HMAC-SHA256 쿠키 토큰 + 요청 IP 일치, 24시간 lifetime
- 본인 글 수정·삭제, 비번 변경
- 댓글: 관리자 + 작성자 본인만, "관리자 답변" 배지 자동
- 본문 에디터: 텍스트 전용 최소 구성 (
<p>/<br>/<a>만 허용) - 첨부 다중 업로드 (화이트리스트 확장자 + 용량 상한, WP 미디어 라이브러리에 정식 등록)
- reCAPTCHA v3 + 허니팟 + IP/Email throttle
- WP-CLI:
wp inquiry migrate-kboard --board=<uid>(idempotent, dry-run, batch, resume, since) - 레거시 KBoard URL (
?mod=document&uid=...) → 새 inquiry 글로 301
Installation
wp-content/plugins/wp-qna-board/에 파일 업로드 또는 zip 으로 업로드.- 플러그인 활성화. (CPT, 택소노미, 카테고리 5개, capability 자동 설치.)
- Settings → Q&A 게시판 에서 reCAPTCHA·첨부·세션 설정.
- 폼을 노출할 페이지에
[inquiry_form]숏코드 삽입.
KBoard 마이그레이션
WP-CLI 가 활성인 환경에서:
wp inquiry migrate-kboard --board=<kboard_uid> --dry-run— 통계만 출력wp inquiry migrate-kboard --board=<uid> --batch=200— 본 작업wp inquiry migrate-kboard --board=<uid> --only=comments— 댓글만wp inquiry migrate-kboard --board=<uid> --since="2026-05-17 00:00:00"— delta 흡수
KBoard category1/category2 와 새 5개 슬롯의 매핑은 inc/migration-map.php 에서 보정한다.
secret=1 인데 비번 없는 글은 무작위 8자 영숫자로 발급되고 wp-content/private/inquiry/inquiry-migration-passwords.csv 에 산출된다 (.htaccess deny 자동).
Changelog
0.13.0
- 헤드리스 프론트용 REST
qna/v1— 목록·상세·비밀글 열기(IP 당 10분 10회)·작성 폼 정보·작성. inquiry CPT 의 wp/v2 노출은 계속 막는다. - 작성 검증·스팸 방어를
inquiry_board_create_inquiry()로 분리해 폼(admin-post)과 REST 가 같이 쓴다.
0.12.0
- security(spam): 스팸 봇 방어를 다층으로 강화. Cloudflare Turnstile 을 폼에 통합 —
simple-cloudflare-turnstile플러그인의 사이트 전역 키(cfturnstile_key/cfturnstile_secret)를 재사용해 위젯을 노출하고 서버에서 siteverify 로 토큰을 재검증한다. 방어 우선순위는 Turnstile → reCAPTCHA(둘 중 사이트에 설정된 것). Turnstile 미설치 사이트에서는 기존 reCAPTCHA 동작 유지. - security(spam): time-trap 추가. 폼 렌더 시각을 HMAC 서명해 hidden 필드로 내보내고, 제출까지 3초 미만(즉시 POST)·1시간 초과면 거부한다. JS 없이 폼을 직접 POST 하는 봇을 걸러낸다.
- security(privacy): inquiry CPT 를 REST 에서 비공개(
show_in_rest=false). 기존에는/wp-json/wp/v2/inquiry로 비밀글 제목과 전건 목록이 비로그인에게 노출됐다(본문은 가려지지만 제목은 raw). 헤드리스·에디터가 inquiry REST 를 쓰지 않으므로 영향 없다(편집은 v0.7.0 부터 Classic Editor). - test:
tests/test-security.php— time-trap 서명·체류시간, Turnstile 분기, REST 비공개, 폼 렌더 검증. - 참고: author enumeration(
?author=N·/wp-json/wp/v2/users) 차단은 사이트 전역 사안이라 별도 mu-plugin(ivy-block-user-enum)으로 처리한다.
0.11.0
- feat(form): 글쓰기 폼에 동의 체크박스 2개 추가 — [필수] 개인정보 수집·이용 / [선택] 마케팅 정보 수신.
_inquiry_privacy_consent·_inquiry_marketing_consent메타('1'/'0')로 저장한다.'1'은 wowbiz-sync 가 동의로 인정하는 값이라 CPT 매핑의consent에 그대로 연결할 수 있다. - 두 항목을 분리한다. 하나로 묶으면 문의하려면 어차피 체크해야 하므로 전원이 마케팅 수신 동의로 집계되어 광고성 발송 대상 판단이 무의미해진다.
- 둘 다 기본 미체크. 개인정보 동의만
required이고, 마케팅 미동의로도 문의 접수·답변에 제한이 없다. 서버에서도 개인정보 동의를 재검증한다(폼 우회 제출 방어). - 개인정보취급방침 링크는 WP 표준
get_privacy_policy_url()로 출력한다. 사이트의 「설정 → 개인정보」에 방침 페이지가 지정돼 있어야 링크가 나온다(미지정이면 문구만 노출). - 알림 메일 메타 행과 편집화면 답글 요약에 「마케팅 수신」 동의/미동의를 표시한다. 메타가 없는 기존 글은 미동의로 읽는다.
- 동의 카드는 기존 공개/비공개 선택과 같은 스타일을 공유하되(
.inquiry-consent-opt를 셀렉터 그룹에 추가) 설명이 길어 항상 1-up 으로 둔다. - test:
tests/test-consent.php셀프체크 (폼 렌더 9 · CSS 1 · 알림 메일 4). 기본 미체크 회귀를 잡는 항목 포함.
0.10.2
- refine(form): 제목·카테고리를 2-up 인라인으로 배치(기존 세로 스택). 기존
.inquiry-form-grid--2col을 재사용하므로 CSS 변경은 없고, ≤768px 에서는 다른 그리드와 함께 1-col 로 접힌다.
0.10.1
- fix(form): 연락처 필드만 다른 입력란과 스타일이 달랐다(폭이 컨테이너를 안 채우고 테두리·포커스 링도 미적용). 폼 입력 스타일이
input[type=…]화이트리스트 셀렉터라 새로 추가한tel이 빠져 있던 것..inquiry-form input[type="tel"]을 기본·focus 두 규칙 모두에 추가했다. - 새 input 타입을 폼에 추가할 때는
assets/wp-qna-board.css의 두 셀렉터 목록도 함께 갱신할 것 —tests/test-phone.php가 이 누락을 잡는다.
0.10.0
- feat(form): 글쓰기 폼에 연락처(휴대폰) 필수 입력 추가.
_inquiry_author_phone메타로 저장한다. app.wowbiz.net 연락처 동기화(wowbiz-sync 의 CPT 매핑phone)가 이 메타를 읽어간다. inquiry_board_normalize_phone()— 국내 휴대폰(01x)만010-1234-5678로 통일하고, 지역번호·국제표기(+44 등)는 입력값을 보존한다. 숫자 9~15자리를 벗어나면 검증 실패.- 알림 메일 메타 행과 편집화면 답글 메타박스 요약에 연락처를 노출한다(메일은
tel:링크). 연락처 메타가 없는 기존 글은 "미입력" 으로 폴백. - 폼 그리드가 이름·이메일·연락처 3-up(비밀번호 필수 설정 시 4-up, ≤1024px 에서 2×2) 으로 바뀌었다.
- test:
tests/test-phone.php셀프체크 (정규화 12 · 폼 렌더 3 · 메일 데이터 2).
0.9.0
- feat(form): 글쓰기 폼에 「공개 / 비공개」 선택 추가. 공개가 기본이고, 비공개를 고를 때만 비밀번호 입력란이 나타난다(JS 토글 + 서버 재검증). 공개글은 비밀번호를 저장하지 않는다.
- 기존
password_required옵션이 그동안 어디에서도 쓰이지 않는 dead option 이었다. 이제 실제로 동작한다 — 켜면 예전처럼 모든 글이 비공개로 강제되고 공개 선택지가 숨겨지며, 끄면 공개/비공개 선택 UI 가 나타난다. 설정 라벨도 「비밀번호 필수 여부」 → 「글 공개 설정」 으로 바꿨다. - 판정 로직을
inquiry_board_is_private_submission()으로 분리해 단위 검증이 가능하게 했다. 공개 제출 시 폼에 남아 있던 비밀번호 값은 서버에서 버린다. - 접근성/UX: 공개 선택 시 비밀번호 필드의
required를 제거한다 — 숨겨진 필드에required가 남아 있으면 브라우저 기본 검증이 제출을 막는다. 필드는[hidden]+ CSS 로 이중 차단(테마가[hidden]을 덮어쓰는 경우 대비). - 공개글은 24시간 세션이 끝나면 본인 수정 수단이 없다(비밀번호가 없으므로). 폼 안내 문구로 명시했다.
- test:
tests/test-visibility.php셀프체크 17항목 (판정 로직 6 · 옵션별 폼 렌더 8 · 공개/비공개 표시 2 · 옵션 원복 1).
0.8.0
- feat(notify): 알림 메일을 HTML 템플릿으로 전면 개편. 기존에는 「작성자 + 관리 화면 링크」 두 줄짜리 plain text 였다.
- 담기는 정보: 제목 · 카테고리/비밀글 배지 · 작성자 · 이메일(mailto 링크) · 등록일시 · 첨부 파일 목록(파일명 + 용량 + 다운로드 링크) · 본문 발췌(600자 초과 시 자르고 안내 문구)
- CTA 2개: 「관리 화면에서 답변하기」(v0.7.0 답글 UI 로 직행) · 「문의 페이지 보기」
- 푸터에 발송 이유와 수신자 변경 위치 안내
- feat(notify): 제목을
[사이트명] 새 문의 · <카테고리> — <제목>형식으로 개선 (기존[사이트명] 새 문의: <제목>). - feat(notify): 문의자 주소가 있으면
Reply-To헤더를 설정해 관리자가 메일에서 바로 회신할 수 있게 했다. - 디자인: 플러그인 디자인 토큰과 정렬(indigo
#533afd액센트, deep ink#0f172aCTA, hairline#e3e8ee). 메일 클라이언트 호환을 위해 table 레이아웃 + 인라인 스타일만 사용하고 한글 폰트 스택을 포함했다. Outlook 은border-radius를 무시하므로 각진 카드로 자연스럽게 폴백된다. - refactor: 알림 관련 코드를
inc/form.php에서inc/notify.php로 분리(수신자 파싱 · 데이터 수집 · 제목/HTML 빌더 · 발송 · 상태 전이 훅). 첨부 ID 조회 헬퍼inquiry_board_get_attachment_ids()는 알림과 관리 화면이 공용이라 항상 로드되는inc/form.php로 옮겼다(inc/admin-reply.php는is_admin()안에서만 로드되므로 거기 두면 프론트 발송 경로에서 미정의가 된다). - test: 셀프체크를 HTML 메일 기준으로 확장 — Content-Type · Reply-To · CTA · 배지 · 발췌 트리밍 · 제목 형식 포함 총 30항목.
0.7.0
- feat(admin): 문의 편집 화면(post.php)에 「답글 작성 · 대화 스레드」 메타박스 추가 (
inc/admin-reply.php). 그동안 관리 화면에는 답글 UI 가 아예 없어서 WP 기본 댓글 박스로만 답변할 수 있었다. 이제 한 화면에서 원문 + 첨부 + 전체 스레드를 보고 바로 답변을 등록한다.- 상단 요약: 작성자 · 이메일 · 카테고리 · 답변 상태 배지 · 답변 수(관리자/전체)
- 스레드: 문의 원문(파란 라벨) + 댓글 시간순. 관리자 답변은 파란 배경(
#eff6ff), 작성자 답글은 흰 배경으로 구분 - 첨부: 이미지 썸네일 / 그 외 확장자 칩 + 파일 크기.
_inquiry_attachments메타 우선, 없으면 attachmentpost_parent폴백(마이그레이션 글 대응) - 편집 화면은 이미
<form id="post">로 감싸져 있어 중첩 form 을 만들 수 없으므로 admin-ajax.php 로 제출(nonce +edit_postcap 검사). 성공 시?inquiry_reply_notice=ok로 리로드
- feat(admin): inquiry 를 Classic Editor 로 연다(
use_block_editor_for_post_type필터). 익명 문의라 본문 편집 수요가 낮고, 블록 에디터에서는 classic 메타박스가 본문 아래로 밀려 답글 UI 접근성이 떨어진다. 되돌리려면 해당 필터만 제거. - 답변 상태는 새 메타를 만들지 않고 관리자 답변 댓글 유무로 계산한다(「답변대기 / 답변완료」). 기존 글에도 즉시 적용되고 목록·프론트·마이그레이션에 파급이 없다.
- 답글 저장은
wp_new_comment()가 아니라wp_insert_comment()를 쓴다 — 전자는 flood/duplicate 검사로 관리자의 연속 답변을 거부할 수 있고 승인 상태도 필터 체인이 덮어쓴다. 대신comment_post훅이 돌지 않으므로_is_admin_reply는 직접 마킹한다. - 참조 구현: ivynet-16 / atumdgbktx 의 mu-plugin "Headless Support Tickets"(
support_ticketCPT). 화면 구성을 맞추되 익명 작성자 메타 ·inquiry_category택소노미 ·_is_admin_reply등 inquiry 도메인에 맞게 매핑했다.
0.6.0
- feat(notify): 알림 메일 수신자를 쉼표 구분 다중 지정 지원으로 확장. 일반설정 「관리자 알림 수신 이메일」 에
a@x.com, b@y.com형식으로 여러 명을 넣을 수 있다(input type="email" multiple). 세미콜론·공백 구분도 관대하게 파싱하며 유효하지 않은 주소는 저장 시 탈락. 미입력 시 기존대로 사이트admin_email폴백. - fix(notify): 알림 발송 지점을 프론트엔드 폼 핸들러 내부 호출에서
transition_post_status훅으로 이동. 기존에는 프론트엔드 글쓰기 폼으로 등록한 경우에만 메일이 나가고 관리 화면 직접 작성 · WP-CLI · REST 로 등록한 문의는 알림이 누락되었다. 이제 모든 등록 경로가 한 곳에서 커버된다. - fix(notify): 알림 메일의 「관리 화면」 링크가 항상 비어 있던 버그 수정.
get_edit_post_link()는 현재 사용자의edit_post권한을 검사하므로 비로그인 방문자가 폼을 제출하는 경로에서 빈 문자열을 반환했다.admin_url( 'post.php?post=ID&action=edit' )로 교체. _inquiry_notified메타로 글 1건당 1회만 발송 — 수정 저장·휴지통 복구 시 재발송되지 않는다. 발송은shutdown으로 미뤄 폼 경로에서wp_insert_post이후 저장되는 작성자명 메타가 메일에 정상 포함되게 한다.- 설정 화면 [사용법] 탭 §5 알림 메일 설명을 위 동작에 맞게 갱신.
- fix(security): 「GitHub Token (선택)」 필드에 PAT 형식 검증 추가 (
ghp_…/github_pat_…/ 40자 hex 만 허용, 그 외는 저장 거부 + 관리 화면 오류 안내). 브라우저 비밀번호 매니저가type="password"필드에 사이트 로그인 비밀번호를 자동완성해 평문으로 DB 옵션에 저장되는 사고가 반복됐다(2026-05-17 발견, 2026-07-31 재발). 아울러autocomplete="off"→autocomplete="new-password"로 교체 — 브라우저는off를 무시한다. sanitize 는 WP-CLI 의update_option경로에서도 실행되므로add_settings_error()는function_exists가드로 감쌌다. - test:
tests/test-notify.php셀프체크 추가 (wp eval-file로 실행). 수신자 파싱·폴백·저장 왕복 회귀·발행 1회 발송·중복 방지·토큰 형식 검증 17항목. 실제 메일은pre_wp_mail로 가로채므로 발송되지 않는다.
0.5.5
- refine(list): 목록 테이블 모바일(≤640px) 다듬기 — 카드 border/shadow/radius 제거하여 풀폭, row 좌우 padding 16px → 4px 로 최소화. 작성자·작성일 메타를 caption(13px) → micro(11px) 로 축소하고 가운데점 마진 8px → 6px 로 더 컴팩트하게.
0.5.4
- feat(list): 목록 테이블 모바일(≤640px) 카드형 stack 레이아웃.
<thead>숨김, 행 단위로 풀폭 제목 + 그 아래 「작성자 · 작성일」 메타 라인. col-num, col-cat 은 모바일에서 계속 숨김. 좌우 패딩을 row 단위 16px 로 통일해 컨테이너 내부 여백 균일화. 데스크탑(>640px) 그리드·헤더는 무수정.
0.5.3
- fix(button): primary CTA(글쓰기·등록 하기·수정 저장·답글 등록·확인) 톤을 indigo
#533afd→ 검정(deep ink)#0f172afill + 흰 텍스트 로 통일. ukuhak.com 에서 테마(Uncode) 의button[type=submit]글로벌 룰이 indigo bg 를 흰색에 가깝게 덮어써서 흰 텍스트가 안 보이던 문제 해결. hover#1e293b, active#000000. - fix(button): primary CTA selector specificity 를
.inquiry-reply-submit.inquiry-reply-submit처럼 클래스 두 번 기재로 (0,2,0) 까지 올리고 핵심 속성(background, color, border, border-radius) 에!important부여하여 테마 override 방어.box-shadow: none,text-shadow: none명시. - fix(reply-submit): 단일 페이지 「답글 등록」 의 라운드·hover 가 다른 primary CTA 와 달라 보이던 문제 해결. 동일 통합 selector 그룹에 묶어 hero 글쓰기 버튼과 시각·인터랙션 완전 일치.
- fix(reply-submit hover): hover 시 텍스트 색이 흰색에서 안 보이게 변하던 문제 해결 — hover 룰에서
color: var(--inq-primary-fg) !important명시. hover 시 -1px translateY + 부드러운 deep shadow 로 lift 피드백 추가. - feat(form): 글쓰기 폼의 「이름 / 이메일 / 글 비밀번호」 입력 행을 데스크탑 3-column / 모바일(≤768px) 1-column grid 로 묶음.
templates/inquiry-form.php에<div class="inquiry-form-grid inquiry-form-grid--3col">wrapper 추가, CSS 에.inquiry-form-grid--2col/.inquiry-form-grid--3col토큰 추가. 비밀번호 안내문은 grid 바깥의.inquiry-form-help단락으로 분리. - hero 글쓰기 버튼(
.inquiry-write-btn--lg) 사이즈: padding 12/32 → 14/36, min-height 44 → 48 로 hero 급으로 키움. 색·라디우스는 통합 selector 가 담당.
0.5.2
- 글쓰기 / 수정 폼의 가로 폭을 목록 페이지(
.inquiry-board-list) 와 동일한 컨테이너 100% 로 변경 (v0.5.0 까지 적용된 75% 제한 해제). ukuhak.com 피드백 반영. 단일 페이지(.inquiry-single-wrap) 는 기존대로 75% 유지. - 글쓰기 폼 헤더(
.inquiry-form-header) 를 3-grid(목록으로 | 타이틀 | 여백) 로 재구성 + 하단 hairline 1px 구분선. 타이틀(.inquiry-form-title) 은 display-lg(32px, weight 300) → heading-md(20px, weight 400) 로 컴팩트하게. - 「목록으로」 (
.inquiry-list-btn) 사이즈 다운(min-height 36 → 32px, padding 8/16 → 6/14, font tabular → caption) — primary CTA 「등록 하기」 와 시각적 위계 분명히. - 카테고리·라벨 select(
<select>) 에 네이티브 chevron 제거 + indigo SVG chevron(%234434d4) 으로 교체.appearance: none+padding-right: 40px+ 우측 14px 위치. - 입력 필드 padding 8/12 → 10/14, min-height 40 → 42 로 살짝 키워 타이핑 가독성 ↑.
- 라벨 톤을 caption(13px, ink-secondary, -0.39px 트래킹) 으로 정리, 필수 표식(
*) 은--inq-ruby컬러. - 「등록 하기」 / 「수정 저장」 행(
.inquiry-form-actions): hairline 분리선 위에 우측 정렬. 모바일(≤640px) 에서는 column + full-width 로 터치 영역 확보. - body class 필터 추가:
[inquiry_form]숏코드가 박힌 페이지에 자동으로inquiry-shortcode-page클래스 부여 (inc/form.php). 단일 inquiry CPT 페이지(body.single-inquiry) 와 동일한 hero-hide CSS 가 글쓰기·목록 페이지에도 적용된다. - Uncode 호환 hero·share·breadcrumb 영역 hide 확대:
.share-on-side,.share-on-hover,.post-share,.uncode-share,.header-share,.breadcrumb(s),.breadcrumb-trail,.uncode-breadcrumb,.post-header,.page-hero,.uncode-page-hero,.post-title-wrapper,.page-title-wrapper,.single-header모두 inquiry 관련 페이지에서 숨김. 본문 상단 padding 도.post-content64px →--inq-gap-xl(24px) 로 줄임.
0.5.1
- fix(thread): 관리자 답변 박스(
.inquiry-msg-admin) 배경이 deep navy#1c1e54fill 이라 사이트 라이트 톤과 너무 대비되어 어둡게 보이던 문제 해결. 본문 배경을 ultra-light lavender#f6f5ff, 헤더 띠를 한 톤 진한#eceafd, 보더를--inq-primary-subdued(#b9b9f9) 로 변경. 좌측에 4px indigo accent bar(::before) 를 추가해 admin reply 정체성은 indigo 시그니처로 유지. 본문 텍스트는--inq-ink(#0d253d) deep navy 그대로 두어 가독성 향상. - role pill
inquiry-msg-role-admin: 어디서나 동일한 filled indigo 톤으로 단순화 (이전에는 admin bubble 안에서 lighter indigo soft 로 전환했으나 light bg 에서는 구분이 약해 원래 톤 유지). - admin reply 내부 링크: indigo deep (
#4434d4) + 1px underline 으로 light bg 에서도 명확히 보이도록.
0.5.0
- DESIGN.md(Stripe 디자인 시스템) 적용 — 플러그인 전 화면(목록 / 단일 / 글쓰기 / 수정 / 비밀번호 / 답변 스레드) UI 를 indigo CTA + deep navy ink + Inter 300 + pill 버튼 + hairline 카드 톤으로 재구성.
- color tokens: amber primary(
#fbbf24) → indigo#533afd(--inq-primary), hover#4434d4(--inq-primary-deep), pressed#2e2b8c(--inq-primary-press). 본문 텍스트는 deep navy#0d253d(--inq-ink). 보더는 hairline#e3e8ee(--inq-hairline), 입력 보더는#a8c3de(--inq-hairline-input). 그라데이션 스톱(cream/orange/lavender/indigo/magenta)을 토큰화. - shape: 모든 버튼은 pill (
--inq-radius-pill: 9999px). DESIGN.md "Don't shrink button padding below 8px 16px" 준수. 카드·테이블 컨테이너는 rounded-lg(12px) + Level 1 shadow0 1px 3px rgba(0,55,112,.08). - typography: Inter 300/400 을 Google Fonts 로 enqueue (
wp-qna-board-inter).font-feature-settings: "ss01"전역, 숫자 셀(번호·날짜·페이지·카운트 뱃지)에는 추가로tnum. display tier 는 weight 300 + negative letter-spacing. - hero mesh backdrop: 목록 페이지(
.inquiry-board-list) 상단에 cream/orange/lavender/indigo/magenta 5-stop radial-gradient 를 CSS 로 근사 출력하여 DESIGN.md 시그니처 mesh 분위기 부여 (blur + saturate). - 관리자 답변 메시지: DESIGN.md
card-pricing-featured톤(--inq-brand-dark: #1c1e54fill + 흰 텍스트 + Level 2 shadow) 으로 featured tier 처럼 표시. - role 배지: pill 형태. admin 은 filled indigo, owner 는 subdued indigo(
--inq-primary-subdued: #b9b9f9+--inq-primary-deep). - 파일 첨부 칩: 회색 박스 →
pill-tag-soft톤(subdued indigo) pill 칩. - 비번 입력 폼(
.inquiry-password-form): bare → card 형 (canvas + hairline + rounded-lg + Level 1 shadow + indigo pill 「확인」 버튼). - 삭제 폼: ruby outline pill 로 destructive 의미 부여, hover 시 ruby fill.
- preconnect: fonts.googleapis.com / fonts.gstatic.com 에
<link rel="preconnect">헤더 추가 (Inter 첫 paint 지연 최소화). - version 상수 동기화:
INQUIRY_BOARD_VERSION도0.5.0. (이전 v0.4.12 에서는 plugin header 만 0.4.12 였고 상수는 0.4.10 에 머물러 있어wp_enqueue_*의 cache buster 가 갱신되지 않던 버그도 함께 해소.)
0.4.12
- design tokens: 전역 CSS 변수 도입.
assets/wp-qna-board.css최상단:where(...)블록에--inq-bg,--inq-text,--inq-border,--inq-primary-bg,--inq-secondary-*,--inq-radius-*,--inq-font-*,--inq-gap-*등 색·라디우스·폰트·간격을 토큰화. specificity 0 으로 노출해 테마/자식 테마에서 단순 오버라이드 가능. 후속 패치(v0.4.13 예정) 에서 관리자 설정 페이지의 color picker 가 이 값을 동적으로 덮어쓰도록 wp_head 인라인:root블록을 출력할 예정. - primary action: 큰 글쓰기 버튼(
.inquiry-write-btn--lg), 단일 페이지 답글 등록(.inquiry-reply-submit), 글쓰기/수정 폼 제출(.inquiry-form button[type="submit"]) 의 톤을 amber 채움(#fbbf24/ hover#f59e0b/ active#d97706+ 흰 글자 +box-shadow) 으로 통일. 단일 페이지 「답글 등록」 = 목록 「큰 글쓰기」 = 글쓰기 「등록 하기」 동일 시각. - secondary action: 단일 페이지 「← 목록으로」(
.inquiry-back-link), 목록 하단 작은 글쓰기(.inquiry-write-btn), 글쓰기 화면 「← 목록으로」(.inquiry-list-btn) 의 톤을 secondary 토큰(흰 박스 +--inq-border+ hover--inq-bg-admin) 으로 통일. - 큰 글쓰기 버튼 사이즈: v0.4.11 의
padding: 16px 32px / font-size: 22px가 너무 크다는 피드백에 따라 가로(좌우 padding 32px) 는 유지하면서 상하 padding 10px + font-sizevar(--inq-font-xl=16px)로 축소(높이 약 60% 수준). - 글쓰기 화면 컨테이너 폭:
.inquiry-form-wrap,.inquiry-form-header,.inquiry-form,.inquiry-edit-form의 폭을 단일 페이지(.inquiry-single-wrap) 와 동일하게 75% (모바일 ≤768px 100%). 글쓰기 폼을<div class="inquiry-form-wrap">…</div>로 wrap 추가. - 파일 첨부 UI: 글쓰기 폼의
<input type="file">을 클립 아이콘(SVG) + 「파일 첨부 (선택수/최대)」 카운트 라벨 + 확장자·용량 안내 + 선택 파일 칩 리스트 UI 로 교체.assets/wp-qna-board.js에 file picker 핸들러 추가 — 선택 시 카운트·칩 갱신, 최대 개수(현재 5 하드코딩) 초과 시 alert + input 초기화. 후속 패치에서max_attachments옵션 분리 예정. - form input/textarea/select 톤 통일: 모든 입력 요소가
--inq-input-*토큰 사용 (padding 10px 12px,border-radius: var(--inq-radius-sm), focus 시border-color: var(--inq-input-border-focus)). - 「등록」 라벨을 「등록 하기」 로 변경.
0.4.11
- list: 상단 글쓰기 버튼(
.inquiry-write-btn--lg)을 중앙 정렬 + 약 2배 크기(font-size: 22px,padding: 16px 32px)로 확대. primary blue(#1d4ed8) 채움 + 흰 글자 + 살짝의 그림자(box-shadow: 0 6px 16px rgba(29,78,216,.18))로 시인성 강화. - list: 하단에 원래 사이즈의 글쓰기 버튼(
.inquiry-list-actions--bottom)을 추가해 페이지네이션과 같은 라인에 배치. 신규.inquiry-list-footer가 grid 3컬럼(1fr / auto / 1fr) 로 페이지네이션을 시각적 중앙에 두고 글쓰기 버튼을 우측 끝에 정렬. 모바일(≤600px) 에서는 1컬럼으로 stack. - pagination:
nav.inquiry-pagination과 내부ul/ol/li의 외곽 라인(테마/플러그인이 추가하는 경우)을border: 0; background: transparent; box-shadow: none으로 명시적으로 제거. 각 페이지 숫자(.page-numbers)의 보더는 그대로 유지.
0.4.10
- fix(list): 페이지네이션 클릭 시 404 발생 수정.
paginate_links()가?paged=N으로 URL 을 생성하면 WPredirect_canonical이 일반 page(쇼트코드를 박아 둔 페이지) 에서 자동으로/page/N/로 301 redirect 하는데, 해당 page 에는 `분할이 없어 404 가 떴다. 자체 쿼리 변수?inq_paged=N으로 base 를 변경(템플릿이 이미$_GET['inq_paged']` 를 수신). canonical redirect 가 발동하지 않으면서 본문 쿼리가 정상 동작.
0.4.9
- list: 목록 페이지(
[inquiry_form]view=list) 스타일을 단일 페이지 톤으로 통일. 테이블.inquiry-list에 둥근 모서리(border-radius: 10px+overflow: hidden), thead 진한 띠(#f1f5f9배경 +#0f172a진한 글자 + 하단 보더), 행 hover#f8fafc. - list: 제목 셀(
.col-title) 오른쪽 끝에 답변(댓글) 카운트 뱃지.inq-comment-count추가. 단일 페이지.inquiry-thread-count와 동일 톤(파란 pill,#1d4ed8배경 + 흰 글자,border-radius: 999px,font-size: 11px). 카운트 0 인 글은 표시 안 함. - list: 글쓰기 버튼(
.inquiry-write-btn) 을 단일 페이지 「← 목록으로」 / 「답글 등록」 박스 톤으로 통일. - pagination:
paginate_links( 'type' => 'list' )의<li>marker 가 테마 CSS 영향으로 노출되던 점(•) 제거 —.inquiry-pagination li에list-style: none !important+list-style-type: none !important+::marker { content: none }+::before { content: none }강제. 페이지 번호도 박스 톤(.page-numbers36×36 박스,current는#1d4ed8채움,dots는 투명). - empty: 빈 상태(
.inquiry-empty) 도 단일 페이지.inquiry-thread-empty와 동일 톤(흰 박스 + dashed#cbd5e1보더).
0.4.8
- single: 본문·댓글 안의 plain URL 을 자동으로
<a>태그로 감싸도록make_clickable적용. inquiry 본문은the_content필터 priority 15 에 보장 필터(inquiry_board_ensure_clickable)를 추가해 다른 플러그인이 코어의 make_clickable(priority 9) 을 제거해 둔 환경에서도 동작. 댓글은wpautop( make_clickable( wp_kses_post(...) ) )순서로 처리 — 줄바꿈이 살아있는 단계에서 URL 인식이 더 정확. - style: 「답글 등록」 버튼(
.inquiry-reply-submit) 을 「← 목록으로」 링크(.inquiry-back-link) 와 동일한 박스 톤·크기로 통일 (padding8px 14px, font-size13px,inline-flex,border-radius 10px, hover#eff6ff/#98bce8).
0.4.7
- style: inquiry 단일 페이지 상단 타이틀(
body.single-inquiry .post-title-wrapper) 도 본문 래퍼(.inquiry-single-wrap) 와 동일하게 75% 폭(모바일 100%) 으로 정렬. 상단부터 본문까지 일관된 컨테이너 폭 유지.
0.4.6
- single: 본문 상단에 "← 목록으로" 링크 추가. 쇼트코드
[inquiry_form]이 박힌 publish 페이지를 자동 탐지(inquiry_board_get_list_page_url())하여 그 URL 로 이동. 6시간 transient 캐시 +save_post_page/delete_post훅으로 무효화. 옵션inquiry_board_list_page_id로 수동 override 가능. - single: inquiry 본문 영역을
.inquiry-single-wrap으로 감싸 테마와 독립적으로 폭을 75% (모바일 100%) 로 정돈. - style: 답변 등록 버튼(
.inquiry-reply-submit) 을 테마 기본 버튼 스타일 의존에서 분리. 댓글 박스(.inquiry-msg) 와 동일한 흰 박스 + 1px#e2e8f0보더 + 10px radius. hover/focus 시 admin 박스 톤(#eff6ff/#98bce8). - style: 답변 박스 메타 헤더(
.inquiry-msg-head) 를 박스 상단 가득한 띠로 분리. 본문보다 진한 톤(#f1f5f9/ admin#dbeafe) + 하단 보더. 본문(.inquiry-msg-body) 좌우 패딩 16px 로 별도 지정. - style: admin 메시지 박스 보더 색
#bfdbfe→#98bce8(사용자 시안 적용). - style: "목록으로" 링크 자체도 박스 톤(
.inquiry-back-link) 으로 디자인.
0.4.5
- single: 단일 inquiry 페이지에 댓글 스레드(메시지 버블) UI 를 플러그인이 자체적으로 출력한다. 테마 single.php 가
comments_template()을 호출하지 않거나 옵션으로 막아 둔 경우(예: Uncode 테마의_uncode_{post_type}_comments옵션) 에도 inquiry 글에서 답변이 항상 보이도록 보장. - single: 본인 인증 세션 사용자(또는 관리자) 에게는 답글 폼이 함께 노출된다. POST 는
admin-post.php?action=inquiry_reply로 처리되고wp_new_comment()가 기존preprocess_comment·pre_comment_approved·comment_post필터 체인을 그대로 통과하므로 권한 게이트와 자동 승인이 일관되게 작동. - single: 마이그레이션된 댓글의 관리자 답변 판별은
_is_admin_reply메타 우선, 없으면user_id의moderate_comments폴백. - style: 메시지 버블·역할 배지·답글 폼 기본 스타일 추가 (관리자 답변
#eff6ff/ 작성자 답글#ffffff).
0.4.4
- settings: 일반설정 탭에 "레거시 URL 처리" 섹션 추가. 체크박스
legacy_redirect_enabled(기본값 off) 로 KBoard 등 레거시 URL(?mod=document&uid=NNN)을 마이그레이션된 새 inquiry 글로 301 리다이렉트할지 선택. - redirect:
inc/redirect.php의inquiry_board_legacy_redirect()시작부에 옵션 가드 추가. 비활성이면 즉시 return 하여 원본 게시판 글을 그대로 노출. SEO 보존 vs 원본/신규 병행 운영 양쪽 사용 사례를 지원.
0.4.3
- admin runner: KBoard 마이그레이션을 [Q&A 게시판 → 설정 → 마이그레이션] 화면에서 직접 실행. AJAX 폴링(1.5초)으로 단계별 진행률 바·통계·최근 로그·최근 에러 실시간 갱신.
- admin runner: 시작 전 안전장치 (Dry-run 사전 검증 패널, DB 백업 확인 체크박스, 동시 실행 락, 취소 후 재시작 안전성). 페이지를 닫아도 cursor 가 옵션에 보존되어 재진입 시 이어 진행 가능.
- core: 마이그레이션 로직을 WP-CLI 비의존 코어 클래스(Inquiry_Board_Migrator) 로 분리. CLI 명령과 관리화면 AJAX 가 동일 코어를 호출. 단계별 batch 메서드는 deadline(microtime) 까지 처리한 뒤 cursor·통계 반환.
- runner state:
inquiry_board_migration_runtime옵션(자동로드 off) 에 status·stage·cursor·통계·최근 30로그/30에러 저장. 엔드포인트는 capability=manage_options + nonce 로 보호.
0.4.2
- migration: KBoard 실제 스키마(
{prefix}kboard_board_setting,kboard_board_content,kboard_comments,kboard_board_attached)에 맞춰 감지·CLI 매핑을 전면 보정. v0.4.1 까지는 존재하지 않는kboard_board테이블을 가정해 마이그레이션 화면 감지가 실패하고 CLI 실행 시 댓글 SQL 에러가 발생했음. - migration: 글 일자(
date/update), 비밀(secret='true'), 공지(notice='true'), 상태(status='trash'제외), 작성자(member_uid/member_display) 매핑 정상화. - migration: 첨부는
{prefix}kboard_board_attached테이블에서 글(content_uid) 단위 JOIN 으로 처리하도록 분리. 댓글은content_uidJOIN 으로 게시판 필터링하며 작성자명은user_display사용. - migration: KBoard char(14)
'YYYYMMDDHHMMSS'↔ MySQL datetime 변환 유틸 추가.--since옵션이 KST 기준으로 정상 동작. - migration: 댓글 idempotent 처리(legacy uid 중복 INSERT 방지). 첨부도 글 메타에 누적 병합되도록 변경.
- migration-map:
정규유학/정규카테고리 →university매핑 추가.
0.4.1
- updater: "업데이트 캐시 강제 갱신" 버튼이 wp_update_plugins() 를 즉시 호출하도록 보강. 캐시 비움 직후 한 사이클 동안 빈 상태가 유지되는 문제 해결.
- settings: 자동 업데이트 섹션에 진단 표 추가 (현재 버전 · GitHub 최신 버전 · update_plugins.response 등록 여부 · 캐시 상태 · 토큰 상태 · zip URL).
0.4.0
- 대시보드 메뉴 개편: Settings → Q&A 게시판을 Q&A게시판 → 설정 으로 이동 (add_submenu_page).
- 설정 페이지 3탭 구조 도입: 일반설정 / 마이그레이션 / 사용방법.
- 일반설정에 페이지당 게시물 수(posts_per_page) 옵션 추가. 숏코드 속성 미지정 시 옵션값 사용.
- 마이그레이션 탭: KBoard 활성 (게시판 자동 감지 + 옵션 폼 + WP-CLI 명령 자동 생성), MangBoard / XE·Rhymix / Gravity Forms 는 준비중.
- 사용방법 탭: 단축코드·카테고리·세션·관리자 답변·CLI·바로가기 안내.
0.3.0
- GitHub Releases 기반 플러그인 자동 업데이트 추가 (ivystation/wp-qna-board).
- 설정 페이지에 GitHub Token 필드 및 업데이트 캐시 강제 갱신 버튼 추가.
0.2.0
- 비밀번호 보호 / 첨부 / 본인 세션 / 관리자 답변 통합 안정화 릴리스.
0.1.0
- 최초 릴리스.
Releases
10 releases. Each count is every asset in that release; expand a row for the breakdown.
Tag
Published
Assets
Downloads