Skip to content

Ensil-dev/QuokkaConverter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

272 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

QuokkaConverter πŸš€

μ„œλ²„λ¦¬μŠ€ 기반의 ν΄λΌμ΄μ–ΈνŠΈ μ‚¬μ΄λ“œ 파일 λ³€ν™˜ ν”Œλž«νΌ

Live Demo TypeScript React Next.js WebAssembly Jotai


πŸ“‹ ν”„λ‘œμ νŠΈ κ°œμš”

문제 상황: κΈ°μ‘΄ 파일 λ³€ν™˜ μ„œλΉ„μŠ€λ“€μ˜ 높은 μ„œλ²„ λΉ„μš©κ³Ό λ³΄μ•ˆ 취약점
ν•΄κ²° λ°©μ•ˆ: WebAssembly 기반 ν΄λΌμ΄μ–ΈνŠΈ λ³€ν™˜ + μ„œλ²„λ¦¬μŠ€ μ•„ν‚€ν…μ²˜
λΉ„μ¦ˆλ‹ˆμŠ€ μž„νŒ©νŠΈ: μ„œλ²„ 운영 λΉ„μš© 100% 절감, λ¬΄μ œν•œ ν™•μž₯μ„± 확보

🎯 핡심 μ„±κ³Ό

  • 기술적 ν˜μ‹ : ffmpeg.wasm을 ν™œμš©ν•œ μ„œλ²„λ¦¬μŠ€ ν™˜κ²½μ—μ„œμ˜ λ―Έλ””μ–΄ 처리 κ΅¬ν˜„
  • λ³΄μ•ˆ κ°•ν™”: Next.js 15 미듀웨어 기반 인증 μ‹œμŠ€ν…œμœΌλ‘œ 무단 μ ‘κ·Ό 차단
  • μ„±λŠ₯ μ΅œμ ν™”: ν΄λΌμ΄μ–ΈνŠΈ μ‚¬μ΄λ“œ 처리둜 μ„œλ²„ λΆ€ν•˜ μ œλ‘œν™”
  • μ‚¬μš©μž κ²½ν—˜: 직관적인 UI/UX둜 λ³€ν™˜ κ³Όμ •μ˜ λ³΅μž‘μ„± 좔상화

πŸ›  기술적 도전과 ν•΄κ²°

1. μ„œλ²„λ¦¬μŠ€ ν™˜κ²½μ—μ„œμ˜ λ―Έλ””μ–΄ 처리

문제: Vercel λ“± μ„œλ²„λ¦¬μŠ€ ν™˜κ²½μ—μ„œ FFmpeg λ°”μ΄λ„ˆλ¦¬ μ‹€ν–‰ λΆˆκ°€
ν•΄κ²°:

  • WebAssembly 기반 @ffmpeg/ffmpeg λ„μž…
  • ν΄λΌμ΄μ–ΈνŠΈ μ‚¬μ΄λ“œ λ³€ν™˜μœΌλ‘œ μ„œλ²„ μ˜μ‘΄μ„± 제거
  • SharedArrayBuffer ν™œμš©ν•œ κ³ μ„±λŠ₯ λ©”λͺ¨λ¦¬ 처리
// 핡심 κ΅¬ν˜„: WASM 기반 λ―Έλ””μ–΄ λ³€ν™˜
const convertVideo = async (inputFile: File, options: ConvertOptions) => {
  const ffmpeg = new FFmpeg();
  await ffmpeg.load();

  ffmpeg.writeFile('input.mp4', await fetchFile(inputFile));
  await ffmpeg.exec(['-i', 'input.mp4', ...buildArgs(options), 'output.webm']);

  const data = await ffmpeg.readFile('output.webm');
  return new Uint8Array(data);
};

2. Next.js 15 인증 미듀웨어 κ΅¬ν˜„

