조민수 조민수 05-07
게시판 관리 form + hook 정리 + 포토형, 일반형 게시판
@56db3d244b5ab37e4196e956260467ba213d571b
 
src/admin/component/button/ActionButtonFormGroup.tsx (added)
+++ src/admin/component/button/ActionButtonFormGroup.tsx
@@ -0,0 +1,75 @@
+type ActionMode =
+    | 'create'
+    | 'update';
+
+type ActionButtonGroupProps = {
+    mode: ActionMode;
+    disabled?: boolean;
+
+    onCreate?: () => void;
+    onUpdate?: () => void;
+    onDelete?: () => void;
+    onList?: () => void;
+};
+
+export const ActionButtonFormGroup = ({
+                                      mode,
+                                      disabled = false,
+                                      onCreate,
+                                      onUpdate,
+                                      onDelete,
+                                      onList
+                                  }: ActionButtonGroupProps) => {
+
+    return (
+        <div className="btn_wrap">
+            <div className="left">
+                {mode === 'update' && (
+                    <button
+                        type="button"
+                        className="btn line red xlarge"
+                        onClick={onDelete}
+                        disabled={disabled}
+                    >
+                        삭제
+                    </button>
+                )}
+            </div>
+
+            <div className="right">
+
+                {mode === 'create' && (
+                    <button
+                        type="button"
+                        className="btn fill primary xlarge"
+                        onClick={onCreate}
+                        disabled={disabled}
+                    >
+                        등록
+                    </button>
+                )}
+
+                {mode === 'update' && (
+                    <button
+                        type="button"
+                        className="btn fill primary xlarge"
+                        onClick={onUpdate}
+                        disabled={disabled}
+                    >
+                        수정
+                    </button>
+                )}
+
+                <button
+                    type="button"
+                    className="btn xlarge fill gray"
+                    onClick={onList}
+                    disabled={disabled}
+                >
+                    목록
+                </button>
+                
+            </div>
+        </div>
+    );
+};
 
src/admin/component/button/ActionButtonListGroup.tsx (added)
+++ src/admin/component/button/ActionButtonListGroup.tsx
@@ -0,0 +1,47 @@
+type ActionButtonListGroupProps = {
+    disabled?: boolean;
+    onCreate?: () => void;
+    onDelete?: () => void;
+    deleteLabel?: string
+};
+
+export const ActionButtonListGroup = ({
+                                          disabled = false,
+                                          onCreate,
+                                          onDelete,
+                                          deleteLabel = '선택 삭제',
+                                      }: ActionButtonListGroupProps) => {
+
+    return (
+        <div className="btn_wrap">
+            <div className="left">
+
+                {onDelete && (
+                    <button
+                        type="button"
+                        className="btn line red xlarge"
+                        onClick={onDelete}
+                        disabled={disabled}
+                    >
+                        {deleteLabel}
+                    </button>
+                )}
+            </div>
+
+            <div className="right">
+
+                {onCreate && (
+                    <button
+                        type="button"
+                        className="btn fill primary xlarge"
+                        onClick={onCreate}
+                        disabled={disabled}
+                    >
+                        등록
+                    </button>
+                )}
+
+            </div>
+        </div>
+    );
+};(No newline at end of file)
 
src/admin/component/checkbox/CheckBox.tsx (added)
+++ src/admin/component/checkbox/CheckBox.tsx
@@ -0,0 +1,54 @@
+import {type ChangeEvent, useEffect, useRef} from "react";
+
+type CheckBoxProps = {
+    id: string;
+    name: string;
+    checked: boolean;
+    onChange: (checked: boolean) => void;
+    value?: string;
+    label?: string;
+    disabled?: boolean;
+    indeterminate?: boolean;
+};
+
+export const CheckBox = ({
+                             id,
+                             name,
+                             checked,
+                             onChange,
+                             value,
+                             label,
+                             disabled = false,
+                             indeterminate = false,
+                         }: CheckBoxProps) => {
+    const inputRef = useRef<HTMLInputElement>(null);
+
+    useEffect(() => {
+        if (!inputRef.current) {
+            return;
+        }
+
+        inputRef.current.indeterminate = indeterminate;
+    }, [indeterminate]);
+
+    const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
+        onChange(event.target.checked);
+    };
+
+    return (
+        <>
+            <input
+                ref={inputRef}
+                type="checkbox"
+                className="checkbox"
+                id={id}
+                name={name}
+                value={value}
+                checked={checked}
+                disabled={disabled}
+                onChange={handleChange}
+            />
+            <label htmlFor={id}>{label}</label>
+        </>
+    );
+};
src/admin/feature/board/api/boardApi.ts
--- src/admin/feature/board/api/boardApi.ts
+++ src/admin/feature/board/api/boardApi.ts
@@ -4,6 +4,8 @@
     BoardArticleExtra,
     BoardArticleListItem,
     BoardArticleSearchParams,
+    BoardDetailResponse,
+    BoardFormItem,
     BoardListItem,
     BoardSearchParams
 } from "../type/board.types.ts";
@@ -15,3 +17,23 @@
 export async function fetchBoardArticleList(params: BoardArticleSearchParams) {
     return apiClient.get<PageResponse<BoardArticleListItem, BoardArticleExtra>>('/cop/bbs/boardList.do', params);
 }
+
+export async function fetchBoardDetail(bbsId: string) {
+    return apiClient.get<BoardDetailResponse>(`/cop/bbs/detail.do?bbsId=${bbsId}`);
+}
+
+export async function createBoard(params: BoardFormItem) {
+    return apiClient.post(`/cop/bbs/insertBoardMasater.do`, params);
+}
+
+export async function updateBoard(params: BoardFormItem) {
+    return apiClient.post(`/cop/bbs/updateBoardMaster.do`, params);
+}
+
+export async function deleteBoard(bbsId: string) {
+    return apiClient.post(`/cop/bbs/deleteBoardMaster.do?bbsId=${bbsId}`);
+}
+
+export async function deleteBoardBatch() {
+    return apiClient.post(`/cop/bbs/deleteBoardBatch.do`, {});
+}
src/admin/feature/board/components/article/BoardArticleListTable.tsx
--- src/admin/feature/board/components/article/BoardArticleListTable.tsx
+++ src/admin/feature/board/components/article/BoardArticleListTable.tsx
@@ -8,6 +8,11 @@
     items: BoardArticleListItem[];
     params: BoardArticleSearchParams;
     onChange: (params: BoardArticleSearchParams) => void;
+    isAllChecked: boolean;
+    isPartiallyChecked: boolean;
+    isChecked: (id: string) => boolean;
+    onCheck: (id: string, checked: boolean) => void;
+    onCheckAll: (checked: boolean) => void;
     totalItems: number
     currentPage: number
     totalPages: number
@@ -17,6 +22,11 @@
                                           items,
                                           params,
                                           onChange,
