Files
sam-docs/dev/guides/2025-12-02_file-attachment-feature.md
권혁성 db63fcff85 refactor: [docs] 팀별 폴더 구조 재편 (공유/개발/프론트/기획)
- 개발팀 전용 폴더 dev/ 생성 (standards, guides, quickstart, changes, deploys, data, history, dev_plans 이동)
- 프론트엔드 전용 폴더 frontend/ 생성 (api/ → frontend/api-specs/)
- 기획팀 폴더 requests/ 생성
- plans/ → dev/dev_plans/ 이름 변경
- README.md 신규 (사람용 안내), INDEX.md 재작성 (Claude Code용)
- resources.md 신규 (노션 링크용, assets/brochure 이관 예정)
- CURRENT_WORKS.md 삭제, TODO.md → dev/ 이동
- 전체 참조 경로 업데이트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:46:03 +09:00

7.0 KiB

게시글 파일 첨부 기능 구현 + 공유 스토리지 설정

작업일: 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 관계

// 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 마이그레이션 방법

# .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)
  • 시각적 피드백 (드래그 시 테두리 파란색 변경)
  • 기존 파일 개수 고려 (최대 파일 수 체크 시 기존 파일 포함)

검증 결과

  • PHP 문법 검증 통과
  • 라우트 등록 확인
  • tenant 디스크 설정 확인
  • Pint 코드 포맷팅 완료

다음 단계 (커밋)

API 저장소

cd /Users/kent/Works/@KD_SAM/SAM/api
git add .
git commit -m "feat(SAM-API): board_files 테이블 삭제 마이그레이션"

MNG 저장소

cd /Users/kent/Works/@KD_SAM/SAM/mng
git add .
git commit -m "feat(SAM-MNG): 게시글 파일 첨부 기능 구현"