524 lines
16 KiB
Markdown
524 lines
16 KiB
Markdown
|
|
# 게시판 시스템 스펙
|
||
|
|
|
||
|
|
**작성일**: 2025-11-27
|
||
|
|
**상태**: 설계 완료, 구현 대기
|
||
|
|
**관련 프로젝트**: mng, api
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 1. 개요
|
||
|
|
|
||
|
|
### 1.1 목적
|
||
|
|
- mng에서 **시스템 게시판**을 생성하여 모든 테넌트에게 제공
|
||
|
|
- sam(api)에서 테넌트별 **자체 게시판** 생성 가능
|
||
|
|
- 공지사항, 1:1 문의, FAQ 등 다양한 게시판 유형 지원
|
||
|
|
|
||
|
|
### 1.2 핵심 개념
|
||
|
|
|
||
|
|
| 구분 | 설명 |
|
||
|
|
|------|------|
|
||
|
|
| **시스템 게시판** | mng에서 생성, `is_system=true`, 모든 테넌트에서 접근 가능 |
|
||
|
|
| **테넌트 게시판** | sam에서 생성, `is_system=false`, 해당 테넌트만 접근 |
|
||
|
|
| **board_type** | 자유 입력 (notice, qna, faq, free 등 제한 없음) |
|
||
|
|
|
||
|
|
### 1.3 역할 분리
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────────────────────────┐
|
||
|
|
│ mng (상위 관리자) │
|
||
|
|
├─────────────────────────────────────────────────────────────┤
|
||
|
|
│ • 시스템 게시판 CRUD (is_system = true) │
|
||
|
|
│ • 게시판 필드 정의 (board_settings) │
|
||
|
|
│ • 게시판 유형 자유 설정 (board_type) │
|
||
|
|
│ • tenant_id = NULL │
|
||
|
|
└─────────────────────────────────────────────────────────────┘
|
||
|
|
↓ 전체 테넌트 공개
|
||
|
|
┌─────────────────────────────────────────────────────────────┐
|
||
|
|
│ sam (api - 테넌트용) │
|
||
|
|
├─────────────────────────────────────────────────────────────┤
|
||
|
|
│ • 테넌트 게시판 CRUD (is_system = false) │
|
||
|
|
│ • 시스템 게시판 사용 (읽기 전용 구조) │
|
||
|
|
│ • 게시글 CRUD (posts) │
|
||
|
|
│ • tenant_id = 현재 테넌트 │
|
||
|
|
└─────────────────────────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. 데이터베이스 스키마
|
||
|
|
|
||
|
|
### 2.1 기존 테이블 현황
|
||
|
|
|
||
|
|
현재 구현된 테이블 (6개):
|
||
|
|
- `boards` - 게시판 정의
|
||
|
|
- `board_settings` - EAV 커스텀 필드 정의
|
||
|
|
- `posts` - 게시글
|
||
|
|
- `post_custom_field_values` - EAV 커스텀 필드 값
|
||
|
|
- `board_comments` - 댓글
|
||
|
|
- `board_files` - 파일 첨부
|
||
|
|
|
||
|
|
### 2.2 boards 테이블 확장
|
||
|
|
|
||
|
|
**추가 컬럼:**
|
||
|
|
|
||
|
|
| 컬럼 | 타입 | 설명 |
|
||
|
|
|------|------|------|
|
||
|
|
| `is_system` | TINYINT(1) DEFAULT 0 | 시스템 게시판 여부 (1=전체 공개) |
|
||
|
|
| `board_type` | VARCHAR(50) NULL | 게시판 유형 (자유 입력) |
|
||
|
|
|
||
|
|
**변경 컬럼:**
|
||
|
|
|
||
|
|
| 컬럼 | 변경 내용 |
|
||
|
|
|------|----------|
|
||
|
|
| `tenant_id` | NOT NULL → **NULL 허용** (시스템 게시판용) |
|
||
|
|
|
||
|
|
**최종 boards 테이블 구조:**
|
||
|
|
|
||
|
|
```sql
|
||
|
|
CREATE TABLE boards (
|
||
|
|
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
|
|
tenant_id BIGINT UNSIGNED NULL COMMENT '테넌트 ID (NULL=시스템 게시판)',
|
||
|
|
is_system TINYINT(1) DEFAULT 0 COMMENT '시스템 게시판 여부 (1=전체 테넌트 공개)',
|
||
|
|
board_type VARCHAR(50) NULL COMMENT '게시판 유형 (notice, qna, faq, free 등)',
|
||
|
|
board_code VARCHAR(50) NOT NULL COMMENT '게시판 코드 (URL용)',
|
||
|
|
name VARCHAR(100) NOT NULL COMMENT '게시판명',
|
||
|
|
description TEXT NULL COMMENT '게시판 설명',
|
||
|
|
editor_type VARCHAR(20) DEFAULT 'wysiwyg' COMMENT '에디터 타입',
|
||
|
|
allow_files TINYINT(1) DEFAULT 1 COMMENT '파일 첨부 허용',
|
||
|
|
max_file_count INT DEFAULT 5 COMMENT '최대 파일 수',
|
||
|
|
max_file_size INT DEFAULT 20480 COMMENT '최대 파일 크기 (KB)',
|
||
|
|
extra_settings JSON NULL COMMENT '추가 설정 (권한, 옵션 등)',
|
||
|
|
is_active TINYINT(1) DEFAULT 1 COMMENT '활성 여부',
|
||
|
|
created_at TIMESTAMP NULL,
|
||
|
|
updated_at TIMESTAMP NULL,
|
||
|
|
created_by BIGINT UNSIGNED NULL,
|
||
|
|
updated_by BIGINT UNSIGNED NULL,
|
||
|
|
deleted_at TIMESTAMP NULL,
|
||
|
|
deleted_by BIGINT UNSIGNED NULL,
|
||
|
|
|
||
|
|
INDEX idx_boards_tenant (tenant_id),
|
||
|
|
INDEX idx_boards_is_system (is_system),
|
||
|
|
INDEX idx_boards_board_type (board_type),
|
||
|
|
UNIQUE INDEX uk_boards_code (tenant_id, board_code)
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2.3 board_settings 테이블 (EAV 필드 정의)
|
||
|
|
|
||
|
|
현재 구조 유지:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
CREATE TABLE board_settings (
|
||
|
|
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
|
|
board_id BIGINT UNSIGNED NOT NULL COMMENT '게시판 ID',
|
||
|
|
name VARCHAR(100) NOT NULL COMMENT '필드명',
|
||
|
|
field_key VARCHAR(50) NOT NULL COMMENT '필드 키',
|
||
|
|
field_type VARCHAR(30) NOT NULL COMMENT '필드 타입 (text, number, select, date 등)',
|
||
|
|
field_meta JSON NULL COMMENT '필드 메타 (옵션, 유효성 등)',
|
||
|
|
is_required TINYINT(1) DEFAULT 0 COMMENT '필수 여부',
|
||
|
|
sort_order INT DEFAULT 0 COMMENT '정렬 순서',
|
||
|
|
created_at TIMESTAMP NULL,
|
||
|
|
updated_at TIMESTAMP NULL,
|
||
|
|
created_by BIGINT UNSIGNED NULL,
|
||
|
|
updated_by BIGINT UNSIGNED NULL,
|
||
|
|
|
||
|
|
INDEX idx_board_settings_board (board_id),
|
||
|
|
FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2.4 posts 테이블
|
||
|
|
|
||
|
|
현재 구조 유지 (SoftDeletes 적용):
|
||
|
|
|
||
|
|
```sql
|
||
|
|
CREATE TABLE posts (
|
||
|
|
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
|
|
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID',
|
||
|
|
board_id BIGINT UNSIGNED NOT NULL COMMENT '게시판 ID',
|
||
|
|
user_id BIGINT UNSIGNED NOT NULL COMMENT '작성자 ID',
|
||
|
|
title VARCHAR(255) NOT NULL COMMENT '제목',
|
||
|
|
content LONGTEXT NULL COMMENT '내용',
|
||
|
|
editor_type VARCHAR(20) DEFAULT 'wysiwyg' COMMENT '에디터 타입',
|
||
|
|
ip_address VARCHAR(45) NULL COMMENT 'IP 주소',
|
||
|
|
is_notice TINYINT(1) DEFAULT 0 COMMENT '공지 여부',
|
||
|
|
is_secret TINYINT(1) DEFAULT 0 COMMENT '비밀글 여부',
|
||
|
|
views INT DEFAULT 0 COMMENT '조회수',
|
||
|
|
status VARCHAR(20) DEFAULT 'active' COMMENT '상태',
|
||
|
|
created_at TIMESTAMP NULL,
|
||
|
|
updated_at TIMESTAMP NULL,
|
||
|
|
created_by BIGINT UNSIGNED NULL,
|
||
|
|
updated_by BIGINT UNSIGNED NULL,
|
||
|
|
deleted_at TIMESTAMP NULL,
|
||
|
|
deleted_by BIGINT UNSIGNED NULL,
|
||
|
|
|
||
|
|
INDEX idx_posts_tenant_board (tenant_id, board_id),
|
||
|
|
INDEX idx_posts_status (status),
|
||
|
|
FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2.5 post_custom_field_values 테이블 (EAV 값)
|
||
|
|
|
||
|
|
현재 구조 유지:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
CREATE TABLE post_custom_field_values (
|
||
|
|
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
|
|
post_id BIGINT UNSIGNED NOT NULL COMMENT '게시글 ID',
|
||
|
|
field_id BIGINT UNSIGNED NOT NULL COMMENT '필드 ID (board_settings.id)',
|
||
|
|
value TEXT NULL COMMENT '필드 값',
|
||
|
|
created_at TIMESTAMP NULL,
|
||
|
|
updated_at TIMESTAMP NULL,
|
||
|
|
created_by BIGINT UNSIGNED NULL,
|
||
|
|
updated_by BIGINT UNSIGNED NULL,
|
||
|
|
|
||
|
|
INDEX idx_pcfv_post (post_id),
|
||
|
|
INDEX idx_pcfv_field (field_id),
|
||
|
|
FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
|
||
|
|
FOREIGN KEY (field_id) REFERENCES board_settings(id) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. 게시판 유형 (board_type)
|
||
|
|
|
||
|
|
### 3.1 권장 유형
|
||
|
|
|
||
|
|
| board_type | 설명 | 특징 |
|
||
|
|
|------------|------|------|
|
||
|
|
| `notice` | 공지사항 | 관리자만 작성, 전체 공개 |
|
||
|
|
| `qna` | 1:1 문의 | 작성자+관리자만 열람, 비밀글 기본 |
|
||
|
|
| `faq` | FAQ | 관리자 작성, 카테고리 분류 |
|
||
|
|
| `free` | 자유게시판 | 댓글 허용, 전체 공개 |
|
||
|
|
| `gallery` | 갤러리 | 이미지 중심 |
|
||
|
|
| `download` | 자료실 | 파일 첨부 중심 |
|
||
|
|
|
||
|
|
### 3.2 유형별 extra_settings 예시
|
||
|
|
|
||
|
|
```json
|
||
|
|
// notice (공지사항)
|
||
|
|
{
|
||
|
|
"write_roles": ["admin", "manager"],
|
||
|
|
"allow_comment": false,
|
||
|
|
"allow_secret": false
|
||
|
|
}
|
||
|
|
|
||
|
|
// qna (1:1 문의)
|
||
|
|
{
|
||
|
|
"write_roles": ["*"],
|
||
|
|
"allow_comment": true,
|
||
|
|
"default_secret": true,
|
||
|
|
"only_author_view": true
|
||
|
|
}
|
||
|
|
|
||
|
|
// faq
|
||
|
|
{
|
||
|
|
"write_roles": ["admin"],
|
||
|
|
"use_category": true,
|
||
|
|
"allow_comment": false
|
||
|
|
}
|
||
|
|
|
||
|
|
// free (자유게시판)
|
||
|
|
{
|
||
|
|
"write_roles": ["*"],
|
||
|
|
"allow_comment": true,
|
||
|
|
"allow_secret": true
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. API 설계
|
||
|
|
|
||
|
|
### 4.1 mng API (시스템 게시판 관리)
|
||
|
|
|
||
|
|
```
|
||
|
|
# 시스템 게시판 CRUD
|
||
|
|
GET /mng/boards # 시스템 게시판 목록
|
||
|
|
POST /mng/boards # 시스템 게시판 생성
|
||
|
|
GET /mng/boards/{id} # 시스템 게시판 상세
|
||
|
|
PUT /mng/boards/{id} # 시스템 게시판 수정
|
||
|
|
DELETE /mng/boards/{id} # 시스템 게시판 삭제
|
||
|
|
|
||
|
|
# 게시판 필드 관리
|
||
|
|
GET /mng/boards/{id}/fields # 필드 목록
|
||
|
|
POST /mng/boards/{id}/fields # 필드 추가
|
||
|
|
PUT /mng/boards/{id}/fields/{fid} # 필드 수정
|
||
|
|
DELETE /mng/boards/{id}/fields/{fid} # 필드 삭제
|
||
|
|
POST /mng/boards/{id}/fields/reorder # 필드 순서 변경
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4.2 sam API (테넌트용)
|
||
|
|
|
||
|
|
```
|
||
|
|
# 게시판 조회 (시스템 + 테넌트)
|
||
|
|
GET /v1/boards # 접근 가능한 게시판 목록
|
||
|
|
GET /v1/boards/{code} # 게시판 상세
|
||
|
|
|
||
|
|
# 테넌트 게시판 관리
|
||
|
|
POST /v1/boards # 테넌트 게시판 생성
|
||
|
|
PUT /v1/boards/{code} # 테넌트 게시판 수정
|
||
|
|
DELETE /v1/boards/{code} # 테넌트 게시판 삭제
|
||
|
|
|
||
|
|
# 게시글 CRUD
|
||
|
|
GET /v1/boards/{code}/posts # 게시글 목록
|
||
|
|
POST /v1/boards/{code}/posts # 게시글 작성
|
||
|
|
GET /v1/boards/{code}/posts/{id} # 게시글 상세
|
||
|
|
PUT /v1/boards/{code}/posts/{id} # 게시글 수정
|
||
|
|
DELETE /v1/boards/{code}/posts/{id} # 게시글 삭제
|
||
|
|
|
||
|
|
# 댓글
|
||
|
|
GET /v1/posts/{id}/comments # 댓글 목록
|
||
|
|
POST /v1/posts/{id}/comments # 댓글 작성
|
||
|
|
PUT /v1/comments/{id} # 댓글 수정
|
||
|
|
DELETE /v1/comments/{id} # 댓글 삭제
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. 모델 설계
|
||
|
|
|
||
|
|
### 5.1 Board 모델
|
||
|
|
|
||
|
|
```php
|
||
|
|
// api/app/Models/Boards/Board.php
|
||
|
|
|
||
|
|
namespace App\Models\Boards;
|
||
|
|
|
||
|
|
use App\Traits\BelongsToTenant;
|
||
|
|
use Illuminate\Database\Eloquent\Model;
|
||
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||
|
|
|
||
|
|
class Board extends Model
|
||
|
|
{
|
||
|
|
use SoftDeletes;
|
||
|
|
|
||
|
|
protected $fillable = [
|
||
|
|
'tenant_id', 'is_system', 'board_type', 'board_code', 'name',
|
||
|
|
'description', 'editor_type', 'allow_files', 'max_file_count',
|
||
|
|
'max_file_size', 'extra_settings', 'is_active',
|
||
|
|
'created_by', 'updated_by', 'deleted_by',
|
||
|
|
];
|
||
|
|
|
||
|
|
protected $casts = [
|
||
|
|
'is_system' => 'boolean',
|
||
|
|
'is_active' => 'boolean',
|
||
|
|
'allow_files' => 'boolean',
|
||
|
|
'extra_settings' => 'array',
|
||
|
|
];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 현재 테넌트에서 접근 가능한 게시판
|
||
|
|
* - 시스템 게시판 (is_system = true)
|
||
|
|
* - 해당 테넌트 게시판 (tenant_id = 현재 테넌트)
|
||
|
|
*/
|
||
|
|
public function scopeAccessible($query, int $tenantId)
|
||
|
|
{
|
||
|
|
return $query->where(function ($q) use ($tenantId) {
|
||
|
|
$q->where('is_system', true)
|
||
|
|
->orWhere('tenant_id', $tenantId);
|
||
|
|
})->where('is_active', true);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 시스템 게시판만 (mng용)
|
||
|
|
*/
|
||
|
|
public function scopeSystemOnly($query)
|
||
|
|
{
|
||
|
|
return $query->where('is_system', true);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 테넌트 게시판만
|
||
|
|
*/
|
||
|
|
public function scopeTenantOnly($query, int $tenantId)
|
||
|
|
{
|
||
|
|
return $query->where('is_system', false)
|
||
|
|
->where('tenant_id', $tenantId);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 관계
|
||
|
|
public function fields()
|
||
|
|
{
|
||
|
|
return $this->hasMany(BoardSetting::class, 'board_id')
|
||
|
|
->orderBy('sort_order');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function posts()
|
||
|
|
{
|
||
|
|
return $this->hasMany(Post::class, 'board_id');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Helper
|
||
|
|
public function getSetting(string $key, $default = null)
|
||
|
|
{
|
||
|
|
return data_get($this->extra_settings, $key, $default);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5.2 BoardService
|
||
|
|
|
||
|
|
```php
|
||
|
|
// api/app/Services/Boards/BoardService.php
|
||
|
|
|
||
|
|
namespace App\Services\Boards;
|
||
|
|
|
||
|
|
use App\Models\Boards\Board;
|
||
|
|
use App\Services\Service;
|
||
|
|
|
||
|
|
class BoardService extends Service
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* 접근 가능한 게시판 목록 (시스템 + 테넌트)
|
||
|
|
*/
|
||
|
|
public function getAccessibleBoards(array $filters = [])
|
||
|
|
{
|
||
|
|
return Board::accessible($this->tenantId())
|
||
|
|
->when(isset($filters['board_type']), fn($q) =>
|
||
|
|
$q->where('board_type', $filters['board_type']))
|
||
|
|
->orderBy('is_system', 'desc')
|
||
|
|
->orderBy('name')
|
||
|
|
->get();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 시스템 게시판 목록 (mng용)
|
||
|
|
*/
|
||
|
|
public function getSystemBoards()
|
||
|
|
{
|
||
|
|
return Board::systemOnly()
|
||
|
|
->orderBy('name')
|
||
|
|
->get();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 시스템 게시판 생성 (mng용)
|
||
|
|
*/
|
||
|
|
public function createSystemBoard(array $data): Board
|
||
|
|
{
|
||
|
|
$data['is_system'] = true;
|
||
|
|
$data['tenant_id'] = null;
|
||
|
|
$data['created_by'] = $this->apiUserId();
|
||
|
|
|
||
|
|
return Board::create($data);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 테넌트 게시판 생성 (sam용)
|
||
|
|
*/
|
||
|
|
public function createTenantBoard(array $data): Board
|
||
|
|
{
|
||
|
|
$data['is_system'] = false;
|
||
|
|
$data['tenant_id'] = $this->tenantId();
|
||
|
|
$data['created_by'] = $this->apiUserId();
|
||
|
|
|
||
|
|
return Board::create($data);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 게시판 코드로 조회
|
||
|
|
*/
|
||
|
|
public function getBoardByCode(string $code): ?Board
|
||
|
|
{
|
||
|
|
return Board::accessible($this->tenantId())
|
||
|
|
->where('board_code', $code)
|
||
|
|
->first();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 6. 권한 모델
|
||
|
|
|
||
|
|
### 6.1 extra_settings 기반 권한
|
||
|
|
|
||
|
|
게시판별 권한은 `extra_settings` JSON 필드로 관리:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"permissions": {
|
||
|
|
"read": ["*"], // 모든 역할 읽기 가능
|
||
|
|
"write": ["admin", "user"], // admin, user 역할만 작성
|
||
|
|
"manage": ["admin"] // admin만 관리
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 6.2 권한 검증
|
||
|
|
|
||
|
|
```php
|
||
|
|
// Board 모델에 추가
|
||
|
|
public function canRead(User $user): bool
|
||
|
|
{
|
||
|
|
$roles = $this->getSetting('permissions.read', ['*']);
|
||
|
|
return in_array('*', $roles) ||
|
||
|
|
$user->hasAnyRole($roles);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function canWrite(User $user): bool
|
||
|
|
{
|
||
|
|
$roles = $this->getSetting('permissions.write', ['*']);
|
||
|
|
return in_array('*', $roles) ||
|
||
|
|
$user->hasAnyRole($roles);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function canManage(User $user): bool
|
||
|
|
{
|
||
|
|
$roles = $this->getSetting('permissions.manage', ['admin']);
|
||
|
|
return $user->hasAnyRole($roles);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 7. 구현 계획
|
||
|
|
|
||
|
|
### 7.1 Phase 1: DB 마이그레이션 (api/)
|
||
|
|
|
||
|
|
1. `boards` 테이블 확장
|
||
|
|
- `tenant_id` nullable 변경
|
||
|
|
- `is_system` 컬럼 추가
|
||
|
|
- `board_type` 컬럼 추가
|
||
|
|
- `deleted_at`, `deleted_by` 추가 (없으면)
|
||
|
|
- 인덱스 추가
|
||
|
|
|
||
|
|
### 7.2 Phase 2: 모델/서비스 수정 (api/)
|
||
|
|
|
||
|
|
1. `Board` 모델 업데이트
|
||
|
|
- 스코프 추가 (accessible, systemOnly, tenantOnly)
|
||
|
|
- SoftDeletes 적용
|
||
|
|
- 권한 헬퍼 메서드
|
||
|
|
|
||
|
|
2. `BoardService` 구현
|
||
|
|
- 시스템/테넌트 게시판 분리 로직
|
||
|
|
|
||
|
|
### 7.3 Phase 3: mng 화면 개발
|
||
|
|
|
||
|
|
1. 게시판 목록 (`/mng/boards`)
|
||
|
|
2. 게시판 생성/수정 폼
|
||
|
|
3. 게시판 필드 관리
|
||
|
|
|
||
|
|
### 7.4 Phase 4: sam API 개발
|
||
|
|
|
||
|
|
1. 게시판 API (`/v1/boards`)
|
||
|
|
2. 게시글 API (`/v1/boards/{code}/posts`)
|
||
|
|
3. Swagger 문서
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 8. 관련 문서
|
||
|
|
|
||
|
|
- [데이터베이스 스키마](./database/README.md)
|
||
|
|
- [API 개발 규칙](../standards/api-rules.md)
|
||
|
|
- [MNG Critical Rules](../../mng/docs/MNG_CRITICAL_RULES.md)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**최종 업데이트**: 2025-11-27
|
||
|
|
**버전**: 1.0
|
||
|
|
**상태**: 설계 완료
|