문제: λ³΅μž‘ν•œ λΌμš°νŒ… κ΅¬μ‘°μ—μ„œμ˜ 인증 처리
ν•΄κ²°:

  • JWT 토큰 기반 미듀웨어 κ΅¬ν˜„
  • NextAuth.js v5와 ν˜Έν™˜λ˜λŠ” λ³΄μ•ˆ 계측
  • 파일 μœ„μΉ˜ 이슈 ν•΄κ²° (src/middleware.js)
// 핡심 κ΅¬ν˜„: 인증 미듀웨어
export async function middleware(request) {
  if (request.nextUrl.pathname.startsWith('/convert')) {
    const token = await getToken({ req: request, secret: process.env.NEXTAUTH_SECRET });
    if (!token) {
      return NextResponse.redirect(new URL('/', request.url));
    }
  }
  return NextResponse.next();
}

3. λŒ€μš©λŸ‰ 파일 처리 μ΅œμ ν™”

문제: λΈŒλΌμš°μ € λ©”λͺ¨λ¦¬ μ œν•œκ³Ό λ³€ν™˜ μ„±λŠ₯
ν•΄κ²°:

  • Streaming 기반 파일 처리
  • Web Workersλ₯Ό ν†΅ν•œ 메인 μŠ€λ ˆλ“œ 차단 λ°©μ§€
  • μ§„ν–‰λ₯  좔적과 λ©”λͺ¨λ¦¬ 관리

πŸ— μ•„ν‚€ν…μ²˜ 섀계

μ‹œμŠ€ν…œ μ•„ν‚€ν…μ²˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Client Side   β”‚    β”‚   Serverless    β”‚    β”‚   External      β”‚
β”‚                 β”‚    β”‚                 β”‚    β”‚                 β”‚
β”‚ β€’ React 19      │───▢│ β€’ Next.js 15    │───▢│ β€’ Google OAuth  β”‚
β”‚ β€’ ffmpeg.wasm   β”‚    β”‚ β€’ NextAuth.js   β”‚    β”‚ β€’ Vercel Edge   β”‚
β”‚ β€’ TypeScript    β”‚    β”‚ β€’ Edge Runtime  β”‚    β”‚ β€’ CloudFront    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

데이터 ν”Œλ‘œμš°

  1. 인증: Google OAuth β†’ JWT 토큰 λ°œκΈ‰
  2. μ—…λ‘œλ“œ: ν΄λΌμ΄μ–ΈνŠΈ λ©”λͺ¨λ¦¬ 직접 λ‘œλ”©
  3. λ³€ν™˜: WebAssembly μ—”μ§„ 처리
  4. λ‹€μš΄λ‘œλ“œ: Blob URL 직접 제곡

πŸ’Ό λΉ„μ¦ˆλ‹ˆμŠ€ μž„νŒ©νŠΈ

운영 λΉ„μš© μ΅œμ ν™”

  • μ„œλ²„ λΉ„μš©: $0/μ›” (κΈ°μ‘΄ λŒ€λΉ„ 100% 절감)
  • CDN λΉ„μš©: 정적 λ¦¬μ†ŒμŠ€λ§Œ μ‚¬μš©μœΌλ‘œ μ΅œμ†Œν™”
  • ν™•μž₯μ„±: μ‚¬μš©μž 증가에 λ”°λ₯Έ μΆ”κ°€ λΉ„μš© μ—†μŒ

기술 뢀채 관리

  • ν…ŒμŠ€νŠΈ 컀버리지: Jest + Testing Library λ„μž…
  • μ½”λ“œ ν’ˆμ§ˆ: ESLint + Prettier μžλ™ν™”
  • νƒ€μž… μ•ˆμ „μ„±: TypeScript strict mode

λ³΄μ•ˆ κ°•ν™”

  • 인증: OAuth 2.0 ν‘œμ€€ μ€€μˆ˜
  • 인가: 이메일 ν™”μ΄νŠΈλ¦¬μŠ€νŠΈ 기반 μ ‘κ·Ό μ œμ–΄
  • 데이터 보호: ν΄λΌμ΄μ–ΈνŠΈ 처리둜 μ„œλ²„ μ €μž₯ μ—†μŒ

