기본 콘텐츠로 건너뛰기

추천 가젯

리액트 + 비트(Vite)로 모바일 청첩장 만들기 — 2편

모바일 청첩장 시리즈 2편 · R2 갤러리 & Firebase 방명록 Cloudflare R2 · Functions Firebase Firestore 클라우드플레어 R2로 갤러리 저장하고, Firebase로 방명록 달기 안녕하세요, 병민입니다 🙌 1편에서 전체 흐름을 잡았고, 이번엔 사진 업로드/보관 과 방명록 을 연결합니다. 서버는 따로 없고 Cloudflare Pages 를 쓰고 있으니, Pages Functions (= 워커)로 R2에 사전서명 URL을 만들어주고, 프론트에서 그 URL로 바로 업로드하는 구조예요. 방명록은 Firebase DB로 간단·안전하게! 전체 그림 프론트(React) → /api/r2/upload 로 업로드용 URL 요청 → R2에 파일 PUT 프론트(React) → /api/r2/list 로 목록 요청 → 갤러리 렌더 프론트(React) → Firebase SDK로 방명록 작성/조회 1) R2 버킷 & Pages Functions 준비 Cloudflare 대시보드 > R2 > Create bucket (예: wedding-gallery ) 버킷 > Settings > CORS 에서 사이트 도메인 허용(예: https://*.pages.dev , 커스텀 도메인) Pages 프로젝트 > Settings > Functions 에서 R2 바인딩 추가: ...

리액트 + 비트(Vite)로 모바일 청첩장 만들기 — 1편

모바일 청첩장 시리즈 1편 · 기획/스택/배포

리액트 + 비트(Vite)로 모바일 청첩장 만들기 — 1편

안녕하세요, 이번에 결혼 준비를 하면서 여자친구와 같이 모바일 청첩장을 만들고 있어요. 여자친구가 디자인을 해서 전달해주면 제가 개발을 진행하고 있어요. 이 글은 구현기 1편으로, 전체 흐름과 스택, 배포 구성까지 “부담 없이” 훑어봅니다. (코드는 여러 버전 테스트 중!)

이 글에서 보는 것
  1. 왜 SPA 모바일 청첩장인가?
  2. 기본 스택 & 폴더 구조
  3. 라우팅 선택: HashRouter가 편한 이유
  4. Cloudflare Pages로 자동 배포
  5. 현재 진행 중인 UI 버전들(테스트 기록)

1) 왜 SPA 모바일 청첩장인가?

모바일 청첩장은 핵심이 명확해요. 가볍고 빠르고 끊김이 없어야 하고, 사진/지도/일정이 터치에 친화적이어야 합니다. 그래서 React + Vite로 싱글 페이지 앱(SPA)을 구성했고, 정적 호스팅(CDN)인 Cloudflare Pages에 올려 GitHub 푸시 → 자동 배포까지 한 번에 묶었습니다.

UX 팁 · 이미지 WebP, loading="lazy" 기본 · 큰 터치 타깃 · BGM은 “사용자 탭 후” 재생(모바일 정책)

2) 기본 스택 & 폴더 구조

서버는 따로 두지 않았고, 정적 빌드 결과물(dist/)만 올립니다. 현재 의존성은 아래와 같아요.

package.json(요약)
{
  "name": "wedding-invitation",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "lucide-react": "^0.548.0",
    "react": "^19.2.0",
    "react-dom": "^19.2.0",
    "react-router-dom": "^7.8.2",
    "swiper": "^12.0.3"
  },
  "devDependencies": {
    "@eslint/js": "^9.33.0",
    "@tailwindcss/postcss": "^4.1.16",
    "@types/react": "^19.2.2",
    "@types/react-dom": "^19.2.2",
    "@vitejs/plugin-react": "^4.7.0",
    "autoprefixer": "^10.4.21",
    "eslint": "^9.33.0",
    "eslint-plugin-react-hooks": "^5.2.0",
    "eslint-plugin-react-refresh": "^0.4.20",
    "globals": "^16.3.0",
    "postcss": "^8.5.6",
    "tailwindcss": "^4.1.16",
    "typescript": "~5.8.3",
    "typescript-eslint": "^8.39.1",
    "vite": "^5.4.19"
  }
}

폴더 구조(예시)

/src
  /components    # 공용 컴포넌트(갤러리, 버튼 등)
  /pages         # Home, Invitation, Venue...
  app.css        # Tailwind v4: @import "tailwindcss";
  main.tsx
index.html
Tailwind v4@import "tailwindcss"; 한 줄로 심플하게 시작할 수 있어요. 전역 토큰(배경색 등)은 :root에 CSS 변수로 두면 협업(혜민 디자인 피드백)이 편합니다.

3) 라우팅 선택: HashRouter가 편한 이유

정적 호스팅에서 서브 경로 새로고침 404를 피하려면 HashRouter가 가장 간단합니다. URL이 #를 포함하지만, 배포 쪽 설정을 신경 덜 써도 되어 빠르게 공유/검증하기 좋아요. (BrowserRouter는 Cloudflare Pages의 SPA 리라이트 설정이 필요합니다.)

옵션장점주의사항
HashRouter설정 없이 즉시 동작, 404 걱정 없음URL에 # 포함
BrowserRouterURL 깔끔리라이트 설정 필요(SPA)

4) Cloudflare Pages로 자동 배포

  1. GitHub 저장소 연결 → 브랜치 선택(main 권장)
  2. Framework preset: Vite (자동 감지되면 그대로)
  3. Build command: npm run build · Output: dist
  4. 푸시할 때마다 자동 빌드/배포

5) 현재 진행 중인 UI 버전들(테스트 기록)

지금은 느낌이 다른 테마를 여러 버전으로 병렬 테스트하고 있어요. 각 버전은 공통적으로 D-Day/갤러리/방명록/하단 액션바를 유지합니다.

Modern · 화이트+로즈 포인트, 핏 단정한 카드/버튼, 대칭 스토리 섹션 – 깔끔/모던 지향, 결혼식 정보 가독성 높음
Sage · 종이질감+세이지 그린, 잉크톤 아이콘, 차분한 톤 – “청첩장 종이 감성”을 모바일에 옮긴 콘셉트
OurFirstLetter · 파스텔톤, BGM 미니플레이어, 갤러리 업로드/비공개, 방명록 – 로컬 우선 기능(관리자 PIN/길게누르기)
WeddingInvite · 시리즈 공통요소를 정리한 기준안 – 반응형/접근성/로컬 데이터 구조 정돈

보너스) 결혼 과정, 이 글도 참고해요

준비 과정 전반을 한눈에 보고 싶다면, 아래 블로그를 확인해주세요!

© 병만 · 디자인 파트너 혜밍 · Cloudflare Pages 배포 도움: 직장 동료님🙏

댓글

가장 많이 본 글

Icons by Flaticon