feat: 게시글 파일 첨부 기능 구현
- File 모델 추가 (Polymorphic 관계) - Post 모델에 files() MorphMany 관계 추가 - PostService 파일 업로드/삭제/다운로드 메서드 추가 - PostController 파일 관련 액션 추가 - 게시글 작성/수정 폼에 드래그앤드롭 파일 업로드 UI - 게시글 상세에 첨부파일 목록 표시 - tenant 디스크 설정 (공유 스토리지) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
163
claudedocs/2025-12-02_file-attachment-feature.md
Normal file
163
claudedocs/2025-12-02_file-attachment-feature.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# 게시글 파일 첨부 기능 구현 + 공유 스토리지 설정
|
||||
|
||||
**작업일**: 2025-12-02
|
||||
**저장소**: MNG, API, Docker
|
||||
**워크플로우**: code-workflow (분석→수정→검증→정리→커밋)
|
||||
|
||||
---
|
||||
|
||||
## 개요
|
||||
|
||||
게시판 시스템에 파일 첨부 기능을 추가했습니다. 기존의 `board_files` 테이블 대신 범용 `files` 테이블의 polymorphic 관계를 활용합니다.
|
||||
|
||||
**추가 작업**: API와 MNG 간 파일 공유를 위한 Docker 공유 볼륨 설정 및 S3 마이그레이션 용이한 구조로 변경
|
||||
|
||||
## 변경 파일
|
||||
|
||||
### Docker 설정
|
||||
| 파일 | 작업 | 설명 |
|
||||
|------|------|------|
|
||||
| `docker/docker-compose.yml` | 수정 | sam_storage 공유 볼륨 추가 (api, admin, mng) |
|
||||
|
||||
### API 저장소
|
||||
| 파일 | 작업 | 설명 |
|
||||
|------|------|------|
|
||||
| `config/filesystems.php` | 수정 | tenant 디스크 공유 경로 + S3 설정 |
|
||||
| `database/migrations/2025_12_02_000238_drop_board_files_table.php` | 생성 | board_files 테이블 삭제 |
|
||||
|
||||
### MNG 저장소
|
||||
| 파일 | 작업 | 설명 |
|
||||
|------|------|------|
|
||||
| `app/Models/Boards/File.php` | 생성 | Polymorphic 파일 모델 |
|
||||
| `app/Models/Boards/Post.php` | 수정 | files() MorphMany 관계 추가 |
|
||||
| `app/Services/PostService.php` | 수정 | 파일 업로드/삭제/다운로드 + 경로 패턴 수정 |
|
||||
| `app/Http/Controllers/PostController.php` | 수정 | 파일 관련 액션 추가 |
|
||||
| `resources/views/posts/create.blade.php` | 수정 | 파일 업로드 UI |
|
||||
| `resources/views/posts/show.blade.php` | 수정 | 첨부파일 목록 표시 |
|
||||
| `resources/views/posts/edit.blade.php` | 수정 | 기존 파일 관리 + 새 파일 업로드 |
|
||||
| `routes/web.php` | 수정 | 파일 라우트 추가 |
|
||||
| `config/filesystems.php` | 수정 | tenant 디스크 공유 경로 + S3 설정 |
|
||||
| `storage/app/tenants/.gitignore` | 생성 | 업로드 파일 Git 제외 |
|
||||
|
||||
## 기술 상세
|
||||
|
||||
### Polymorphic 관계
|
||||
```php
|
||||
// Post -> files() MorphMany
|
||||
$post->files; // Collection of File models
|
||||
|
||||
// File -> fileable() MorphTo
|
||||
$file->fileable; // Returns Post model
|
||||
```
|
||||
|
||||
### 파일 저장 경로 (공유 스토리지)
|
||||
```
|
||||
Docker 볼륨: sam_storage → /var/www/shared-storage
|
||||
실제 경로: /var/www/shared-storage/tenants/{tenant_id}/posts/{year}/{month}/{stored_name}
|
||||
DB 저장: {tenant_id}/posts/{year}/{month}/{stored_name}
|
||||
```
|
||||
|
||||
### 공유 스토리지 아키텍처
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Docker Volume: sam_storage │
|
||||
│ /var/www/shared-storage/tenants │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ API │ │ MNG │ │ Admin │ │
|
||||
│ │Container│ │Container│ │Container│ │
|
||||
│ └────┬────┘ └────┬────┘ └────┬────┘ │
|
||||
│ │ │ │ │
|
||||
│ └────────────────┴────────────────┘ │
|
||||
│ │ │
|
||||
│ Storage::disk('tenant') │
|
||||
│ │ │
|
||||
│ ┌─────────────────────┴─────────────────────┐ │
|
||||
│ │ /var/www/shared-storage/tenants │ │
|
||||
│ │ ├── {tenant_id}/ │ │
|
||||
│ │ │ ├── posts/2025/12/xxx.pdf │ │
|
||||
│ │ │ ├── products/2025/12/yyy.jpg │ │
|
||||
│ │ │ └── documents/2025/12/zzz.docx │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### S3 마이그레이션 방법
|
||||
```bash
|
||||
# .env 설정 변경만으로 S3 전환 가능
|
||||
TENANT_STORAGE_DRIVER=s3
|
||||
AWS_ACCESS_KEY_ID=your_key
|
||||
AWS_SECRET_ACCESS_KEY=your_secret
|
||||
AWS_DEFAULT_REGION=ap-northeast-2
|
||||
AWS_BUCKET=sam-storage
|
||||
```
|
||||
|
||||
### 게시판 설정
|
||||
- `allow_files`: 파일 첨부 허용 여부
|
||||
- `max_file_count`: 최대 파일 개수
|
||||
- `max_file_size`: 최대 파일 크기 (KB)
|
||||
|
||||
### 새 라우트
|
||||
```
|
||||
GET boards/{board}/posts/{post}/files/{fileId}/download # 다운로드
|
||||
POST boards/{board}/posts/{post}/files # 업로드 (AJAX)
|
||||
DELETE boards/{board}/posts/{post}/files/{fileId} # 삭제 (AJAX)
|
||||
```
|
||||
|
||||
### File 모델 주요 메서드
|
||||
- `fileable()`: Polymorphic 관계
|
||||
- `download()`: StreamedResponse 반환
|
||||
- `getFormattedSize()`: 사람이 읽기 쉬운 파일 크기
|
||||
- `isImage()`: 이미지 파일 여부
|
||||
- `permanentDelete()`: 실제 파일 + DB 레코드 삭제
|
||||
|
||||
### PostService 주요 메서드
|
||||
- `uploadFiles(Post, array)`: 파일 업로드 및 저장
|
||||
- `deleteFile(Post, fileId)`: 파일 소프트 삭제
|
||||
- `downloadFile(Post, fileId)`: 파일 다운로드 응답
|
||||
|
||||
## UI 기능
|
||||
|
||||
### 글쓰기 (create.blade.php)
|
||||
- 드래그앤드롭 파일 업로드 영역 ✅
|
||||
- 파일 선택 시 미리보기 목록
|
||||
- 파일 개수/크기 제한 클라이언트 검증
|
||||
- **드래그앤드롭 JS 이벤트** (dragenter, dragover, dragleave, drop)
|
||||
- **시각적 피드백** (드래그 시 테두리 파란색 변경)
|
||||
|
||||
### 글보기 (show.blade.php)
|
||||
- 첨부파일 섹션 (파일 있을 때만 표시)
|
||||
- 이미지/문서 아이콘 구분
|
||||
- 다운로드 버튼
|
||||
|
||||
### 글수정 (edit.blade.php)
|
||||
- 기존 첨부파일 목록 (삭제 버튼 포함)
|
||||
- AJAX 파일 삭제 (확인 후 즉시 반영)
|
||||
- 새 파일 추가 영역
|
||||
- **드래그앤드롭 JS 이벤트** (dragenter, dragover, dragleave, drop)
|
||||
- **시각적 피드백** (드래그 시 테두리 파란색 변경)
|
||||
- **기존 파일 개수 고려** (최대 파일 수 체크 시 기존 파일 포함)
|
||||
|
||||
## 검증 결과
|
||||
|
||||
- [x] PHP 문법 검증 통과
|
||||
- [x] 라우트 등록 확인
|
||||
- [x] tenant 디스크 설정 확인
|
||||
- [x] Pint 코드 포맷팅 완료
|
||||
|
||||
## 다음 단계 (커밋)
|
||||
|
||||
### API 저장소
|
||||
```bash
|
||||
cd /Users/kent/Works/@KD_SAM/SAM/api
|
||||
git add .
|
||||
git commit -m "feat(SAM-API): board_files 테이블 삭제 마이그레이션"
|
||||
```
|
||||
|
||||
### MNG 저장소
|
||||
```bash
|
||||
cd /Users/kent/Works/@KD_SAM/SAM/mng
|
||||
git add .
|
||||
git commit -m "feat(SAM-MNG): 게시글 파일 첨부 기능 구현"
|
||||
```
|
||||
Reference in New Issue
Block a user