
서버 비용 거의 0원으로 온라인 동영상 편집 서비스를 만들어 본 이야기 (Next.js + Remotion)
요약
서버 비용 부담을 최소화하기 위해 동영상 렌더링과 인코딩을 서버가 아닌 사용자의 브라우저(클라이언트 사이드)에서 수행하도록 설계한 ChatStoryStudio 개발 사례를 소개합니다. Next.js와 Remotion을 활용하여 인프라 비용을 거의 0원으로 유지하며 서비스를 운영하는 전략을 다룹니다.
핵심 포인트
- 서버 측 렌더링 대신 클라이언트 사이드 인코딩을 채택하여 인프라 비용 절감
- Remotion 라이브러리를 브라우저 환경에서 구동하는 기술적 접근
- IndexedDB를 활용한 로컬 데이터 저장으로 스토리지 비용 및 보안 리스크 해결
- 사용자 리소스를 활용한 무한 스케일링 가능한 서비스 구조 설계
개인 개발로 동영상 계열의 Web 서비스를 만들려고 하면, 가장 먼저 맞닥뜨리는 문제가 바로 **「서버 비용이 너무 비싸서 유지할 수 없다」**는 문제입니다. 렌더링(Rendering)이나 인코딩(Encoding)을 서버 측에서 수행하면, GPU 서버 비용 등으로 순식간에 지갑이 비게 됩니다.
이 과제를 회피하기 위해, 동영상 편집부터 인코딩(내보내기)까지를 **「100% 사용자의 브라우저(클라이언트 사이드)에서 수행한다」**는 설계를 채택하여, 서버 비용이 거의 0원에 동작하는 채팅 동영상 제작 서비스 **「ChatStoryStudio」**를 개인적으로 개발 및 공개했습니다.
서비스 URL: ChatStoryStudio -
특징: 로그인 불필요, 설치 불필요, 기본 무료로 브라우저에서 즉시 동영상 내보내기까지 완결
이 기사에서는 React로 동영상을 만드는 라이브러리인 「Remotion」을 브라우저 상에서 구동하는 방법과, 개발 중에 마주친 「일본어 글자 깨짐 및 표시 오류 버그」를 패치로 강행 돌파한 투박한 이야기, 그리고 서비스를 파산시키지 않기 위한 비용 설계에 대해 공유합니다.
통상적으로 온라인 동영상 편집 서비스를 만들려고 하면, 다음과 같은 구성이 일반적입니다.
| 단계 | 처리 내용 |
|---|---|
| 1. 편집 | 프론트엔드(Frontend)에서 사용자가 동영상을 편집한다 |
| 2. 전송 | 편집 데이터(JSON 등)를 백엔드(Backend)로 전송한다 |
| 3. 렌더링 | 백엔드에서 FFmpeg나 헤드리스 브라우저(Headless Browser, Puppeteer)를 기동하여, 서버 측에서 동영상을 렌더링한다 |
| 4. 저장·배포 | 렌더링 완료 후, S3 등의 스토리지(Storage)에 저장하여 사용자에게 다운로드하게 한다 |
이 구성은 안정적으로 동작하지만, 개인 개발 규모에서는 다음과 같은 단점이 너무나 큽니다.
| 단점 항목 | 상세·발생하는 과제 |
|---|---|
| 고액의 인프라 비용 | 동영상 1개를 출력하는 데 수십 초~수 분간 서버의 CPU/GPU를 점유합니다. 동시 내보내기 요청이 늘어나면 서버 스케일(Scale)이 필요해지며, 월간 비용이 급증합니다. |
| 사용자의 대기 시간 | 비용을 억제하기 위해 서버 수를 제한하면, 내보내기 「대기 큐(Queue)」가 발생하여 사용자 경험이 현저히 저하됩니다. |
| 「사용할수록 적자가 나는」 함정 | 무료 사용자가 동영상을 내보낼 때마다 인프라 비용을 개발자가 대신 부담하게 되어, 서비스가 화제가 되는 순간 서버 비용으로 파산하게 됩니다. |
그래서, **「동영상 인코딩 처리 자체를 사용자 자신의 PC 리소스(브라우저)에 통째로 맡긴다」**는 접근 방식을 취했습니다.
모든 것을 클라이언트 사이드에서 처리함으로써, 시스템 구성은 다음과 같이 극한까지 심플해집니다.
| 항목 | 접근 방식과 장점 |
|---|---|
| 호스팅 | 정적 파일 배포(Cloudflare Pages / Vercel 등)만 수행. 서버 비용은 거의 0원. |
| 데이터 저장 | 사용자가 편집한 타임라인이나 소재 데이터는 서버가 아닌 브라우저의 로컬(IndexedDB 등)에 저장. 정보 유출 리스크가 없으며, 스토리지 비용도 0원. |
| 렌더링 | 사용자의 브라우저가 Canvas 등의 기술을 이용하여, 그 자리에서 동영상 파일을 인코딩하여 로컬로 직접 다운로드. |
이를 통해 사용자가 얼마나 늘어나고 동영상이 많이 내보내지더라도, 개발자 측의 서버 비용은 거의 0원인 상태로 스케일링하는 것이 가능해집니다.
사용자의 PC 리소스를 사용하여 동영상을 내보내는 것 자체는, 예전부터 있던 로컬 동영상 편집 소프트웨어(Premiere Pro나 AviUtl 등)와 같습니다.
하지만 본 서비스가 접근 방식으로서 새로운 점은, **「설치가 필요 없는 Web 서비스이면서도, 로컬 내보내기 메커니즘을 채택했다」**는 점입니다.
기존의 로컬 앱: PC 설치나 OS별 동작 제한이 있어 도입 장벽이 높음. -
기존의 Web 서비스: 설치가 필요 없어 간편하지만, 동영상 내보내기는 서버에서 이루어지기 때문에 개발자의 인프라 부하가 크고, 무료 이용 제한이나 대기 시간이 발생하기 쉬움. -
최근 브라우저 기능의 향상으로 인해, 「접속하는 순간 바로 사용할 수 있고(Web의 간편함), 처리는 사용자의 PC에서 수행한다(로컬의 저비용·안전성)」는 하이브리드 설계가 특별한 소프트웨어 설치 없이도 실현 가능해졌습니다.
이 「브라우저 완결형 동영상 렌더링」을 실현하기 위한 핵심 라이브러리가 바로 Remotion입니다.
Remotion은 React 컴포넌트를 사용하여 동영상(MP4/WebM 등)을 제작할 수 있는 라이브러리입니다. HTML5 Canvas, CSS 애니메이션, Web Audio API를 조합하여 동영상 타임라인을 기술하며, 일반적으로는 CLI를 통해 서버 사이드(Server-side)에서 인코딩을 수행합니다.
Zenn이나 Qiita에서 Remotion 사례를 검색해 보면, 그 대부분이 "CLI를 통한 내보내기" 또는 "AWS Lambda 등의 서버 사이드에서 렌더링하는 구성"입니다.
하지만 본 서비스에서는 아직 일본어 기술 블로그 등에서도 실용 사례가 거의 소개되지 않은 @remotion/web-renderer라는 패키지를 채택하여, 서버 사이드 처리를 일절 거치지 않는 완전한 프론트엔드(Frontend) 완결형(브라우저 완결형) 렌더링을 실현하고 있습니다.
Remotion은 오랫동안 서버 사이드에서의 렌더링이 기본이었으나, 현재는 브라우저 상에서만 렌더링을 수행하는 패키지인 @remotion/web-renderer가 (Experimental(실험적) 기능으로서) 제공되고 있습니다.
이를 사용하면 서버를 거치지 않고 브라우저 내에서 동영상의 각 프레임을 HTML5 Canvas에 그리고, WebM 등의 포맷으로 인코딩하여 사용자에게 직접 출력할 수 있습니다.
import { renderMediaOnWeb } from "@remotion/web-renderer";
async function exportVideo() {
const baseRenderOptions = {
...
이 처리는 모두 사용자의 브라우저 프로세스에서 실행되므로, 서버 측에서 무거운 FFmpeg 프로세스를 실행할 필요가 전혀 없습니다. 또한, 하드웨어 인코딩(Hardware encoding) 실패에 대해 자동으로 소프트웨어 인코딩(Software encoding)으로 폴백(Fallback)시키는 로직을 넣어, 사용자 환경 의존성에 따른 에러 발생을 방지하도록 설계되었습니다.
@remotion/web-renderer를 통한 브라우저 렌더링은 매우 강력하지만, 영어권 라이브러리이기 때문에 일본어 환경에서는 몇 가지 문제에 부딪혔습니다.
Remotion 내부에서 텍스트를 자동으로 줄 바꿈(Line break)하기 위한 단어 분리 로직에서, 다음과 같이 영어(en)의 단어 단위(word) 세그멘테이션(Segmentation)이 하드코딩되어 있습니다.
// Remotion 내부 코드 (find-line-breaks)
const segmenter = new Intl.Segmenter("en", { granularity: "word" });
영어라면 "단어의 구분(공백 등)"으로 개행 위치를 계산하면 문제가 없습니다. 하지만 일본어는 단어가 공백으로 구분되어 있지 않기 때문에, 영어용 세그멘터를 통과하면 글자의 구분이나 텍스트 너비 계산이 어긋나게 됩니다. 결과적으로 개행은 되지만 일부 글자가 깨지거나, 여러 줄의 텍스트가 왠지 모르게 같은 좌표에 겹쳐서 표시되는 매우 부자연스러운 렌더링 오류가 발생했습니다.
이를 회피하기 위해 patch-package를 사용하여 node_modules 내의 해당 로직을 다음과 같이 수정하는 패치를 적용했습니다.
diff --git a/node_modules/@remotion/web-renderer/dist/esm/index.mjs b/node_modules/@remotion/web-renderer/dist/esm/index.mjs
index a72b622..b663cc1 100644
--- a/node_modules/@remotion/web-renderer/dist/esm/index.mjs
...
ja-JP의 granularity: "grapheme"(Grapheme 단위, 즉 음절/자소 단위)로 지정함으로써, 단어 단위가 아닌 "글자(Glyph) 단위"로 세그멘테이션되도록 하여 일본어 말풍선 내에서도 깔끔하게 자동 줄 바꿈이 이루어지도록 했습니다.
이러한 일본어 대응이 필요한 이유는 @remotion/web-renderer가 현재 시점에서 아직 Experimental(실험적 기능) 상태이기 때문입니다. 향후 정식 출시될 때는 타 언어의 줄 바꿈 규칙이나 Intl.Segmenter의 커스텀 옵션이 본사 측에서 고려 및 정비되어, 패치 없이도 깔끔하게 동작하도록 개선될 가능성이 높다고 생각됩니다.
@remotion/web-renderer를 사용하여 동영상 생성을 시작할 때, 대화 데이터(inputProps)에 일본어 멀티바이트 문자가 단 한 글자라도 포함되어 있으면, 브라우저 표준 btoa 함수의 사양 제한(Latin1 범위 외 문자 에러)으로 인해 인코딩 예외가 발생하며 프로세스가 즉시 크래시(Crash)됩니다.
이를 방지하기 위해 실제 ChatStoryStudio에서는 대화 데이터를 직접 전달하는 대신, Unicode(멀티바이트 문자)에 대응하는 독자적인 Base64 직렬화(Serialization) 처리를 거쳐 전달하고 있습니다.
송신 측 (Web 클라이언트): encodePropsToBase64를 통해 멀티바이트 문자 대응 Base64로 변환하여 inputProps에 설정.
수신 측 (Remotion 컴포넌트): decodePropsFromBase64로 디코딩하여 데이터를 복원하고 렌더링.
"서버 비용이 거의 0원"이라고는 하지만, 실제 서비스(SaaS)로서 본 프로덕션 환경에서 운영하기 위해서는 완전히 비용이 0인 것은 아닙니다. 실제로 다음과 같은 비용이 발생하고 있습니다.
Web 서버 및 API 호스팅 비용 (월 수백 엔~): API나 백엔드 처리에 Cloudflare Workers 유료 플랜을 채택하고 있습니다. 요청 수에 따른 종량제 방식이지만, 초기 단계에서는 월 약 5달러의 최소한의 인프라 유지비로 억제하고 있습니다.
음성 합성 (TTS) API 비용: 캐릭터에게 풍부한 감정이 담긴 목소리를 설정하기 위해 외부의 고품질 TTS API를 호출합니다.
AI 시나리오 로드 (대본 자동 생성) API 비용: 텍스트 대본으로부터 타임라인을 자동으로 파싱(Parsing) 및 생성하기 위한 API 비용.
이러한 외부 API 호출 비용에 대해, 본 서비스에서는 다음과 같은 비즈니스 및 시스템 설계로 균형을 맞추고 있습니다.
기본 기능의 완전 무료화: "채팅 영상을 직접 구성하여 브라우저에서 내보내기"라는 핵심 기능은 외부 API를 전혀 소비하지 않으므로(서버 비용이 전혀 발생하지 않음), 제한 없이 무료로 개방하고 있습니다.
무료 범위 제한 및 저단가 모델 채택을 통한 비용 컨트롤: 음성 합성 (TTS)이나 AI 시나리오 생성과 같은 부가 가치 기능은 무료 (Free) 플랜 사용자에게도 일정 횟수의 "무료 체험 범위"를 제공합니다. 이것이 가능한 이유는 **"API 단가가 매우 저렴한 모델 (Gemini TTS나 비용 효율이 뛰어난 경량 LLM 모델)"**을 엄선하여 채택했기 때문입니다.
개인 개발자가 허용할 수 있는 수준의 횟수 제한(Quota)을 설정함으로써, 설령 무료 사용자가 급증하더라도 개발자의 부담액이 파산하지 않는 안전한 상한선 내에 머물도록 설계했습니다.
헤비 유저는 유료 구독 (Pro 플랜)으로 회수: 체험 범위를 넘어 이러한 기능들을 일상적으로 사용하고자 하는 사용자에게는 유료 구독(Stripe 연동)으로의 전환을 요구하여, API 이용 비용을 상쇄하고 흑자로 전환하는 구조로 만들었습니다.
로컬 내보내기의 간편함에 따른 인프라 비교: 백엔드 측에서 무거운 동영상 서버를 계속 구동했을 때 발생하는 "월 수만 엔~의 고정 인프라 비용"에 비하면, 종량제로 부과되는 TTS나 LLM API 비용은 훨씬 경미하며, 구독료 범위 내에서 충분히 흑자 전환 및 커버가 가능하다는 계산이 나옵니다.
서버 비용을 극한까지 억제할 수 있는 반면, 고부하 처리를 사용자의 브라우저에 맡기는 것에는 다음과 같은 명확한 단점과 한계가 존재합니다.
사용자 단말의 처리 부하 및 스펙 요구: 인코딩 중에는 사용자의 CPU/GPU 리소스를 풀(Full)로 소비하기 때문에, 일시적으로 PC 동작이 무거워지거나 팬 회전, 배터리 급격한 소모가 발생할 수 있습니다. 또한 저사양 PC에서는 내보내기에 상당한 시간이 소요됩니다.
브라우저 메모리 제한으로 인한 크래시: 특히 스마트폰 (iOS 등)이나 메모리가 부족한 환경에서는 긴 영상이나 무거운 에셋을 포함한 영상을 내보내려 할 때, 브라우저의 메모리 상한(제한)에 도달하여 탭이 크래시될 수 있습니다. 본 서비스에서 "PC 환경을 강력히 권장"하는 이유도 바로 이것입니다.
환경 의존성에 따른 디버깅의 어려움:
서버 사이드 처리라면 에러 로그를 일원 관리하여 원인을 추적할 수 있지만, 클라이언트의 브라우저 환경(설치된 확장 기능의 간섭, 하드웨어와 브라우저의 호환성 등)에서 발생하는 개별 에러는 개발자 측에서 특정하거나 디버깅하기가 매우 어렵습니다.
지금까지 '동영상 편집·생성 서비스'는 개인 개발자에게 인프라 유지비와 구현의 복잡성 때문에 쉽게 손대기 어려운 영역이었습니다.
하지만, Next.js + Remotion (web-renderer) 을 조합함으로써, 이러한 트레이드오프 (Trade-off)를 허용할 수 있는 유스케이스라면, **'얼마나 많이 사용되어도 서버 비용이 거의 늘어나지 않는 동영상 편집 서비스'**를 개인으로서 충분히 구축하는 것이 가능해집니다.
현시점에서는 아직 실험적인 기능이기 때문에 일본어 대응 (Intl.Segmenter 패치 적용 및 인코딩 대책 등)과 같은 번거로운 회피책이 필요하지만, 클라이언트 사이드 (Client-side)로 처리를 위임하는 것 (로컬 퍼스트 (Local-first))은 개인 개발의 가능성을 크게 넓히는 강력한 접근 방식입니다.
서버 비용 적자에 떨며 개인 개발을 하는 것은 정신 건강에 좋지 않으므로, 영상 계열의 프로덕트를 만들려고 하시는 분들은 클라이언트 사이드 렌더링 (Client-side Rendering)을 하나의 돌파구로 검토해 보신다면 행복해질 수 있을지도 모릅니다.
필자에 대하여
'개인 x AI'로 싸우는 고독한 개인 개발자입니다. 1인 비즈니스나 프리랜서 엔지니어의 생생한 실태, 그 궤적과 과정에서 얻은 지견을 가감 없이 발신하고 있습니다.
기사가 마음에 드셨다면, '좋아요'나 '팔로우'를 해주시면 기뻐서 눈물을 흘릴 것 같습니다.
진행 중인 프로젝트나 기사의 상세 버전 등에 관심이 있으신 분은 꼭 yukapero.com 을 방문해 주세요.
SNS에서도 적극적으로 활동하고 있으니, 꼭 연결합시다! @yukapero_com
X: @yukapero_com
Web: yukapero.com
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기