Skip to content

♻️Refactor & Update: CloudFront–S3 기반 영상 CDN 적용 및 접근 정책 개선#144

Merged
skyblue1232 merged 3 commits intodevelopfrom
refactor/#135/web-app-accessibility
Nov 15, 2025
Merged

♻️Refactor & Update: CloudFront–S3 기반 영상 CDN 적용 및 접근 정책 개선#144
skyblue1232 merged 3 commits intodevelopfrom
refactor/#135/web-app-accessibility

Conversation

@skyblue1232
Copy link
Copy Markdown
Contributor

@skyblue1232 skyblue1232 commented Nov 15, 2025

🔥 작업 내용

  • CloudFront 기반 영상 CDN 적용
    • 도메인 cdn.geulda.kr을 CloudFront Distribution과 연결
    • ACM(us-east-1) 인증서 생성 및 CNAME 검증 완료
    • CloudFront Origin을 S3 버킷로 지정하여 HTTPS 전송 및 캐싱 활성화
  • S3 경로 구조 재정리
    • /upload/video/ 폴더로 mp4 리소스 전용 디렉터리 생성
    • 기존 이미지 파일(jpg/png)과 충돌 방지
    • CloudFront Origin Path와 요청 URL 경로 일치하도록 구조 정규화
  • S3 퍼블릭 접근 & CloudFront 권한 구성
    • 퍼블릭 액세스 차단 상태 점검 후 필요한 범위만 허용
    • CloudFront Origin Access Control(OAC) 허용 정책 추가
    • s3:GetObject 권한을 CloudFront 및 퍼블릭에 적절히 부여
  • CORS 및 메타데이터 적용
    • 영상 스트리밍을 위해 CORS(JSON) 업데이트
    • mp4 객체에 Content-Type: video/mp4 메타데이터 적용
    • CDN 캐싱 강화를 위해 Cache-Control(public, max-age=31536000) 추가
  • 프론트엔드 영상 링크 전면 교체
    • 기존 S3 URL → https://cdn.geulda.kr/upload/video/... 로 전면 변경
    • preload 옵션 기반 초기 렌더링 최적화 적용 준비
    • AccessDenied 문제 해결 후 정상 스트리밍 확인 완료
  • UX 개선 작업
    • 영상 시청 페이지에 '건너뛰기' 버튼 추가
    • 자동 재생 + 스킵 지원으로 사용자 흐름 선택권 강화
    • iOS 전체화면 강제 방지(playsInline) 등 모바일 UX 안정성 확보

⚡ 적용 방법 요약

  1. 영상 파일(mp4) 은 앞으로 S3 /upload/video 폴더에 업로드
  2. 프론트에서 영상 URL은 다음 형태로 사용
    https://cdn.geulda.kr/upload/video/파일명.mp4
  3. 객체 업로드 시 Content-Type: video/mp4 으로만 설정하면 자동 반영
  4. 기존 S3 링크 사용 금지 → 모든 링크 CDN 주소로 통일
  5. 다른 설정 필요 없이 CloudFront가 자동 캐싱 & HTTPS 제공

🤔 추후 작업 사항

  • HLS(MediaConvert) 기반 스트리밍 적용 검토
  • CloudFront 캐시 키(Cache Key) 최적화 여부 확인
  • 이미지 리소스에도 CDN 적용 확장 가능성 검토
  • Preload/IntersectionObserver 기반 렌더링 최적화 예정
  • UX 개선

🔗 이슈

PR Point (To Reviewer)

  • CloudFront Origin Path(/upload/video) 설정이 올바른지 확인 부탁드립니다.
  • S3 버킷 정책이 과도하게 노출되지 않았는지 검토 부탁드립니다.
  • CDN URL 변경된 부분 중 누락된 링크가 없는지 체크 부탁드립니다.

📸 피그마 스크린샷 or 기능 GIF

(캡처 첨부)

Summary by CodeRabbit