+                                          isAllChecked,
+                                          isPartiallyChecked,
+                                          isChecked,
+                                          onCheck,
+                                          onCheckAll,
                                           totalItems,
                                           currentPage,
                                           totalPages
@@ -28,6 +38,9 @@
                 <BoardArticleListTableHeader
                     params={params}
                     onChange={onChange}
+                    checked={isAllChecked}
+                    indeterminate={isPartiallyChecked}
+                    onCheckAll={onCheckAll}
                 />
                 <tbody>
                 {items.length > 0 ?
@@ -40,6 +53,8 @@
                                 totalItems={totalItems}
                                 currentPage={currentPage}
                                 totalPages={totalPages}
+                                checked={isChecked(item.nttId)}
+                                onCheck={onCheck}
                             />
                         )) :
                     (<EmptyRow colSpan={8}/>)
@@ -49,4 +64,4 @@
         </div>
     )
 
-}
(No newline at end of file)
+}
src/admin/feature/board/components/article/BoardArticleListTableHeader.tsx
--- src/admin/feature/board/components/article/BoardArticleListTableHeader.tsx
+++ src/admin/feature/board/components/article/BoardArticleListTableHeader.tsx
@@ -1,13 +1,20 @@
 import type {BoardArticleSearchParams} from "../../type/board.types.ts";
+import {CheckBox} from "../../../../component/checkbox/CheckBox.tsx";
 
 type BoardArticleListTableHeaderProps = {
     params: BoardArticleSearchParams;
     onChange: (params: BoardArticleSearchParams) => void;
+    checked: boolean;
+    indeterminate: boolean;
+    onCheckAll: (checked: boolean) => void;
 }
 
 export const BoardArticleListTableHeader = ({
                                                 params,
-                                                onChange
+                                                onChange,
+                                                checked,
+                                                indeterminate,
+                                                onCheckAll,
                                             }: BoardArticleListTableHeaderProps) => {
     const handleSort = (field: string) => {
         const nextOrder =
@@ -52,8 +59,13 @@
             <thead>
             <tr>
                 <th>
-                    <input type={"checkbox"} name={"checkbox"}/>
-                    <label htmlFor={"checkbox"}></label>
+                    <CheckBox
+                        id="checkAll"
+                        name="checkAll"
+                        checked={checked}
+                        indeterminate={indeterminate}
+                        onChange={onCheckAll}
+                    />
                 </th>
                 <th>번호</th>
                 <th scope={"col"}>
@@ -79,4 +91,4 @@
             </thead>
         </>
     )
-}
(No newline at end of file)
+}
src/admin/feature/board/components/article/BoardArticleListTableRow.tsx
--- src/admin/feature/board/components/article/BoardArticleListTableRow.tsx
+++ src/admin/feature/board/components/article/BoardArticleListTableRow.tsx
@@ -1,5 +1,6 @@
 import type {BoardArticleListItem} from "../../type/board.types.ts";
 import type {SearchParams} from "../../../../../type/searchParams.ts";
+import {CheckBox} from "../../../../component/checkbox/CheckBox.tsx";
 
 type BoardArticleListTableRowProps = {
     item: BoardArticleListItem
@@ -8,6 +9,8 @@
     totalItems: number
     currentPage: number
     totalPages: number
+    checked: boolean
+    onCheck: (id: string, checked: boolean) => void
 }
 
 export const BoardArticleListTableRow = ({
@@ -17,6 +20,8 @@
                                              totalItems,
                                              currentPage,
                                              totalPages,
+                                             checked,
+                                             onCheck,
                                          }: BoardArticleListTableRowProps) => {
 
     const rowNumber = searchParams.searchSortOrd === 'DESC'
@@ -24,7 +29,15 @@
         : (currentPage - 1) * totalPages + (index + 1)
     return (
         <tr>
-            <td></td>
+            <td>
+                <CheckBox
+                    id={`checkList_${item.nttId}`}
+                    name="checkList"
+                    value={item.nttId}
+                    checked={checked}
+                    onChange={(nextChecked) => onCheck(item.nttId, nextChecked)}
+                />
+            </td>
             <td>{rowNumber}</td>
             <td>{item.nttSj}</td>
             <td>{item.atchFileId}</td>
@@ -34,4 +47,4 @@
             <td>{item.inqireCo}</td>
         </tr>
     )
-}
(No newline at end of file)
+}
 