πŸ”§ 기술 μŠ€νƒ

Core Technologies

  • Frontend: Next.js 15.3.4, React 19.0.0, TypeScript 5
  • Authentication: NextAuth.js 5.0.0-beta.29 (Google OAuth)
  • Media Processing: @ffmpeg/ffmpeg 0.12.15, @ffmpeg/util 0.12.2
  • PDF Processing: pdf-lib 1.17.1

Development & Testing

  • Testing: Jest 29.7.0, Testing Library
  • Code Quality: ESLint 9, Prettier 3.6.2
  • Bundling: Next.js built-in Webpack 5
  • State Management: Jotai 2.8.3

Infrastructure & Deployment

  • Hosting: Vercel (Edge Functions + Static Generation)
  • CDN: CloudFront for WebAssembly files
  • Analytics: Vercel Analytics integration

πŸ“Š μ„±λŠ₯ μ§€ν‘œ

λ³€ν™˜ μ„±λŠ₯

  • λΉ„λ””μ˜€: 1080p/60fps β†’ 720p/30fps (90초 μ˜μƒ μ•½ 45초)
  • μ˜€λ””μ˜€: MP3 320kbps β†’ 128kbps (5MB 파일 μ•½ 8초)
  • 이미지: 4K PNG β†’ WebP (20MB β†’ 2MB, 3초)
  • PDF: 10νŽ˜μ΄μ§€ λ¬Έμ„œ 병합 (2초)

μ‚¬μš©μž κ²½ν—˜

  • 첫 λ‘œλ”©: < 2초 (Static Generation)
  • λ³€ν™˜ μ‹œμž‘: < 1초 (WASM λ‘œλ”© μΊμ‹œ)
  • λͺ¨λ°”일 μ΅œμ ν™”: ν„°μΉ˜ μΈν„°νŽ˜μ΄μŠ€, λ°˜μ‘ν˜• λ””μžμΈ

πŸš€ μ£Όμš” κΈ°λŠ₯

πŸ“Ή λΉ„λ””μ˜€ λ³€ν™˜

  • 지원 포맷: MP4, AVI, MOV, MKV, WebM
  • 해상도 μ‘°μ •: 480p ~ 1080p
  • FPS μ œμ–΄: 24 ~ 60fps
  • ν’ˆμ§ˆ/λΉ„νŠΈλ ˆμ΄νŠΈ μ΅œμ ν™”

🎡 μ˜€λ””μ˜€ λ³€ν™˜

  • 지원 포맷: MP3, WAV, FLAC, AAC, OGG
  • μƒ˜ν”Œλ ˆμ΄νŠΈ: 22kHz ~ 48kHz
  • 채널: λͺ¨λ…Έ/μŠ€ν…Œλ ˆμ˜€ 선택

πŸ–ΌοΈ 이미지 처리

  • 포맷 λ³€ν™˜: JPG, PNG, WebP, TIFF
  • GIF 생성: 닀쀑 이미지 ν•©μ„±
  • 해상도/ν’ˆμ§ˆ μ‘°μ •

πŸ“‘ PDF 처리

  • 이미지 β†’ PDF λ³€ν™˜
  • λ¬Έμ„œ 병합/λΆ„ν• 
  • 메타데이터 관리

πŸ“± UX/UI νŠΉν™” κΈ°λŠ₯

λͺ¨λ°”일 μ΅œμ ν™”

  • λ’€λ‘œκ°€κΈ° λ°©μ§€: λ³€ν™˜ 쀑 μ‹€μˆ˜ μ’…λ£Œ λ°©μ§€
  • 인앱 λΈŒλΌμš°μ € 감지: KakaoTalk/LINEμ—μ„œ μ™ΈλΆ€ λΈŒλΌμš°μ € μœ λ„
  • ν„°μΉ˜ μ΅œμ ν™”: λ“œλž˜κ·Έ μ•€ λ“œλ‘­, μŠ€μ™€μ΄ν”„ 제슀처