릴리스 노트

  • Chores
    • 동영상 서비스 인프라를 개선하여 콘텐츠 전송 성능을 최적화했습니다.

@skyblue1232 skyblue1232 self-assigned this Nov 15, 2025
@skyblue1232 skyblue1232 added the refactor 프로덕션 코드 리팩토링업, QA 반영 label Nov 15, 2025
@skyblue1232 skyblue1232 added the update 뭐라 형용할 수 없는 업데이트 label Nov 15, 2025
@vercel
Copy link
Copy Markdown

vercel bot commented Nov 15, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
af-fe Ready Ready Preview Comment Nov 15, 2025 7:10pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Nov 15, 2025

Walkthrough

videoLocations.ts의 모든 videoSrc 문자열을 S3 -> CDN(cdn.geulda.kr)으로 교체하고, 메인 동영상 재생 흐름에 "Skip" 버튼을 추가해 동영상 종료 시와 동일한 라우팅을 호출하도록 했습니다. VideoPlayer 컴포넌트는 src를 trim하고 preload="auto" autoPlay muted playsInline controls={false}로 속성을 변경했습니다.

Changes

Cohort / File(s) Summary
CDN 마이그레이션
src/shared/constants/main/videoLocations.ts
videoSrc 값들을 S3 버킷 도메인에서 CDN 도메인(cdn.geulda.kr)으로 모두 교체
페이지: 스킵 버튼 추가
src/pages/main/videoPlay/index.tsx
비디오 설명 아래에 "Skip" 버튼 추가; 클릭 시 기존 handleVideoEnd 로직을 호출해 HiddenReward 또는 PostCard로 라우팅
비디오 플레이어 속성 변경
src/shared/components/main/components/video/VideoPlayer.tsx
srctrim()하여 사용하도록 변경; preload="auto", autoPlay, muted, playsInline, controls={false} 속성으로 재생/버퍼/컨트롤 동작 조정 (렌더 조건 및 이벤트 콜백 유지)

Sequence Diagram(s)

sequenceDiagram
  participant User as 사용자
  participant Page as VideoPlay 페이지
  participant Player as VideoPlayer
  participant Router as 라우터

  User->>Page: 페이지 진입
  Page->>Player: videoSrc 전달
  Player->>Player: src.trim(), preload/autoPlay 설정
  Player-->>User: 비디오 재생 시작 (자동)
  alt 유저가 끝까지 재생
    Player->>Page: onEnd 이벤트
    Page->>Router: handleVideoEnd() 호출 -> HiddenReward / PostCard 라우팅
  else 유저가 Skip 버튼 클릭
    User->>Page: Skip 클릭
    Page->>Page: handleVideoEnd() 호출
    Page->>Router: HiddenReward / PostCard 라우팅
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 분

  • 이유: 단순 문자열 교체 외에 UI(버튼)와 VideoPlayer 속성 변경이 있어 동작/접근성 검증 필요
  • 주의 검토 포인트:
    • VideoPlayer의 autoplay/muted/playsInline가 모바일/브라우저별 동작에 미치는 영향
    • src.trim()이 모든 입력 케이스에 안전한지(널/undefined 처리)
    • Skip 버튼의 접근성(aria-label) 및 키보드 포커스/동작
    • CDN URL 변경으로 인한 CORS/캐싱/경로 오타 점검

Possibly related issues

Possibly related PRs

Suggested labels

feat

Suggested reviewers

  • KongMezu
  • jjangminii

Poem

🐰✨
CDN 길로 바삐 달려가며
짧게 자른 src에 귀 기울여요
스킵 한 번이면 목적지로 휙 —
재생은 조용히, 길은 빠르게,
우리 래빗은 춤추며 축하해요 🎬

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed PR 설명이 제공된 템플릿의 모든 필수 섹션(작업 내용, 추후 작업 사항, 이슈, PR Point, 피그마 스크린샷)을 포함하고 있으며, CloudFront CDN 적용과 프론트엔드 변경 사항을 상세히 기술하고 있습니다.
Title check ✅ Passed PR 타이틀이 CloudFront CDN 적용 및 S3 설정 개선이라는 주요 변경 사항을 명확하게 반영하고 있으며, 실제 변경 내용(S3 URL을 CDN 도메인으로 교체, 비디오 플레이어 속성 개선, Skip 버튼 추가)과 일치합니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/#135/web-app-accessibility

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the comment 필요한 주석 추가 및 변경 label Nov 15, 2025
@github-actions
Copy link
Copy Markdown