src/admin/feature/board/components/master/BoardFormTable.tsx (added)
+++ src/admin/feature/board/components/master/BoardFormTable.tsx
@@ -0,0 +1,193 @@
+import type {ChangeEvent} from "react";
+import type {BoardFormItem} from "../../type/board.types.ts";
+import type {CommonCodeItem} from "../../../../../type/code.ts";
+
+type BoardFormTableProps = {
+    form: BoardFormItem;
+    typeList?: CommonCodeItem[];
+    onChange: (event: ChangeEvent<HTMLInputElement | HTMLSelectElement>) => void;
+};
+
+export const BoardFormTable = ({
+                                   form,
+                                   typeList = [],
+                                   onChange
+                               }: BoardFormTableProps) => {
+    return (
+        <div className="table table_type_rows">
+            <table>
+                <colgroup>
+                    <col style={{ width: '200px' }} />
+                    <col style={{ width: 'auto' }} />
+                </colgroup>
+
+                <tbody>
+                <tr>
+                    <th>
+                        <span className="required">*</span>
+                        게시판명
+                    </th>
+                    <td>
+                        <input
+                            type="text"
+                            className="input"
+                            id="bbsNm"
+                            name="bbsNm"
+                            value={form.bbsNm}
+                            onChange={onChange}
+                        />
+                    </td>
+                </tr>
+
+                <tr>
+                    <th>
+                        <span className="required">*</span>
+                        게시판유형
+                    </th>
+                    <td>
+                        {typeList.map((type) => (
+                            <label key={type.code}>
+                                <input
+                                    type="radio"
+                                    id={`bbsTyCode_${type.code}`}
+                                    name="bbsTyCode"
+                                    value={type.code}
+                                    checked={form.bbsTyCode === type.code}
+                                    onChange={onChange}
+                                />
+                                {type.codeNm}
+                            </label>
+                        ))}
+                    </td>
+                </tr>
+
+                <tr>
+                    <th>
+                        <span className="required">*</span>
+                        공지기능
+                    </th>
+                    <td>
+                        <select
+                            id="noticeYn"
+                            name="noticeYn"
+                            value={form.noticeYn}
+                            onChange={onChange}
+                        >
+                            <option value="Y">사용</option>
+                            <option value="N">미사용</option>
+                        </select>
+                    </td>
+                </tr>
+
+                <tr>
+                    <th>
+                        <span className="required">*</span>
+                        댓글기능
+                    </th>
+                    <td>
+                        <select
+                            id="addYn"
+                            name="addYn"
+                            value={form.addYn}
+                            onChange={onChange}
+                        >
+                            <option value="Y">사용</option>
+                            <option value="N">미사용</option>
+                        </select>
+                    </td>
+                </tr>
+
+                <tr>
+                    <th>
+                        <span className="required">*</span>
+                        파일첨부기능
+                    </th>
+                    <td>
+                        <select
+                            id="fileAtchPosblAt"
+                            name="fileAtchPosblAt"
+                            value={form.fileAtchPosblAt}
+                            onChange={onChange}
+                        >
+                            <option value="Y">사용</option>
+                            <option value="N">미사용</option>
+                        </select>
+                    </td>
+                </tr>
+
+                <tr>
+                    <th>
+                        <span className="required">*</span>
+                        파일첨부갯수
+                    </th>
+                    <td>
+                        <select
+                            id="posblAtchFileNumber"
+                            name="posblAtchFileNumber"
+                            value={form.posblAtchFileNumber}
+                            onChange={onChange}
+                        >
+                            <option value="0">없음</option>
+                            <option value="1">1</option>
+                            <option value="9">9</option>
+                        </select>
+                    </td>
+                </tr>
+
+                <tr>
+                    <th>
+                        <span className="required">*</span>
+                        파일첨부사이즈
+                    </th>
+                    <td>
+                        <input
+                            type="number"
+                            className="input"
+                            id="posblAtchFileSize"
+                            name="posblAtchFileSize"
+                            value={form.posblAtchFileSize}
+                            onChange={onChange}
+                        />
+                    </td>
+                </tr>
+
+                <tr>
+                    <th>
+                        <span className="required">*</span>
+                        조회수 노출여부
+                    </th>
+                    <td>
+                        <select
+                            id="viewsYn"
+                            name="viewsYn"
+                            value={form.viewsYn}
+                            onChange={onChange}
+                        >
+                            <option value="Y">사용</option>
+                            <option value="N">미사용</option>
+                        </select>
+                    </td>
+                </tr>
+
+                <tr>
+                    <th>
+                        <span className="required">*</span>
+                        게시판 사용여부
+                    </th>
+                    <td>
+                        <select
+                            id="useAt"
+                            name="useAt"
+                            value={form.useAt}
+                            onChange={onChange}
+                        >
+                            <option value="Y">사용</option>
+                            <option value="N">미사용</option>
+                        </select>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+    );
+};
src/admin/feature/board/components/master/BoardListTable.tsx
--- src/admin/feature/board/components/master/BoardListTable.tsx
+++ src/admin/feature/board/components/master/BoardListTable.tsx
@@ -11,6 +11,11 @@
     totalItems: number
     currentPage: number
     totalPages: number
+    isAllChecked: boolean
+    isPartiallyChecked: boolean
+    isChecked: (id: string) => boolean
+    onCheck: (id: string, checked: boolean) => void
+    onCheckAll: (checked: boolean) => void
     onDetail: (bbsId: string) => void
     onArticleList: (bbsId: string) => void
     onPreview: (bbsId: string) => void
@@ -23,6 +28,11 @@
                                    totalItems,
                                    currentPage,
                                    totalPages,
+                                   isAllChecked,
+                                   isPartiallyChecked,
+                                   isChecked,
+                                   onCheck,
+                                   onCheckAll,
                                    onDetail,
                                    onArticleList,
                                    onPreview
