ID: key_26_22_05_25_P3_3_1 Created date: 5월 25 2026 월요일
연관 문서
개요
이슈 첨부 파일 업로드 API를 구현한다. 스토리지는 AWS S3 또는 MinIO를 사용한다.
- 예상 소요: 3~4일
- 선행 조건: 스토리지 결정 (AWS S3 / GCS / MinIO)
- 완료 기준: 파일 업로드 → S3 저장 → 다운로드 URL 반환 동작 확인
Claude Code 작업 수행서
작업 지시
CIRA 서버에 파일 첨부 API를 구현해줘.
[스토리지 선택]
- [AWS S3 / MinIO 중 결정값]
- Bucket 이름: cira-attachments
- Region: (결정값)
[수행 작업]
1. 의존성 추가
- AWS SDK v2: software.amazon.awssdk:s3
- 또는 MinIO: io.minio:minio
2. 스토리지 설정
파일: application.yml
cloud:
aws:
s3.bucket: cira-attachments
credentials.access-key: (placeholder)
credentials.secret-key: (placeholder)
region.static: ap-northeast-2
3. StorageService 구현
파일: src/main/java/.../common/storage/StorageService.java
- upload(MultipartFile file, String path): String (저장된 S3 key)
- generatePresignedUrl(String s3Key): String (15분 유효 URL)
- delete(String s3Key): void
파일 경로 패턴: attachments/{projectId}/{issueId}/{uuid}_{originalFileName}
4. 첨부 파일 API
POST /api/v1/issues/{issueId}/attachments
- multipart/form-data 수신
- 파일 크기 제한: 50MB
- 허용 MIME 타입: image/*, application/pdf, text/*, application/zip 등
- S3 업로드 → attachments 테이블 INSERT
- Response: AttachmentResponse (id, fileName, fileSize, mimeType, uploadedAt, downloadUrl)
GET /api/v1/issues/{issueId}/attachments
- attachments 테이블 조회
- 각 파일에 Presigned URL 포함
GET /api/v1/attachments/{attachmentId}/download
- Presigned URL 생성 후 302 Redirect
DELETE /api/v1/attachments/{attachmentId}
- S3 파일 삭제
- attachments 테이블 Soft Delete
5. 보안 처리
- 파일명 sanitize (경로 traversal 방지)
- 업로드자 또는 프로젝트 Admin만 삭제 가능
- Presigned URL TTL: 15분
6. issue_logs에 첨부 기록
- 파일 추가/삭제 시 이슈 이력에 기록
[준수 사항]
- 비동기 업로드 고려 (대용량 파일)
- 업로드 실패 시 S3 임시 파일 정리 (트랜잭션 주의)
완료 기준
| 항목 | 기준 |
|---|---|
| 파일 업로드 | S3 저장 + DB 기록 |
| 다운로드 URL | Presigned URL 정상 동작 |
| 파일 삭제 | S3 + DB 동시 처리 |
| 파일 크기/타입 검증 | 초과/비허용 시 400 에러 |