🏷️ Labeler has automatically applied labels based on your PR title, branch name, or commit message.
Please verify that they are correct before merging.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/shared/constants/main/videoLocations.ts (1)

3-54: CDN 베이스 URL을 상수로 추출하는 것을 권장합니다.

현재 CDN 베이스 URL(https://cdn.geulda.kr/upload/video/)이 10개의 항목에 반복되고 있습니다. 이를 별도 상수로 추출하면 다음과 같은 이점이 있습니다:

  • 향후 CDN 도메인 변경 시 한 곳만 수정
  • 환경별(dev/staging/prod) 설정 관리 용이
  • 유지보수성 향상

다음과 같이 리팩토링을 적용하세요:

 import { VideoLocation } from "@/shared/types/main/videoLocation";
 
+const CDN_VIDEO_BASE_URL = "https://cdn.geulda.kr/upload/video/";
+
 export const VIDEO_LOCATIONS: VideoLocation[] = [
   {
     label: "부천아트벙커",
-    videoSrc: "https://cdn.geulda.kr/upload/video/artBunker.mp4",
+    videoSrc: `${CDN_VIDEO_BASE_URL}artBunker.mp4`,
     description: "옛 방공호를 개조한 독특한 문화예술 공간입니다.",
   },
   {
     label: "다솔관",
-    videoSrc: "https://cdn.geulda.kr/upload/video/dasol.mp4",
+    videoSrc: `${CDN_VIDEO_BASE_URL}dasol.mp4`,
     description: "학생들의 창의적인 활동과 휴식을 위한 복합 문화 공간입니다.",
   },
   // ... 나머지 항목도 동일하게 적용
 ];

더 나아가 환경 변수를 활용한 구성도 고려해볼 수 있습니다:

const CDN_VIDEO_BASE_URL = process.env.NEXT_PUBLIC_CDN_VIDEO_URL || "https://cdn.geulda.kr/upload/video/";
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 457bece and 70b9d7a.

📒 Files selected for processing (1)
  • src/shared/constants/main/videoLocations.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy
🔇 Additional comments (2)
src/shared/constants/main/videoLocations.ts (2)

6-51: 일관된 CDN URL 마이그레이션 적용을 확인했습니다.

모든 동영상 소스가 일관된 형식으로 CloudFront CDN URL로 변경되었습니다:

  • HTTPS 프로토콜 사용 ✓
  • 통일된 경로 구조 (/upload/video/) ✓
  • 설명적인 파일명 사용 ✓

이 변경으로 동영상 로딩 성능과 캐싱 효율이 개선될 것으로 기대됩니다.


6-51: CDN URL 검증 완료 - 모든 URL 정상 작동 확인됨

검증 결과 모든 10개 동영상 파일이 새로운 CDN에서 정상적으로 접근 가능합니다:

  • ✓ 모든 URL HTTP 200 상태 반환
  • ✓ Content-Type 헤더 정상 설정 (video/mp4)

단, Cache-Control 헤더가 비어있는 상태로, 이는 CDN 측 캐싱 최적화 설정 문제입니다. 이는 videoLocations.ts 파일의 코드 이슈가 아니며, CloudFront/CDN 구성 단계에서 별도로 검토가 필요합니다.

@skyblue1232 skyblue1232 changed the title Update: 영상 CDN 적용 및 S3 퍼블릭/CloudFront 설정 반영 Refactor&Update: 영상 CDN 적용 및 S3 퍼블릭/CloudFront 설정 반영 Nov 15, 2025
@skyblue1232 skyblue1232 changed the title Refactor&Update: 영상 CDN 적용 및 S3 퍼블릭/CloudFront 설정 반영 ♻️Refactor&Update: 영상 CDN 적용 및 S3 퍼블릭/CloudFront 설정 반영 Nov 15, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/pages/main/videoPlay/index.tsx (1)

52-63: Skip 버튼 type 속성 추가를 권장합니다.

Skip 버튼이 정상적으로 작동하지만, 명시적으로 type="button"을 추가하여 form 제출 등의 예상치 못한 동작을 방지하는 것이 좋습니다.

다음 diff를 적용하세요:

      <button
+       type="button"
        onClick={handleVideoEnd}
        className="
          mt-[0.4rem]
          text-mint-700
          text-body-lg
          underline
        "
        aria-label="영상 스킵하고 다음으로 이동"
      >
        Skip
      </button>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 70b9d7a and ddd4044.

📒 Files selected for processing (2)
  • src/pages/main/videoPlay/index.tsx (1 hunks)
  • src/shared/components/main/components/video/VideoPlayer.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy
🔇 Additional comments (2)
src/shared/components/main/components/video/VideoPlayer.tsx (2)

18-18: src.trim() 호출 시 빈 문자열 처리를 확인하세요.

src가 공백만 포함된 문자열인 경우 trim()이 빈 문자열을 반환하여 video 요소가 유효하지 않은 src를 가질 수 있습니다. 현재 15번 라인의 조건문이 {src ? ...}로 체크하지만, 공백 문자열은 truthy로 평가됩니다.

다음 개선을 고려하세요:

-          src={src.trim()}
+          src={src?.trim() || ''}

또는 조건문을 더 엄격하게 수정:

-      {src ? (
+      {src?.trim() ? (

19-23: 동영상 자동 재생 및 컨트롤 제거에 대한 접근성 고려 사항을 확인하세요.

현재 설정(autoPlay, muted, controls={false})은 기술적으로 올바르지만, 다음 접근성 및 UX 문제를 고려해야 합니다:

  1. 사용자 제어 부족: 네이티브 컨트롤이 비활성화되어 사용자가 일시정지, 탐색, 볼륨 조절을 할 수 없습니다.
  2. 자동 재생 정책: WCAG 2.1 가이드라인에서는 자동 재생되는 미디어에 대해 사용자가 일시정지/중지할 수 있는 메커니즘을 권장합니다.
  3. 음소거 상태: 영구적으로 음소거된 상태로 재생되며 사용자가 오디오를 활성화할 방법이 없습니다.

Skip 버튼이 추가되었지만, 일시정지/재생 기능도 고려해보세요.

접근성 요구사항을 충족하는지 확인하고, 필요시 다음 개선을 검토하세요:

  • 커스텀 재생/일시정지 버튼 추가
  • 음소거 해제 옵션 제공
  • 또는 controls를 true로 설정하고 사용자 제어 허용

@skyblue1232 skyblue1232 changed the title ♻️Refactor&Update: 영상 CDN 적용 및 S3 퍼블릭/CloudFront 설정 반영 ♻️ Refactor & Update: CloudFront–S3 기반 영상 CDN 적용 및 접근 정책 개선 Nov 15, 2025
@skyblue1232 skyblue1232 changed the title ♻️ Refactor & Update: CloudFront–S3 기반 영상 CDN 적용 및 접근 정책 개선 ♻️Refactor & Update: CloudFront–S3 기반 영상 CDN 적용 및 접근 정책 개선 Nov 15, 2025
@skyblue1232 skyblue1232 merged commit 04a4be1 into develop Nov 15, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comment 필요한 주석 추가 및 변경 refactor 프로덕션 코드 리팩토링업, QA 반영 update 뭐라 형용할 수 없는 업데이트

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor] CloudFront–S3 CDN 연동 및 UX/스트리밍 최적화

1 participant