@@ -31,7 +41,13 @@
     return (
         <div className="table table_type_cols">
             <table>
-                <BoardListTableHeader params={params} onChange={onChange}/>
+                <BoardListTableHeader
+                    params={params}
+                    onChange={onChange}
+                    checked={isAllChecked}
+                    indeterminate={isPartiallyChecked}
+                    onCheckAll={onCheckAll}
+                />
                 <tbody>
                 {items.length > 0 ?
                     items.map((item, index) => (
@@ -43,6 +59,8 @@
                             totalItems={totalItems}
                             currentPage={currentPage}
                             totalPages={totalPages}
+                            checked={isChecked(item.bbsId)}
+                            onCheck={onCheck}
                             onDetail={onDetail}
                             onArticleList={onArticleList}
                             onPreview={onPreview}
src/admin/feature/board/components/master/BoardListTableHeader.tsx
--- src/admin/feature/board/components/master/BoardListTableHeader.tsx
+++ src/admin/feature/board/components/master/BoardListTableHeader.tsx
@@ -1,11 +1,21 @@
 import type {SearchParams} from "../../../../../type/searchParams.ts";
+import {CheckBox} from "../../../../component/checkbox/CheckBox.tsx";
 
 interface BoardListTableHeaderProps {
     params: SearchParams;
     onChange: (params: SearchParams) => void
+    checked: boolean
+    indeterminate: boolean
+    onCheckAll: (checked: boolean) => void
 }
 
-export function BoardListTableHeader({params, onChange}: BoardListTableHeaderProps) {
+export function BoardListTableHeader({
+                                         params,
+                                         onChange,
+                                         checked,
+                                         indeterminate,
+                                         onCheckAll
+                                     }: BoardListTableHeaderProps) {
     const handleSort = (field: string) => {
 
         const nextOrder =
@@ -36,6 +46,7 @@
     return (
         <>
             <colgroup>
+                <col style={{width: '40px'}}/>
                 <col style={{width: '6%'}}/>
                 <col style={{width: '18%'}}/>
                 <col style={{width: '18%'}}/>
@@ -48,6 +59,15 @@
 
             <thead>
             <tr>
+                <th>
+                    <CheckBox
+                        id="boardCheckAll"
+                        name="checkAll"
+                        checked={checked}
+                        indeterminate={indeterminate}
+                        onChange={onCheckAll}
+                    />
+                </th>
                 <th>번호</th>
                 <th>
                     게시판명
src/admin/feature/board/components/master/BoardListTableRow.tsx
--- src/admin/feature/board/components/master/BoardListTableRow.tsx
+++ src/admin/feature/board/components/master/BoardListTableRow.tsx
@@ -1,5 +1,6 @@
 import type {BoardListItem} from "../../type/board.types.ts";
 import type {SearchParams} from "../../../../../type/searchParams.ts";
+import {CheckBox} from "../../../../component/checkbox/CheckBox.tsx";
 
 interface BoardListTableRowProps {
     item: BoardListItem
@@ -8,6 +9,8 @@
     totalItems: number
     currentPage: number
     totalPages: number
+    checked: boolean
+    onCheck: (id: string, checked: boolean) => void
     onDetail: (bbsId: string) => void
     onArticleList: (bbsId: string) => void
     onPreview: (bbsId: string) => void
@@ -20,6 +23,8 @@
                                       totalItems,
                                       currentPage,
                                       totalPages,
+                                      checked,
+                                      onCheck,
                                       onDetail,
                                       onArticleList,
                                       onPreview
@@ -31,6 +36,15 @@
 
     return (
         <tr>
+            <td>
+                <CheckBox
+                    id={`boardCheckList_${bbsId}`}
+                    name="checkList"
+                    value={bbsId}
+                    checked={checked}
+                    onChange={(nextChecked) => onCheck(bbsId, nextChecked)}
+                />
+            </td>
             <td>{rowNumber}</td>
             <td>{item.bbsNm}</td>
             <td>{item.menuNm}</td>
 
src/admin/feature/board/hook/mutation/useCreateBoard.ts (added)
+++ src/admin/feature/board/hook/mutation/useCreateBoard.ts
@@ -0,0 +1,15 @@
+import {useMutation, useQueryClient} from "@tanstack/react-query";
+import {createBoard} from "../../api/boardApi.ts";
+
+export const useCreateBoard = () => {
+    const queryClient = useQueryClient();
+
+    return useMutation({
+        mutationFn: createBoard,
+        onSuccess: () => {
+            queryClient.invalidateQueries({
+                queryKey: ['boardList']
+            });
+        },
+    });
+}
 
src/admin/feature/board/hook/mutation/useDeleteBoard.ts (added)
+++ src/admin/feature/board/hook/mutation/useDeleteBoard.ts
@@ -0,0 +1,15 @@
+import {useMutation, useQueryClient} from "@tanstack/react-query";
+import {deleteBoard} from "../../api/boardApi.ts";
+
+export const useDeleteBoard = () => {
+    const queryClient = useQueryClient();
+
+    return useMutation({
+        mutationFn: deleteBoard,
+        onSuccess: () => {
+            queryClient.invalidateQueries({
+                queryKey: ['boardList']
+            });
+        },
+    });
+};
 
src/admin/feature/board/hook/mutation/useUpdateBoard.ts (added)
+++ src/admin/feature/board/hook/mutation/useUpdateBoard.ts
@@ -0,0 +1,19 @@
+import {useMutation, useQueryClient} from "@tanstack/react-query";
+import {updateBoard} from "../../api/boardApi.ts";
+
+export const useUpdateBoard = () => {
+    const queryClient = useQueryClient();
+
+    return useMutation({
+        mutationFn: updateBoard,
+        onSuccess: (_, variables) => {
+            queryClient.invalidateQueries({
+                queryKey: ['boardList']
+            });
+
+            queryClient.invalidateQueries({
+                queryKey: ['boardDetail', variables.bbsId]
+            });
+        },
+    });
+};
 
src/admin/feature/board/hook/page/useBoardArticleListPage.ts (added)
+++ src/admin/feature/board/hook/page/useBoardArticleListPage.ts
@@ -0,0 +1,105 @@
+import {useMemo, useState} from "react";
+import {ADMIN_BBS_MASTER_ROUTE} from "../../../../route/adminRouteMap.ts";
+import {useCheckedList} from "../../../../hook/useCheckedList.ts";
+import type {BoardArticleSearchParams} from "../../type/board.types.ts";
+import {useBoardArticleList} from "../query/useBoardArticleList.ts";
+
+const initSearchParam: BoardArticleSearchParams = {
+    pageIndex: 1,
+    pageUnit: 10,
+    searchCnd: "0",
+    searchKeyword: "",
+    searchSortCnd: "FRST_REGIST_PNTTM",
+    searchSortOrd: "ASC",
+    bbsId: ""
+};
+
+const searchOptions = [
+    {value: '0', label: '제목'},
+    {value: '1', label: '내용'},
+    {value: '2', label: '작성자'},
+];
+
+export const useBoardArticleListPage = (bbsId: string) => {
+    const [searchDraft, setSearchDraft] = useState<BoardArticleSearchParams>(initSearchParam);
+    const searchParams = useMemo(
+        () => ({
+            ...searchDraft,
+            bbsId,
+        }),
+        [bbsId, searchDraft]
+    );
+
+    const {
+        list,
+        extraData,
+        totalItems,
+        currentPage,
+        totalPages,
+        size,
+        isLoading,
+        error
+    } = useBoardArticleList(searchParams);
+    const articleIds = useMemo(
+        () => list.map((item) => item.nttId),
+        [list]
+    );
+    const {
+        checkedIds,
+        isAllChecked,
+        isPartiallyChecked,
+        isChecked,
+        handleCheck,
+        handleCheckAll,
+        resetChecked,
+    } = useCheckedList(articleIds);
+    const bbsNm = extraData?.boardMaster?.bbsNm ?? '';
+    const bbsTyCode = extraData?.boardMaster?.bbsTyCode ?? '';
+    const title = `${bbsNm || '게시글'} 목록`;
+    const breadcrumb = [
+        {label: '게시판 관리', url: ADMIN_BBS_MASTER_ROUTE},
+        {label: title}
+    ];
+    const successMessage = bbsNm
+        ? `${bbsNm} 목록을 불러왔습니다.`
+        : '게시글 목록을 불러왔습니다.';
+
+    const handleSearchChange = (params: BoardArticleSearchParams) => {
+        setSearchDraft({
+            ...params,
+            bbsId: "",
+        });
+    };
+
+    const handlePageChange = (pageIndex: number) => {
+        setSearchDraft((prev) => ({
+            ...prev,
+            pageIndex,
+        }));
+    };
+
+    return {
+        title,
+        breadcrumb,
+        searchOptions,
+        searchParams,
+        list,
+        bbsTyCode,
+        totalItems,
+        currentPage,
+        totalPages,
+        size,
+        isLoading,
+        error,
+        successMessage,
+        checkedIds,
+        isAllChecked,
+        isPartiallyChecked,
+        isChecked,
+        handleCheck,
+        handleCheckAll,
+        resetChecked,
+        handleSearchChange,
+        handlePageChange,
+    };
+};
 
src/admin/feature/board/hook/page/useBoardForm.ts (added)
+++ src/admin/feature/board/hook/page/useBoardForm.ts
@@ -0,0 +1,154 @@
+import {type ChangeEvent, useMemo, useState} from "react";
+import {useNavigate} from "react-router-dom";
+import {toast} from "react-toastify";
+import {ADMIN_BBS_MASTER_ROUTE} from "../../../../route/adminRouteMap.ts";
+import type {CommonCodeItem} from "../../../../../type/code.ts";
+import type {BoardFormItem} from "../../type/board.types.ts";
+import {useBoardDetail} from "../query/useBoardDetail.ts";
+import {useCreateBoard} from "../mutation/useCreateBoard.ts";
+import {useDeleteBoard} from "../mutation/useDeleteBoard.ts";
+import {useUpdateBoard} from "../mutation/useUpdateBoard.ts";
+
+export type BoardFormMode = 'create' | 'update';
+
+const initBoardFormData: BoardFormItem = {
+    bbsId: '',
+    bbsNm: '',
+    bbsTyCode: '',
+    noticeYn: 'Y',
+    addYn: 'Y',
+    fileAtchPosblAt: 'Y',
+    posblAtchFileNumber: '0',
+    posblAtchFileSize: '0',
+    viewsYn: 'Y',
+    useAt: 'Y',
+};
+
+const createInitialForm = (
+    item?: BoardFormItem,
+    typeList: CommonCodeItem[] = []
+) => ({
+    ...initBoardFormData,
+    bbsTyCode: typeList[0]?.code ?? '',
+    ...item,
+});
+
+export const useBoardForm = (bbsId: string) => {
+    const navigate = useNavigate();
+    const mode: BoardFormMode = bbsId ? 'update' : 'create';
+    const [formDraft, setFormDraft] = useState<Partial<BoardFormItem>>({});
+
+    const {data, isLoading, error} = useBoardDetail(bbsId, {enabled: !!bbsId});
+    const {mutateAsync: createBoard, isPending: isCreating} = useCreateBoard();
+    const {mutateAsync: updateBoard, isPending: isUpdating} = useUpdateBoard();
+    const {mutateAsync: deleteBoard, isPending: isDeleting} = useDeleteBoard();
+    const isPending = isCreating || isUpdating || isDeleting;
+
+    const title = `게시판 ${mode === 'create' ? '생성' : '수정'}`;
+    const breadcrumb = [
+        {label: '게시판 관리', url: ADMIN_BBS_MASTER_ROUTE},
+        {label: title}
+    ];
+    const baseForm = useMemo(
+        () => createInitialForm(data?.result, data?.typeList),
+        [data?.result, data?.typeList]
+    );
+    const form = {
+        ...baseForm,
+        ...formDraft,
+    };
+
+    const handleChange = (event: ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
+        const {name, value} = event.target;
+
+        setFormDraft((prev) => ({
+            ...prev,
+            [name]: value,
+        }));
+    };
+
+    const validateForm = () => {
+        if (!form.bbsNm.trim()) {
+            toast.warning('게시판명을 입력해주세요.');
+            return false;
+        }
+
+        if (!form.bbsTyCode) {
+            toast.warning('게시판유형을 선택해주세요.');
+            return false;
+        }
+
+        return true;
+    };
+
+    const handleCreate = async () => {
+        if (!validateForm()) {
+            return;
+        }
+
+        await toast.promise(
+            createBoard(form),
+            {
+                pending: '등록 중...',
+                success: '등록 완료',
+                error: '등록 실패'
+            }
+        );
+
+        navigate(ADMIN_BBS_MASTER_ROUTE);
+    };
+
+    const handleUpdate = async () => {
+        if (!validateForm()) {
+            return;
+        }
+
+        await toast.promise(
+            updateBoard(form),
+            {
+                pending: '수정 중...',
+                success: '수정 완료',
+                error: '수정 실패'
+            }
+        );
+
+        navigate(ADMIN_BBS_MASTER_ROUTE);
+    };
+
+    const handleDelete = async () => {
+        if (!bbsId || !window.confirm('게시판을 삭제하시겠습니까?')) {
+            return;
+        }
+
+        await toast.promise(
+            deleteBoard(bbsId),
+            {
+                pending: '삭제 중...',
+                success: '삭제 완료',
+                error: '삭제 실패'
+            }
+        );
+
+        navigate(ADMIN_BBS_MASTER_ROUTE);
+    };
+
+    const handleList = () => {
+        navigate(ADMIN_BBS_MASTER_ROUTE);
+    };
+
+    return {
+        mode,
+        title,
+        breadcrumb,
+        form,
+        typeList: data?.typeList,
+        isLoading,
+        error,
+        isPending,
+        handleChange,
+        handleCreate,
+        handleUpdate,
+        handleDelete,
+        handleList,
+    };
+};
 
src/admin/feature/board/hook/page/useBoardListPage.ts (added)
+++ src/admin/feature/board/hook/page/useBoardListPage.ts
@@ -0,0 +1,117 @@
+import {useMemo, useState} from "react";
+import type {BoardSearchParams} from "../../type/board.types.ts";
+import {useBoardList} from "../query/useBoardList.ts";
+import {ADMIN_BBS_ARTICLE_DETAIL_ROUTE, ADMIN_BBS_ARTICLE_LIST_ROUTE} from "../../../../route/adminRouteMap.ts";
+import {useNavigate} from "react-router-dom";
+import {useCheckedList} from "../../../../hook/useCheckedList.ts";
+import {toast} from "react-toastify";
+
+const initSearchParam: BoardSearchParams = {
+    pageIndex: 1,
+    pageUnit: 10,
+    searchCnd: "0",
+    searchKeyword: "",
+    searchSortCnd: "BBS_NM",
+    searchSortOrd: "ASC"
+}
+
+const searchOptions = [
+    {value: '0', label: '게시판명/연결메뉴'},
+    {value: '1', label: '게시판유형'},
+]
+
+const pageSizeOptions = [
+    {value: '10', label: '10건씩'},
+    {value: '20', label: '20건씩'},
+    {value: '30', label: '30건씩'},
+]
+
+export const useBoardListPage = () => {
+
+    const [searchParams, setSearchParams] = useState(initSearchParam);
+    const {
+        list,
+        totalItems,
+        totalPages,
+        currentPage,
+        size,
+        isLoading,
+        error
+    } = useBoardList(searchParams);
+    const boardIds = useMemo(
+        () => list.map((item) => item.bbsId),
+        [list]
+    );
+    const {
+        checkedIds,
+        isAllChecked,
+        isPartiallyChecked,
+        isChecked,
+        handleCheck,
+        handleCheckAll,
+        resetChecked,
+    } = useCheckedList(boardIds);
+    const title = '게시판 관리';
+    const breadcrumb = [{label: '게시판 관리'}];
+    const homeUrl = '#';
+    const successMessage = "게시판을 조회하였습니다.";
+    const navigate = useNavigate();
+
+    const handleDetail = (bbsId: string) => {
+        navigate(ADMIN_BBS_ARTICLE_DETAIL_ROUTE + bbsId);
+    }
+    const handleArticleList = (bbsId: string) => {
+        navigate(ADMIN_BBS_ARTICLE_LIST_ROUTE + bbsId);
+    }
+    const handlePreview = (bbsId: string) => {
+        navigate(`/preview/${bbsId}`);
+    }
+    const handlePageChange = (pageIndex: number) => {
+        setSearchParams((prev) => ({
+            ...prev,
+            pageIndex,
+        }));
+    }
+    const handleDeleteBatch = () => {
+        if (checkedIds.length === 0) {
+            toast.warning('미사용 처리할 게시판을 선택해주세요.');
+            return;
+        } else {
+            toast.info("삭제로직은 아직 미처리");
+        }
+    }
+    const handleCreate = () => {
+        navigate(ADMIN_BBS_ARTICLE_DETAIL_ROUTE);
+    }
+
+    return {
+        list,
+        totalItems,
+        totalPages,
+        currentPage,
+        size,
+        isLoading,
+        error,
+        title,
+        breadcrumb,
+        homeUrl,
+        searchOptions,
+        pageSizeOptions,
+        successMessage,
+        searchParams,
+        setSearchParams,
+        handleDetail,
+        handleArticleList,
+        handlePreview,
+        handlePageChange,
+        handleDeleteBatch,
+        handleCreate,
+        checkedIds,
+        isAllChecked,
+        isPartiallyChecked,
+        isChecked,
+        handleCheck,
+        handleCheckAll,
+        resetChecked,
+    }
+}
src/admin/feature/board/hook/query/useBoardArticleList.ts (Renamed from src/admin/feature/board/hook/useBoardArticleList.ts)
--- src/admin/feature/board/hook/useBoardArticleList.ts
+++ src/admin/feature/board/hook/query/useBoardArticleList.ts
@@ -1,14 +1,13 @@
 import {keepPreviousData, useQuery} from "@tanstack/react-query";
-import {fetchBoardArticleList} from "../api/boardApi.ts";
-import type {BoardArticleSearchParams} from "../type/board.types.ts";
+import {fetchBoardArticleList} from "../../api/boardApi.ts";
+import type {BoardArticleSearchParams} from "../../type/board.types.ts";
 
 export function useBoardArticleList(searchParams: BoardArticleSearchParams) {
     const query = useQuery({
-        queryKey: ['boardArticleList'],
+        queryKey: ['boardArticleList', searchParams],
         queryFn: () => fetchBoardArticleList(searchParams),
         placeholderData: keepPreviousData,
     });
-    console.log("useBoardArticleList", query);
 
     return {
         list : query.data?.list ?? [],
@@ -20,4 +19,4 @@
         isLoading: query.isLoading,
         error: query.error,
     }
-}
(No newline at end of file)
+}
 
src/admin/feature/board/hook/query/useBoardDetail.ts (added)
+++ src/admin/feature/board/hook/query/useBoardDetail.ts
@@ -0,0 +1,19 @@
+import {fetchBoardDetail} from "../../api/boardApi.ts";
+import {keepPreviousData, useQuery} from "@tanstack/react-query";
+
+type UseBoardDetailOptions = {
+    enabled: boolean;
+}
+
+export const useBoardDetail = (
+    bbsId: string,
+    options?: UseBoardDetailOptions
+) => {
+
+    return useQuery({
+        queryKey: ['boardDetail', bbsId],
+        queryFn: () => fetchBoardDetail(bbsId),
+        placeholderData: keepPreviousData,
+        enabled: options?.enabled ?? true
+    });
+}
src/admin/feature/board/hook/query/useBoardList.ts (Renamed from src/admin/feature/board/hook/useBoardList.ts)
--- src/admin/feature/board/hook/useBoardList.ts
+++ src/admin/feature/board/hook/query/useBoardList.ts
@@ -1,8 +1,8 @@
 import {keepPreviousData, useQuery} from "@tanstack/react-query";
-import {fetchBoardList} from "../api/boardApi.ts";
-import type {SearchParams} from "../../../../type/searchParams.ts";
+import {fetchBoardList} from "../../api/boardApi.ts";
+import type {SearchParams} from "../../../../../type/searchParams.ts";
 
-export function useBoardListQuery(searchParams: SearchParams) {
+export function useBoardList(searchParams: SearchParams) {
 
     const query = useQuery({
         queryKey: ['boardList', searchParams],
@@ -13,8 +13,9 @@
     return {
         list: query.data?.list ?? [],
         totalItems: query.data?.totalItems ?? 0,
-        currentPage: query.data?.currentPage ?? 0,
         totalPages: query.data?.totalPages ?? 0,
+        currentPage: query.data?.currentPage ?? 0,
+        size: query.data?.size ?? 0,
         isLoading: query.isLoading,
         error: query.error,
     }
src/admin/feature/board/page/BoardArticleListPage.tsx
--- src/admin/feature/board/page/BoardArticleListPage.tsx
+++ src/admin/feature/board/page/BoardArticleListPage.tsx
@@ -1,57 +1,43 @@
 import {useParams} from "react-router-dom";
-import {useBoardArticleList} from "../hook/useBoardArticleList.ts";
-import type {BoardArticleSearchParams} from "../type/board.types.ts";
-import {useState} from "react";
 import {PageHeader} from "../../../component/PageHeader.tsx";
 import {ListSearchForm} from "../../../component/ListSearchForm.tsx";
 import {Pagination} from "../../../component/pagination/Pagination.tsx";
 import {useLoadingToast} from "../../../hook/useLoadingToast.ts";
 import {BoartArticleListTable} from "../components/article/BoardArticleListTable.tsx";
 import {BoardArticleImageListTable} from "../components/article/BoardArticleImageListTable.tsx";
-
-const initSearchParam: BoardArticleSearchParams = {
-    pageIndex: 1,
-    pageUnit: 10,
-    searchCnd: "0",
-    searchKeyword: "",
-    searchSortCnd: "FRST_REGIST_PNTTM",
-    searchSortOrd: "ASC",
-    bbsId: ""
-};
+import {useBoardArticleListPage} from "../hook/page/useBoardArticleListPage.ts";
 
 export const BoardArticleListPage = () => {
     const {bbsId = ''} = useParams();
-    const searchOptions = [
-        {value: '0', label: '제목'},
-        {value: '1', label: '내용'},
-        {value: '2', label: '작성자'},
-    ]
-
-    const [searchParams, setSearchParams] = useState<BoardArticleSearchParams>({
-        ...initSearchParam,
-        bbsId,
-    });
     const {
+        title,
+        breadcrumb,
+        searchOptions,
+        searchParams,
         list,
-        extraData,
+        bbsTyCode,
         totalItems,
         currentPage,
         totalPages,
         size,
         isLoading,
-        error
-    } = useBoardArticleList(searchParams);
+        error,
+        successMessage,
+        isAllChecked,
+        isPartiallyChecked,
+        isChecked,
+        handleCheck,
+        handleCheckAll,
+        handleSearchChange,
+        handlePageChange,
+    } = useBoardArticleListPage(bbsId);
 
-    const bbsNm = extraData ? extraData.boardMaster?.bbsNm : null;
-    const bbsTyCode = extraData ? extraData.boardMaster?.bbsTyCode : null;
     useLoadingToast({
         isLoading,
         error,
-        successMessage: `${bbsNm} 목록을 불러왔습니다.`
+        successMessage
     });
 
-    const title = `${bbsNm} 목록`
-    const breadcrumb = [{label: '게시판 관리', url: '/admin/cop/bbs/SelectBBSMasterInfs.do'}, {label: `${bbsNm} 목록`}]
     const homeUrl = '#'
 
     return (
@@ -60,7 +46,7 @@
             <ListSearchForm
                 totalItems={totalItems}
                 searchParams={searchParams}
-                onChange={setSearchParams}
+                onChange={handleSearchChange}
                 searchOptions={searchOptions}
                 totalLabel={"게시글"}
             />
@@ -71,7 +57,12 @@
                 <BoartArticleListTable
                     items={list}
                     params={searchParams}
-                    onChange={setSearchParams}
+                    onChange={handleSearchChange}
+                    isAllChecked={isAllChecked}
+                    isPartiallyChecked={isPartiallyChecked}
+                    isChecked={isChecked}
+                    onCheck={handleCheck}
+                    onCheckAll={handleCheckAll}
                     totalPages={totalPages}
                     currentPage={currentPage}
                     totalItems={totalItems}
@@ -82,9 +73,8 @@
                 totalPages={totalPages}
                 currentPage={currentPage}
                 size={size}
-                onPageChange={() => {
-                }}
+                onPageChange={handlePageChange}
             />
         </>
     );
-}
(No newline at end of file)
+}
 
src/admin/feature/board/page/BoardFormPage.tsx (added)
+++ src/admin/feature/board/page/BoardFormPage.tsx
@@ -0,0 +1,50 @@
+import {useParams} from "react-router-dom";
+import {PageHeader} from "../../../component/PageHeader.tsx";
+import {useLoadingToast} from "../../../hook/useLoadingToast.ts";
+import {ActionButtonFormGroup} from "../../../component/button/ActionButtonFormGroup.tsx";
+import {BoardFormTable} from "../components/master/BoardFormTable.tsx";
+import {useBoardForm} from "../hook/page/useBoardForm.ts";
+
+export const BoardFormPage = () => {
+    const {bbsId = ''} = useParams();
+    const {
+        mode,
+        title,
+        breadcrumb,
+        form,
+        typeList,
+        isLoading,
+        error,
+        isPending,
+        handleChange,
+        handleCreate,
+        handleUpdate,
+        handleDelete,
+        handleList,
+    } = useBoardForm(bbsId);
+
+    useLoadingToast({
+        isLoading,
+        error,
+        successMessage: '데이터 조회가 완료되었습니다.'
+    });
+
+    return (
+        <>
+            <PageHeader title={title} breadcrumb={breadcrumb} homeUrl="#"/>
+            <BoardFormTable
+                form={form}
+                typeList={typeList}
+                onChange={handleChange}
+            />
+            <ActionButtonFormGroup
+                mode={mode}
+                disabled={isPending}
+                onDelete={handleDelete}
+                onCreate={handleCreate}
+                onUpdate={handleUpdate}
+                onList={handleList}
+            />
+        </>
+    );
+};
src/admin/feature/board/page/BoardListPage.tsx
--- src/admin/feature/board/page/BoardListPage.tsx
+++ src/admin/feature/board/page/BoardListPage.tsx
@@ -1,62 +1,46 @@
-import {useBoardListQuery} from "../hook/useBoardList.ts";
 import {PageHeader} from "../../../component/PageHeader.tsx";
-import {useState} from "react";
 import {ListSearchForm} from "../../../component/ListSearchForm.tsx";
 import {BoardListTable} from "../components/master/BoardListTable.tsx";
-import {useNavigate} from "react-router-dom";
-import type {BoardSearchParams} from "../type/board.types.ts";
 import {useLoadingToast} from "../../../hook/useLoadingToast.ts";
-
-const initSearchParam: BoardSearchParams = {
-    pageIndex: 1,
-    pageUnit: 10,
-    searchCnd: "0",
-    searchKeyword: "",
-    searchSortCnd: "BBS_NM",
-    searchSortOrd: "ASC"
-}
+import {Pagination} from "../../../component/pagination/Pagination.tsx";
+import {ActionButtonListGroup} from "../../../component/button/ActionButtonListGroup.tsx";
+import {useBoardListPage} from "../hook/page/useBoardListPage.ts";
 
 export const BoardListPage = () => {
-    const searchOptions = [
-        {value: '0', label: '게시판명/연결메뉴'},
-        {value: '1', label: '게시판유형'},
-    ]
-
-    const pageSizeOptions = [
-        {value: '10', label: '10건씩'},
-        {value: '20', label: '20건씩'},
-        {value: '30', label: '30건씩'},
-    ]
-    const [searchParams, setSearchParams] = useState<BoardSearchParams>(initSearchParam);
     const {
         list,
         totalItems,
-        currentPage,
         totalPages,
+        currentPage,
+        size,
         isLoading,
-        error
-    } = useBoardListQuery(searchParams);
-    const navigate = useNavigate();
-
-    const handleDetail = (bbsId: string) => {
-        navigate(`/admin/cop/bbs/detail/${bbsId}`);
-    }
-    const handleArticleList = (bbsId: string) => {
-        navigate(`/detail/cop/bbs/article/${bbsId}`);
-    }
-    const handlePreview = (bbsId: string) => {
-        navigate(`/preview/${bbsId}`);
-    }
+        error,
+        title,
+        breadcrumb,
+        homeUrl,
+        searchOptions,
+        pageSizeOptions,
+        successMessage,
+        searchParams,
+        setSearchParams,
+        handleDetail,
+        handleArticleList,
+        handlePreview,
+        handlePageChange,
+        handleDeleteBatch,
+        handleCreate,
+        isAllChecked,
+        isPartiallyChecked,
+        isChecked,
+        handleCheck,
+        handleCheckAll,
+    } = useBoardListPage();
 
     useLoadingToast({
         isLoading,
         error,
-        successMessage : '게시판 마스터 목록을 조회하였습니다.'
+        successMessage
     });
-
-    const title = '게시판 관리'
-    const breadcrumb = [{label: '게시판 관리'}]
-    const homeUrl = '#'
 
     return (
         <>
@@ -82,10 +66,27 @@
                 totalItems={totalItems}
                 currentPage={currentPage}
                 totalPages={totalPages}
+                isAllChecked={isAllChecked}
+                isPartiallyChecked={isPartiallyChecked}
+                isChecked={isChecked}
+                onCheck={handleCheck}
+                onCheckAll={handleCheckAll}
                 onDetail={handleDetail}
                 onArticleList={handleArticleList}
                 onPreview={handlePreview}
             />
+            <ActionButtonListGroup
+                onDelete={handleDeleteBatch}
+                onCreate={handleCreate}
+                deleteLabel={"미사용"}
+            />
+            <Pagination
+                totalItems={totalItems}
+                totalPages={totalPages}
+                currentPage={currentPage}
+                size={size}
+                onPageChange={handlePageChange}
+            />
         </>
     )
 };
src/admin/feature/board/type/board.types.ts
--- src/admin/feature/board/type/board.types.ts
+++ src/admin/feature/board/type/board.types.ts
@@ -1,4 +1,5 @@
 import type {SearchParams} from "../../../../type/searchParams.ts";
+import type {CommonCodeItem} from "../../../../type/code.ts";
 
 export interface BoardSearchParams extends SearchParams {
 
@@ -37,4 +38,22 @@
         bbsNm: string;
         bbsTyCode: string;
     }
+}
+
+export interface BoardFormItem {
+    bbsId: string;
+    bbsNm: string;
+    bbsTyCode: string;
+    noticeYn: string;
+    addYn: string;
+    fileAtchPosblAt: string;
+    posblAtchFileNumber: string;
+    posblAtchFileSize: string;
+    viewsYn: string;
+    useAt: string;
+}
+
+export interface BoardDetailResponse {
+    result: BoardFormItem;
+    typeList: CommonCodeItem[];
 }
(No newline at end of file)
 
src/admin/hook/useCheckedList.ts (added)
+++ src/admin/hook/useCheckedList.ts
@@ -0,0 +1,44 @@
+import {useMemo, useState} from "react";
+
+type CheckedListId = string | number;
+
+export const useCheckedList = <T extends CheckedListId>(ids: T[]) => {
+    const [checkedIds, setCheckedIds] = useState<T[]>([]);
+
+    const currentCheckedIds = useMemo(
+        () => checkedIds.filter((checkedId) => ids.includes(checkedId)),
+        [checkedIds, ids]
+    );
+    const isAllChecked = ids.length > 0 && ids.every((id) => checkedIds.includes(id));
+    const isPartiallyChecked = currentCheckedIds.length > 0 && !isAllChecked;
+
+    const isChecked = (id: T) => checkedIds.includes(id);
+
+    const handleCheck = (id: T, checked: boolean) => {
+        setCheckedIds((prev) => {
+            if (checked) {
+                return prev.includes(id) ? prev : [...prev, id];
+            }
+
+            return prev.filter((checkedId) => checkedId !== id);
+        });
+    };
+
+    const handleCheckAll = (checked: boolean) => {
+        setCheckedIds(checked ? ids : []);
+    };
+
+    const resetChecked = () => {
+        setCheckedIds([]);
+    };
+
+    return {
+        checkedIds: currentCheckedIds,
+        isAllChecked,
+        isPartiallyChecked,
+        isChecked,
+        handleCheck,
+        handleCheckAll,
+        resetChecked,
+    };
+};
src/admin/route/AdminRoute.tsx
--- src/admin/route/AdminRoute.tsx
+++ src/admin/route/AdminRoute.tsx
@@ -2,6 +2,7 @@
 import {BoardListPage} from "../feature/board/page/BoardListPage.tsx";
 import {ADMIN_BBS_MASTER_ROUTE} from "./adminRouteMap.ts";
 import {BoardArticleListPage} from "../feature/board/page/BoardArticleListPage.tsx";
+import {BoardFormPage} from "../feature/board/page/BoardFormPage.tsx";
 
 const ReadyPage = () => {
     return <div>Preparing menu.</div>;
@@ -10,10 +11,12 @@
 export const AdminRoute = () => {
     return (
         <Routes>
-            <Route path="/" element={<Navigate to={ADMIN_BBS_MASTER_ROUTE} replace />} />
-            <Route path={ADMIN_BBS_MASTER_ROUTE} element={<BoardListPage />} />
-            <Route path={`/detail/cop/bbs/article/:bbsId`} element={<BoardArticleListPage />}/>
-            <Route path="*" element={<ReadyPage />} />
+            <Route path="/" element={<Navigate to={ADMIN_BBS_MASTER_ROUTE} replace/>}/>
+            <Route path={ADMIN_BBS_MASTER_ROUTE} element={<BoardListPage/>}/>
+            <Route path={`/admin/cop/bbs/article/:bbsId`} element={<BoardArticleListPage/>}/>
+            <Route path={`/admin/cop/bbs/detail/:bbsId`} element={<BoardFormPage/>}/>
+            <Route path={`/admin/cop/bbs/detail`} element={<BoardFormPage/>}/>
+            <Route path="*" element={<ReadyPage/>}/>
         </Routes>
     );
 };
src/admin/route/adminRouteMap.ts
--- src/admin/route/adminRouteMap.ts
+++ src/admin/route/adminRouteMap.ts
@@ -1,11 +1,13 @@
 export const ADMIN_ROUTE_PREFIX = '/admin';
 
+export const ADMIN_BBS_MASTER_ROUTE = `${ADMIN_ROUTE_PREFIX}/cop/bbs/SelectBBSMasterInfs.do`;
+export const ADMIN_BBS_ARTICLE_LIST_ROUTE = `${ADMIN_ROUTE_PREFIX}/cop/bbs/article/`;
+export const ADMIN_BBS_ARTICLE_DETAIL_ROUTE = `${ADMIN_ROUTE_PREFIX}/cop/bbs/detail/`;
 export const ADMIN_MENU_CREATE_TREE_ROUTE = `${ADMIN_ROUTE_PREFIX}/sym/mnu/mcm/EgovMenuCreatSelectJtree.do`;
 export const ADMIN_AUTHOR_LIST_ROUTE = `${ADMIN_ROUTE_PREFIX}/sec/ram/EgovAuthorList.do`;
 export const ADMIN_MAIN_ZONE_LIST_ROUTE = `${ADMIN_ROUTE_PREFIX}/uss/ion/pwm/mainZoneList.do`;
 export const ADMIN_CONTENT_LIST_ROUTE = `${ADMIN_ROUTE_PREFIX}/uss/ion/cnt/contentList.do`;
 export const ADMIN_MAIN_PAGE_ROUTE = `${ADMIN_ROUTE_PREFIX}/cmm/main/mainPage.do`;
-export const ADMIN_BBS_MASTER_ROUTE = `${ADMIN_ROUTE_PREFIX}/cop/bbs/SelectBBSMasterInfs.do`;
 export const ADMIN_LOGIN_GROUP_POLICY_ROUTE = `${ADMIN_ROUTE_PREFIX}/uat/uap/selectLoginGroupPolicyList.do`;
 export const ADMIN_MEMBER_MANAGE_ROUTE = `${ADMIN_ROUTE_PREFIX}/uss/umt/EgovMberManage.do`;
 export const ADMIN_POPUP_ZONE_LIST_ROUTE = `${ADMIN_ROUTE_PREFIX}/uss/ion/pwm/popupZoneList.do`;
 
src/type/code.ts (added)
+++ src/type/code.ts
@@ -0,0 +1,15 @@
+export interface CommonCodeItem {
+    clCode: string;
+    code: string;
+    codeDc: string;
+    codeId: string;
+    codeIdNM: string;
+    codeNm: string;
+    frstRegisterId:string
+    lastUpdusrId:string
+    searchSortCnd:string
+    searchSortOrd:string
+    sortNo:string
+    tempCodeId:string
+    useAt:string
+}(No newline at end of file)
Add a comment
List