μ‚¬μš©μž κ°€μ΄λ“œ

  • μ‹€μ‹œκ°„ 미리보기: λ³€ν™˜ μ˜΅μ…˜ 적용 κ²°κ³Ό 예츑
  • μ§„ν–‰λ₯  ν‘œμ‹œ: λ³€ν™˜ 단계별 μƒνƒœ ν‘œμ‹œ
  • μ—λŸ¬ 핸듀링: μ‚¬μš©μž μΉœν™”μ  였λ₯˜ λ©”μ‹œμ§€

πŸ”’ λ³΄μ•ˆ 및 인증

OAuth 2.0 κ΅¬ν˜„

// λ³΄μ•ˆ κ°•ν™”λœ NextAuth μ„€μ •
export const { auth, signIn, signOut } = NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
  ],
  callbacks: {
    async signIn({ user }) {
      const allowedEmails = process.env.ALLOWED_EMAILS?.split(',') || [];
      return allowedEmails.includes(user.email!);
    },
  },
});

미듀웨어 λ³΄μ•ˆ 계측

  • JWT 토큰 검증
  • λΌμš°νŠΈλ³„ μ ‘κ·Ό μ œμ–΄
  • CSRF λ°©μ§€

πŸ“¦ μ„€μΉ˜ 및 μ‹€ν–‰

Quick Start

git clone https://github.com/your-repo/QuokkaConverter.git
cd QuokkaConverter/next-converter
npm install
cp env.example .env.local
npm run dev

ν™˜κ²½λ³€μˆ˜ μ„€μ •

NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-nextauth-secret
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
ALLOWED_EMAILS=admin@example.com,user@example.com

배포 (Vercel)

vercel --prod
# ν™˜κ²½λ³€μˆ˜λŠ” Vercel Dashboardμ—μ„œ μ„€μ •

πŸ§ͺ ν…ŒμŠ€νŠΈ 및 ν’ˆμ§ˆ 관리

ν…ŒμŠ€νŠΈ 컀버리지

npm run test              # λ‹¨μœ„ ν…ŒμŠ€νŠΈ
npm run test:coverage     # 컀버리지 리포트
npm run lint              # μ½”λ“œ ν’ˆμ§ˆ 검사
npm run build             # ν”„λ‘œλ•μ…˜ λΉŒλ“œ 검증

μ£Όμš” ν…ŒμŠ€νŠΈ μ‹œλ‚˜λ¦¬μ˜€

  • 파일 μ—…λ‘œλ“œ/λ³€ν™˜ ν”Œλ‘œμš°
  • 인증/인가 둜직
  • μ—λŸ¬ 핸듀링
  • 크둜슀 λΈŒλΌμš°μ € ν˜Έν™˜μ„±

πŸ“ˆ ν–₯ν›„ κ°œμ„  κ³„νš

기술적 ν™•μž₯

  • Web Workers 병렬 처리 μ΅œμ ν™”
  • WebCodecs API ν™œμš©ν•œ ν•˜λ“œμ›¨μ–΄ 가속

λΉ„μ¦ˆλ‹ˆμŠ€ ν™•μž₯

  • μ‚¬μš©λŸ‰ 뢄석 λŒ€μ‹œλ³΄λ“œ
  • API μ„œλΉ„μŠ€ 제곡
  • μ—”ν„°ν”„λΌμ΄μ¦ˆ 버전 개발

Portfolio Repository: GitHub
Live Demo: quokkaconverter.vercel.app
Contact: dlwjd164@gmail.com

About

🐻 μ›ν•˜λŠ”λŒ€λ‘œ 파일 포맷을 λ³€ν™˜ν•  수 μžˆλŠ” μ„œλ²„λ¦¬μŠ€ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors