Skip to content

[feat] 배너 미디어 타입 지원 (IMAGE/VIDEO) 및 동영상 업로드#38

Merged
hyejj19 merged 4 commits intomainfrom
feature/webp-upload-optimize
Mar 26, 2026
Merged

[feat] 배너 미디어 타입 지원 (IMAGE/VIDEO) 및 동영상 업로드#38
hyejj19 merged 4 commits intomainfrom
feature/webp-upload-optimize

Conversation

@hyejj19
Copy link
Copy Markdown
Collaborator

@hyejj19 hyejj19 commented Mar 26, 2026

요약

배너 API에 추가된 mediaType 필드(IMAGE/VIDEO)를 프론트엔드 전 계층에 반영하고, 동영상(MP4) 업로드 및 미리보기 기능을 구현한다.

동기

  • animated WebP는 모바일에서 하드웨어 디코딩 미지원으로 CPU 부하가 심함 → MP4 전환 필요 (workspace#205)
  • 백엔드에서 presigned URL의 contentType 파라미터 및 Banner 엔티티의 mediaType 필드가 이미 반영됨 (bottle-note-api-server#571)

변경사항

API 타입 (types → service → hook 3계층)

  • MediaType 타입(IMAGE | VIDEO) 및 MEDIA_TYPE_LABELS 추가
  • 배너 목록/상세 응답에 mediaType 필드 추가
  • 배너 생성/수정 요청에 mediaType? 필드 추가
  • PresignUrlParamscontentType? 파라미터 추가
  • s3Service.uploadImage에서 presigned URL 요청 시 contentType 전달

폼 / UI

  • 폼 스키마에 mediaType enum 필드 추가 (기본값: IMAGE)
  • useBannerDetailForm: 폼 초기화 및 API 요청 시 mediaType 포함
  • ImageUpload: accept, onFileRejected, 비디오 미리보기 분기 지원
  • BannerImageCard: image/*,video/mp4 허용, file.type 기반 mediaType 자동 판별, 허용 외 파일 에러 토스트
  • BannerPreviewCard: form.mediaType 기반 <video> 미리보기

버그 수정

  • blob URL에서 useEffectisVideo 상태를 덮어쓰는 문제 수정 (CDN URL만 확장자 기반 판별, blob URL은 handleFile에서 설정한 값 유지)

테스트

  • ImageUpload.test.tsx: 파일 검증 유틸(isFileTypeAllowed, isVideoFile), 파일 거부 콜백, 미리보기 렌더링 분기, blob URL 재렌더링 안정성 (35 cases)
  • BannerImageCard.test.tsx: mediaType 자동 판별, 파일 거부, UI 상태 (8 cases)
  • banner.schema.test.ts: 폼 스키마 유효성 검사 (6 cases)
  • s3.service.test.ts: presigned URL contentType 전달, S3 업로드 헤더, 에러 처리 (8 cases)
  • useBanners.test.ts: 목록/상세 mediaType 포함, VIDEO 타입 생성/수정 (4 cases 추가)
  • banners.spec.ts (E2E): 동영상/이미지 업로드 시 미리보기 분기 (2 cases)

테스트

  • pnpm test:run — 129개 테스트 전부 통과
  • pnpm build — 타입 체크 + 프로덕션 빌드 통과
  • 로컬에서 이미지 업로드 → <img> 미리보기 확인
  • 로컬에서 MP4 업로드 → <video> 미리보기 확인
  • 허용 외 파일(.pdf 등) → 에러 토스트 확인

🤖 Generated with Claude Code

배너 API에 추가된 mediaType 필드를 프론트엔드 전 계층에 반영하고,
동영상(MP4) 업로드 및 미리보기 기능을 구현한다.

- types: MediaType 타입, presigned URL contentType 파라미터 추가
- schema: 폼 스키마에 mediaType 필드 추가 (기본값: IMAGE)
- service: S3 presigned URL 요청 시 contentType 전달
- form: 파일 업로드 시 file.type 기반 mediaType 자동 판별
- ImageUpload: 이미지/동영상 accept, 거부 콜백, 미리보기 분기
- BannerImageCard: 허용 외 파일 에러 토스트, mediaType 자동 설정
- BannerPreviewCard: form.mediaType 기반 비디오 미리보기
- fix: blob URL에서 useEffect가 isVideo를 덮어쓰는 버그 수정
- test: 유틸/컴포넌트/서비스/훅/E2E 테스트 51개 추가 (총 129개)

Refs: bottle-note/workspace#205

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 26, 2026 01:30
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

배너 API의 mediaType(IMAGE/VIDEO) 추가에 맞춰 프론트 전 계층 타입/서비스/훅/폼/UI를 확장하고, MP4 업로드 및 미리보기까지 지원하도록 변경한 PR입니다.

Changes:

  • MediaType 및 배너 API 타입(mediaType) / S3 presign 파라미터(contentType) 반영
  • 배너 등록/수정 폼에 mediaType 포함, 업로드 컴포넌트가 image/*,video/mp4<video> 미리보기 지원
  • 관련 단위 테스트 및 E2E 테스트/fixture 추가

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/types/api/s3.api.ts presign URL 요청 파라미터에 contentType? 추가
src/types/api/banner.api.ts MediaType/라벨, 배너 응답·요청에 mediaType 추가
src/test/mocks/data.ts 배너 mock 데이터에 mediaType 추가
src/services/s3.service.ts uploadImage에서 presign 요청 시 contentType 전달
src/services/tests/s3.service.test.ts contentType 전달 및 PUT 헤더 관련 테스트 추가
src/pages/banners/useBannerDetailForm.ts 폼 초기값/submit payload에 mediaType 포함
src/pages/banners/components/BannerPreviewCard.tsx mediaType에 따라 <img>/<video> 미리보기 분기
src/pages/banners/components/BannerImageCard.tsx accept/reject 처리, file.type 기반 mediaType 자동 판별
src/pages/banners/banner.schema.ts Zod 스키마에 mediaType 추가 및 기본값 설정
src/pages/banners/tests/banner.schema.test.ts mediaType 스키마 검증 테스트 추가
src/pages/banners/tests/BannerImageCard.test.tsx mediaType 자동 판별/거부/UI 상태 테스트 추가
src/pages/banners/BannerDetail.tsx 업로드/삭제 흐름에서 mediaType 상태 반영
src/hooks/tests/useBanners.test.ts 목록/상세/생성/수정에서 mediaType 검증 테스트 추가
src/components/common/ImageUpload.tsx accept/거부 콜백, 비디오 미리보기, blob URL 판별 로직 추가
src/components/common/tests/ImageUpload.test.tsx 파일 타입 유틸/거부/미리보기 분기/재렌더 안정성 테스트 추가
e2e/specs/banners.spec.ts 동영상/이미지 업로드 미리보기 분기 E2E 추가
e2e/pages/banner-detail.page.ts 업로드 대상 locator 및 업로드 헬퍼(video) 추가
e2e/fixtures/test-video.mp4 E2E용 MP4 fixture 추가

Comment on lines +60 to 66
uploadImage: async (file: File, rootPath: string, contentType?: string): Promise<string> => {
// 1. Presigned URL 발급
const presignResponse = await s3Service.getPresignedUrls({
rootPath,
uploadSize: 1,
contentType: contentType ?? file.type,
});
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] uploadImage에서 contentType을 presign 요청에만 적용하고, 실제 S3 PUT은 항상 file.type으로 Content-Type 헤더를 보내서 불일치가 발생할 수 있습니다.

uploadImage(file, rootPath, 'video/webm')처럼 contentType을 명시한 경우 presigned URL의 서명 조건과 PUT 헤더가 달라져 업로드가 403으로 실패할 수 있습니다; PUT에도 동일한 contentType을 사용하도록 uploadToS3에 전달해 주세요.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 9bf359e.

변경 내용: uploadToS3contentType 파라미터를 추가하고, uploadImage에서 presign과 PUT 양쪽에 동일한 contentType을 전달하도록 수정했습니다.
이유: presigned URL 서명 조건과 S3 PUT 헤더가 불일치하면 403 에러가 발생하므로, 두 값을 항상 일치시켜야 합니다.

Comment on lines +92 to 95
setIsVideo(file.type.startsWith('video/'));
const url = URL.createObjectURL(file);
setPreviewUrl(url);
onImageChange(file, url);
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] URL.createObjectURL로 만든 blob URL을 URL.revokeObjectURL로 정리하지 않아 파일을 여러 번 교체/삭제하면 메모리가 누적될 수 있습니다.

배너 등록/수정 페이지에서 미디어를 여러 번 바꾸는 경우 탭 메모리가 계속 증가할 수 있으니, 새 blob URL 생성 전에 이전 URL을 revoke하고 unmount/삭제 시에도 revoke하도록 cleanup을 추가해 주세요.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e07e49f.

변경 내용: blobUrlRef로 현재 blob URL을 추적하고, 파일 교체 시 이전 blob URL을 URL.revokeObjectURL로 정리합니다. 삭제 시에도 동일하게 cleanup합니다.
이유: 파일을 여러 번 교체하면 blob URL이 누적되어 메모리 누수가 발생할 수 있습니다.

Comment on lines +68 to +70
const handleMediaTypeChange = (mediaType: 'IMAGE' | 'VIDEO') => {
form.setValue('mediaType', mediaType);
};
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 폼 validation 실패 시 console.log가 남아 있습니다.

프로덕션에서 콘솔 로그가 남으면 운영 중 디버그 출력이 노출될 수 있으니 제거하거나 로깅 유틸로 대체해 주세요.

Copilot generated this review using guidance from repository custom instructions.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in bcf586c.

변경 내용: console.log 디버그 코드를 제거하고, 불필요한 에러 핸들러 콜백도 함께 제거했습니다.

hyejj19 and others added 3 commits March 26, 2026 10:52
uploadToS3에 contentType 파라미터를 추가하여 presigned URL 서명 조건과
S3 PUT 헤더가 항상 동일하도록 보장한다.

Addresses review comment by @Copilot on src/services/s3.service.ts:66.
PR: #38

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
파일 교체/삭제 시 이전 blob URL을 revokeObjectURL로 정리하여
메모리 누적을 방지한다. 빌드 에러 수정 포함.

Addresses review comment by @Copilot on src/components/common/ImageUpload.tsx:95.
PR: #38

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
폼 validation 에러 핸들러의 console.log를 제거한다.

Addresses review comment by @Copilot on src/pages/banners/BannerDetail.tsx:70.
PR: #38

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@hyejj19 hyejj19 merged commit 1135150 into main Mar 26, 2026
2 checks passed
@hyejj19 hyejj19 deleted the feature/webp-upload-optimize branch March 26, 2026 01:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants