# 게시판 관리 시스템 ## 개요 SAM 프로젝트의 게시판 관리 시스템은 **MNG(상위 관리자)**와 **API(테넌트)**에서 각각 다른 역할로 운영됩니다. | 구분 | 역할 | 게시판 유형 | |------|------|-------------| | **MNG** | 시스템 게시판 생성/관리 | `is_system=true`, `tenant_id=null` | | **API** | 테넌트 게시판 생성 + 시스템 게시판 조회 | `is_system=false`, `tenant_id={tenant}` | ## 아키텍처 ``` ┌─────────────────────────────────────────────────────────────┐ │ MNG (상위 관리자) │ │ - 시스템 게시판 CRUD │ │ - 커스텀 필드 관리 │ │ - 모든 테넌트에서 접근 가능한 공용 게시판 │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ boards 테이블 │ │ - is_system: boolean (시스템/테넌트 구분) │ │ - tenant_id: nullable (시스템은 null) │ │ - board_type: varchar(50) - 자유 입력 │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ API (테넌트) │ │ - 시스템 게시판 조회 (읽기 전용) │ │ - 테넌트 게시판 CRUD │ │ - 게시글/댓글 CRUD │ └─────────────────────────────────────────────────────────────┘ ``` ## 데이터베이스 스키마 ### boards 테이블 | 컬럼 | 타입 | 설명 | |------|------|------| | id | bigint | PK | | tenant_id | bigint | FK (nullable - 시스템 게시판은 null) | | is_system | boolean | 시스템 게시판 여부 (default: false) | | board_type | varchar(50) | 게시판 유형 (notice, qna, faq 등 자유 입력) | | board_code | varchar(50) | 게시판 코드 (unique per tenant) | | name | varchar(100) | 게시판명 | | description | text | 설명 | | editor_type | enum | wysiwyg, markdown, text | | allow_files | boolean | 파일 첨부 허용 | | max_file_count | int | 최대 파일 수 | | max_file_size | int | 최대 파일 크기 (KB) | | extra_settings | json | 추가 설정 | | is_active | boolean | 활성 상태 | | deleted_at | timestamp | Soft Delete | ### board_settings 테이블 (커스텀 필드) | 컬럼 | 타입 | 설명 | |------|------|------| | id | bigint | PK | | board_id | bigint | FK → boards | | name | varchar(100) | 필드명 (한글 라벨) | | field_key | varchar(50) | 필드 키 (영문, 스네이크케이스) | | field_type | varchar(20) | text, textarea, number, date, select 등 | | is_required | boolean | 필수 여부 | | sort_order | int | 정렬 순서 | | options | json | 선택형 필드의 옵션 값 | ## MNG 구현 ### 파일 구조 ``` mng/ ├── app/ │ ├── Http/Controllers/ │ │ ├── BoardController.php # Blade 컨트롤러 │ │ └── Api/Admin/BoardController.php # API 컨트롤러 │ ├── Models/Boards/ │ │ ├── Board.php │ │ └── BoardSetting.php │ └── Services/ │ └── BoardService.php ├── resources/views/boards/ │ ├── index.blade.php │ ├── create.blade.php │ ├── edit.blade.php │ └── partials/table.blade.php └── routes/ ├── web.php # Blade 라우트 └── api.php # API 라우트 ``` ### 라우트 #### Web 라우트 (Blade) | Method | URI | Name | 설명 | |--------|-----|------|------| | GET | /boards | boards.index | 목록 | | GET | /boards/create | boards.create | 생성 폼 | | GET | /boards/{id}/edit | boards.edit | 수정 폼 | #### API 라우트 (HTMX/Ajax) | Method | URI | 설명 | |--------|-----|------| | GET | /api/admin/boards | 목록 (페이지네이션) | | POST | /api/admin/boards | 생성 | | GET | /api/admin/boards/{id} | 상세 | | PUT | /api/admin/boards/{id} | 수정 | | DELETE | /api/admin/boards/{id} | 삭제 | | GET | /api/admin/boards/{id}/fields | 커스텀 필드 목록 | | POST | /api/admin/boards/{id}/fields | 커스텀 필드 추가 | | PUT | /api/admin/boards/{id}/fields/{fieldId} | 커스텀 필드 수정 | | DELETE | /api/admin/boards/{id}/fields/{fieldId} | 커스텀 필드 삭제 | ### 커스텀 필드 모달 다중 필드 추가 기능: - 한 줄에 필드명, 필드키, 타입, 필수 체크박스 배치 - `+ 필드 추가` 버튼으로 행 추가 - X 버튼으로 행 삭제 - 여러 필드 일괄 저장 ``` ┌─────────────────────────────────────────────────────────────┐ │ 필드 추가 │ ├─────────────────────────────────────────────────────────────┤ │ 필드명* 필드키* 타입* 필수 삭제 │ │ [카테고리] [category] [선택 ▼] [✓] [X] │ │ [작성자] [author] [텍스트 ▼] [ ] [X] │ ├─────────────────────────────────────────────────────────────┤ │ ┌─────────────────────────┐ │ │ │ + 필드 추가 │ │ │ └─────────────────────────┘ │ │ * 필드 키: 영문 소문자와 언더스코어만 사용 │ ├─────────────────────────────────────────────────────────────┤ │ [취소] [저장] │ └─────────────────────────────────────────────────────────────┘ ``` ## API 구현 (테넌트용) ### 파일 구조 ``` api/ ├── app/ │ ├── Http/Controllers/Api/V1/ │ │ ├── BoardController.php │ │ └── PostController.php │ ├── Http/Requests/Boards/ │ │ ├── BoardStoreRequest.php │ │ ├── BoardUpdateRequest.php │ │ ├── PostStoreRequest.php │ │ ├── PostUpdateRequest.php │ │ └── CommentStoreRequest.php │ └── Services/Boards/ │ └── PostService.php ├── app/Swagger/v1/ │ ├── BoardApi.php │ └── PostApi.php └── routes/api.php ``` ### API 엔드포인트 #### 게시판 API | Method | URI | 설명 | |--------|-----|------| | GET | /api/v1/boards | 접근 가능한 게시판 목록 (시스템 + 테넌트) | | GET | /api/v1/boards/tenant | 테넌트 게시판만 | | POST | /api/v1/boards | 테넌트 게시판 생성 | | GET | /api/v1/boards/{code} | 게시판 상세 (코드 기반) | | PUT | /api/v1/boards/{id} | 테넌트 게시판 수정 | | DELETE | /api/v1/boards/{id} | 테넌트 게시판 삭제 | | GET | /api/v1/boards/{code}/fields | 커스텀 필드 목록 | #### 게시글 API | Method | URI | 설명 | |--------|-----|------| | GET | /api/v1/boards/{code}/posts | 게시글 목록 | | POST | /api/v1/boards/{code}/posts | 게시글 작성 | | GET | /api/v1/boards/{code}/posts/{id} | 게시글 상세 | | PUT | /api/v1/boards/{code}/posts/{id} | 게시글 수정 | | DELETE | /api/v1/boards/{code}/posts/{id} | 게시글 삭제 | #### 댓글 API | Method | URI | 설명 | |--------|-----|------| | GET | /api/v1/boards/{code}/posts/{postId}/comments | 댓글 목록 | | POST | /api/v1/boards/{code}/posts/{postId}/comments | 댓글 작성 | | PUT | /api/v1/boards/{code}/posts/{postId}/comments/{commentId} | 댓글 수정 | | DELETE | /api/v1/boards/{code}/posts/{postId}/comments/{commentId} | 댓글 삭제 | ## 접근 권한 로직 ```php // 게시판 목록 조회 (테넌트 API) public function index() { $tenantId = $this->tenantId(); // 시스템 게시판 + 해당 테넌트 게시판 $boards = Board::where(function ($q) use ($tenantId) { $q->where('is_system', true) ->orWhere('tenant_id', $tenantId); }) ->where('is_active', true) ->get(); } // 게시판 수정/삭제 (테넌트는 자신의 게시판만) public function update($id) { $board = Board::where('id', $id) ->where('tenant_id', $this->tenantId()) ->where('is_system', false) // 시스템 게시판 수정 불가 ->firstOrFail(); } ``` ## 커스텀 필드 타입 | 타입 | 설명 | 옵션 | |------|------|------| | text | 한 줄 텍스트 | - | | textarea | 여러 줄 텍스트 | - | | number | 숫자 | min, max | | date | 날짜 | - | | select | 드롭다운 선택 | options[] | | checkbox | 체크박스 | - | | radio | 라디오 버튼 | options[] | | file | 파일 첨부 | allowed_extensions | ## 관련 문서 - [SAM API Rules](/SAM/API_RULES.md) - [MNG Critical Rules](/SAM/mng/docs/MNG_CRITICAL_RULES.md) - [Board System Spec](/SAM/docs/specs/board-system-spec.md)