streamObject + zod 스키마"로 LLM 출력을 처음부터 끝까지 타입이 있는 JSON으로 강제하고, 그 JSON을 그대로 E2B 샌드박스(격리된 마이크로VM)에 파일로 써넣어 실행한다. Python 데이터분석, Next.js, Vue, Streamlit, Gradio 다섯 개 스택과 10개 넘는 LLM 제공자를 갈아 끼울 수 있다.
e2b-dev/fragments · 라이선스 Apache License 2.0 · package.json 버전 0.1.0(사실상 고정, 실사용 서비스는 fragments.e2b.dev) · Next.js 14.2 App Router · Vercel AI SDK v3 · e2b SDK 2.8 / @e2b/code-interpreter 1.0 · TypeScript · 소스 73개 파일 약 5,500줄 · 최신 커밋 dafbf91, 2026-07-28(Renovate 자동 의존성 업데이트) · 이 문서는 저장소를 직접 얕은 클론(clone --depth 1)해 소스코드를 읽고 작성)
Fragments는 "채팅으로 앱을 만들고 그 자리에서 실행까지 보는" 웹앱이다. 사용자가 "할 일 목록 앱 만들어줘" 같은 문장을 입력하면, 선택된 LLM(Claude·GPT·Gemini 등)이 자유로운 텍스트가 아니라 미리 정해진 필드를 가진 JSON(제목·설명·코드·실행 포트 등)을 스트리밍으로 채워 넣는다. 그 JSON이 완성되는 즉시 서버가 E2B 샌드박스라는 진짜 리눅스 컴퓨터를 하나 만들어, 거기에 코드를 파일로 써넣고 실행해 화면(웹앱이면 접속 URL, 데이터분석 코드면 실행 결과)을 사용자에게 돌려준다.
README가 스스로 밝히듯 이 프로젝트는 Anthropic Claude Artifacts, Vercel v0, GPT Engineer의 오픈소스 버전을 표방한다. 다만 이들과 달리 소스 전체가 공개돼 있어 구조를 그대로 읽을 수 있고, Apache-2.0 라이선스라 조건 없이 포크·수정·재배포가 가능하다.
일반 챗봇은 "이렇게 코드를 짜세요"라고 말로만 알려준다. 사용자가 그 말을 복사해 자기 컴퓨터에 붙여넣고, 필요한 프로그램을 깔고, 직접 실행해봐야 결과를 알 수 있었다.
Fragments는 그 사이 단계를 없앤다. AI가 "레시피"(코드·설치 명령·실행 포트)를 정해진 양식(zod 스키마)대로 받아 적자마자, 바로 옆에 있는 깨끗한 주방(E2B 샌드박스)에서 그 레시피대로 직접 요리해 접시(실행 결과 화면)를 내온다. 사용자는 주방에 들어갈 필요가 없다.
2022~2023년 챗봇들은 코드를 텍스트로만 뱉었다. 그런데 v0·Claude Artifacts·bolt.new·Lovable 같은 제품들이 잇달아 "프롬프트 → 구조화 출력 → 즉시 실행/미리보기"라는 3단 패턴으로 옮겨가면서, 이 패턴 자체가 AI 코딩 도구의 표준 UX가 됐다. Fragments가 주목받는 이유는 이 표준 패턴을 상용 서비스 수준으로 완결된 형태로, 그것도 통째로 오픈소스로 공개한 몇 안 되는 참고 구현이기 때문이다.
Vercel AI SDK의 streamObject처럼 LLM 출력을 zod 스키마로 강제 스트리밍하는 기법이 실무 표준으로 자리잡으면서, 그 실전 예제를 찾는 개발자에게 Fragments의 lib/schema.ts·app/api/chat/route.ts는 그대로 베껴 쓸 수 있는 살아있는 교과서가 됐다.
AI가 생성한 임의의 코드를 서버에서 그냥 실행하면 보안 사고로 직결된다. Fragments는 E2B의 격리된 마이크로VM 샌드박스에서만 실행해 이 문제를 원천 차단한다. "AI 생성 코드를 안전하게 실행하려면 무엇을 써야 하나"라는 질문에 실물 답을 준다.
OpenAI·Anthropic·Google(AI Studio/Vertex)·Mistral·Groq·Fireworks·Together AI·xAI·DeepSeek·Ollama(로컬)까지 골라 쓸 수 있고, 생성 대상도 Python 데이터분석·Next.js·Vue·Streamlit·Gradio 다섯 스택 중에서 고를 수 있다. 특정 회사에 종속되지 않고 내 API 키, 내 서버로 똑같은 경험을 재현할 수 있다는 점이 셀프호스팅 수요를 끌어당긴다.
Claude Artifacts·v0·bolt.new는 각 회사의 클라우드·모델에 묶인 폐쇄형 제품이다. Fragments는 그 UX를 그대로 재현하면서도 모델·인프라를 자유롭게 고를 수 있는 오픈소스 레퍼런스라는 자리를 차지한다. "이런 앱을 어떻게 만드는지"를 배우려는 개발자와, 자기 팀 전용 사내 도구로 포크해 쓰려는 회사 양쪽에서 참고된다.
Fragments가 실제로 없애주는 마찰은 크게 세 가지다.
일반 챗봇에서 코드를 받으면 사용자가 직접 파일을 만들고, 의존성을 설치하고, 실행해야 결과를 알 수 있다. Fragments는 /api/sandbox가 그 전 과정(패키지 설치 → 파일 작성 → 실행/URL 발급)을 자동으로 처리해, LLM 응답이 끝나는 순간 바로 눈으로 보이는 결과를 내놓는다.
서버가 직접 사용자 프롬프트로 생성된 코드를 실행하면 서버 자체가 뚫릴 수 있다. Fragments는 매 요청마다 E2B의 격리된 샌드박스(마이크로VM)를 새로 만들어 그 안에서만 실행하고, 10분 타임아웃까지 걸어둔다(sandboxTimeout = 10 * 60 * 1000). 메인 서버와 실행 환경이 물리적으로 분리된다.
lib/models.ts의 providerConfigs가 제공자별 클라이언트 생성 로직을 한곳에 모아두고, lib/templates.ts가 생성 대상 스택을 한곳에 모아둔다. 새 모델이나 새 스택을 추가하는 지점이 코드베이스 안에서 명확히 하나로 정해져 있어, 포크해서 회사 내부 모델이나 내부 전용 스택으로 바꿔 끼우기 쉽다.
Fragments의 심장은 "LLM 호출과 코드 실행을 완전히 분리된 두 개의 API 라우트로 나눈다"는 설계다. 채팅 UI는 자신이 지금 스트리밍 중인 JSON이 아직 완성되지 않았다는 것도, 완성되자마자 실행 요청이 나간다는 것도 모두 하나의 리액트 훅(useObject) 하나로 처리한다.
이 흐름에서 중요한 건 "/api/chat은 코드를 만들기만 하고, /api/sandbox는 실행만 한다"는 역할 분리다. LLM 호출 비용(시간이 오래 걸릴 수 있음, maxDuration = 300)과 샌드박스 실행 비용(maxDuration = 60)이 서로 다른 타임아웃 정책을 갖는 것도 이 분리 때문에 가능하다. 코드 편집을 위한 /api/morph-chat 라우트가 별도로 하나 더 있는데, 이는 5번 섹션에서 자세히 다룬다.
streamObject로 이를 스트리밍하며 강제한다.lib/schema.ts의 fragmentSchema
모든 것의 출발점은 zod로 정의된 fragmentSchema다. LLM은 이 스키마의 필드를 순서대로 채우도록 강제된다. 실제 필드는 이렇다.
export const fragmentSchema = z.object({
commentary: z.string(), // 지금 뭘, 왜 만드는지 설명(사용자에게 실시간으로 보임)
template: z.string(), // 어떤 스택 템플릿을 쓸지(예: "nextjs-developer")
title: z.string(), // 프래그먼트 짧은 제목(최대 3단어)
description: z.string(), // 한 문장 설명
additional_dependencies: z.array(z.string()), // 템플릿에 없는 추가 패키지
has_additional_dependencies: z.boolean(),
install_dependencies_command: z.string(), // 예: "npm i axios"
port: z.number().nullable(), // 열려야 할 포트, 없으면 null
file_path: z.string(), // 코드를 쓸 파일 경로
code: z.string(), // 실제 코드 — 이 필드가 실행될 원본
})
이 스키마 하나가 system 프롬프트 · 스트리밍 파싱 · 프론트엔드 상태 · 샌드박스 실행 네 곳 전부에서 재사용된다. zod 스키마 하나를 서버 검증과 타입 정의 양쪽에 쓰는 전형적인 "스키마가 곧 진실원(source of truth)" 패턴이다.
lib/prompt.ts · lib/templates.ts
lib/prompt.ts의 toPrompt(template) 함수가 system 프롬프트를 만든다. 이 함수는 짧다 — "너는 실수하지 않는 숙련된 엔지니어다, 프래그먼트를 생성해라, 의존성 파일은 건드리지 마라"는 몇 줄의 규칙 뒤에, templatesToPrompt(template)가 만들어낸 사용 가능한 템플릿 목록을 붙인다. lib/templates.ts는 각 템플릿의 이름·설치된 라이브러리·기본 파일·포트를 하드코딩된 JS 객체로 갖고 있고, 이 함수는 그걸 번호 매긴 텍스트 목록으로 바꿔 LLM에게 "이 중에서 골라 쓰라"고 알려준다.
app/api/chat/route.ts
실제 라우트 핸들러는 streamObject({ model, schema, system: toPrompt(template), messages, maxRetries: 0 })를 호출하고 stream.toTextStreamResponse()로 응답한다. maxRetries: 0이 눈에 띄는데, LLM 호출이 실패해도 서버가 자동 재시도하지 않는다 — 실패는 그대로 lib/api-errors.ts의 handleAPIError()로 넘어가 사용자에게 "레이트리밋"·"과부하"·"인증 실패" 중 어떤 상황인지 구분된 메시지로 전달된다.
app/page.tsx의 useObject
브라우저 쪽은 Vercel AI SDK의 experimental_useObject as useObject 훅을 쓴다. fragment 상태의 타입은 DeepPartial<FragmentSchema> — 스트리밍 도중에는 필드 일부만 채워진 "불완전한" 객체라는 뜻이다. 그래서 코드가 화면에 타이핑되듯 한 줄씩 채워지는 것처럼 보이는데, 사실은 이미 도착한 JSON 조각을 그때그때 리렌더하는 것뿐이다. 스트림이 끝나면 onFinish 콜백이 완성된 fragment를 들고 /api/sandbox로 새 요청을 쏜다.
app/api/sandbox/route.ts
가장 핵심적인 부분이다. Sandbox.create(fragment.template, { metadata, timeoutMs: 10 * 60 * 1000 })로 10분짜리 격리 샌드박스를 하나 만든 뒤:
fragment.has_additional_dependencies가 참이면 sbx.commands.run(fragment.install_dependencies_command)로 패키지를 설치한다.sbx.files.write(fragment.file_path, fragment.code)로 생성된 코드를 샌드박스 파일시스템에 그대로 써넣는다.code-interpreter-v1(순수 Python 실행)이면 sbx.runCode(fragment.code)로 즉시 실행해 stdout/stderr/그래프 결과를 반환한다.sbx.getHost(fragment.port || 80)로 https://…e2b.app 형태의 접속 URL을 만들어 반환한다. 이미 그 스택의 개발 서버가 템플릿 안에서 자동 실행 중이라, URL만 넘겨주면 된다.템플릿마다 이미 시동이 걸린 채 대기 중인 자동차(예: Next.js 개발 서버가 이미 떠 있는 컨테이너)라고 보면 된다. Fragments는 그 차에 새로 생긴 부품(생성된 코드 파일)만 갈아 끼우고, "이 주소로 오면 차가 있다"(getHost)고 알려줄 뿐, 매번 차를 처음부터 조립하지 않는다. 그래서 프롬프트 한 번에 몇 초 만에 미리보기가 뜬다.
sandbox-templates/
sandbox-templates/nextjs-developer/template.ts 같은 파일은 앱이 실행되는 동안 쓰이는 코드가 아니라, E2B CLI로 미리 빌드해 E2B 클라우드에 올려두는 도커 이미지 정의다. 예를 들어 Next.js 템플릿은:
export const template = Template()
.fromNodeImage('24-slim')
.aptInstall('curl')
.setWorkdir('/home/user/nextjs-app')
.runCmd('npx create-next-app@14.2.33 . --ts --tailwind …')
.runCmd('npx shadcn@2.1.7 init -d')
.runCmd('npx shadcn@2.1.7 add --all')
.setWorkdir('/home/user')
.setStartCmd('npx next --turbo', waitForPort(3000))
즉 Next.js·shadcn/ui가 미리 깔린 이미지를 만들고, setStartCmd로 "이 명령을 실행하고 3000번 포트가 열릴 때까지 기다려라"고 정의해둔다. 이렇게 만든 템플릿의 id가 lib/templates.ts의 키(nextjs-developer 등)와 정확히 일치해야 Sandbox.create(fragment.template, …)가 올바른 이미지를 찾아낸다 — 두 파일이 서로 다른 저장소 위치에 있으면서도 문자열 하나로 묶여 있는 셈이다.
/api/morph-chat, lib/morph.ts)
프래그먼트가 이미 만들어진 뒤 "버튼 색을 파란색으로 바꿔줘"라고 후속 요청을 하면, 매번 전체 코드를 처음부터 다시 생성하는 건 느리고 비싸다. Fragments는 Morph Apply 모델(morph-v3-large, OpenAI 호환 엔드포인트)을 토글로 켤 수 있게 해뒀다. 흐름은:
app/api/morph-chat/route.ts가 generateObject로 morphEditSchema(변경 설명 + // ... existing code ... 표기가 섞인 부분 diff)를 먼저 뽑는다.lib/morph.ts의 applyPatch()가 그 diff와 원본 코드를 Morph의 morph-v3-large 모델에 함께 넘겨 병합된 전체 코드를 받아온다.FragmentSchema 모양 그대로 감싸 반환해, /api/sandbox 실행 흐름과 그대로 이어진다.
MORPH_API_KEY가 없으면 이 기능은 "설정에서 키를 넣거나 환경변수를 설정하라"는 에러를 던지고 끝난다 — 기본 채팅/생성 흐름과는 완전히 독립된 선택적 부가 기능이다.
lib/ratelimit.ts
사용자가 자기 API 키를 넣지 않은 경우에만(!config.apiKey) 레이트리밋이 걸린다. @upstash/ratelimit의 슬라이딩 윈도(기본 1일 10회, RATE_LIMIT_MAX_REQUESTS/RATE_LIMIT_WINDOW 환경변수로 조정)를 @vercel/kv 저장소에 얹어 IP(x-forwarded-for) 단위로 센다. KV_REST_API_URL·KV_REST_API_TOKEN 환경변수가 없으면 이 함수는 그냥 아무것도 하지 않고 통과시킨다 — 로컬 개발 환경에서는 사실상 무제한이라는 뜻이다.
lib/auth.ts · Supabase
Supabase 인증으로 로그인하면 getUserTeam()이 users_teams 테이블에서 기본 팀을 조회한다. 팀에 속한 사용자가 샌드박스를 만들면 X-Supabase-Team·X-Supabase-Token 헤더가 Sandbox.create 호출에 실려 E2B 쪽에 팀 단위 과금·접근 제어 정보를 전달한다. Supabase 환경변수가 없으면 useAuth()는 demo@e2b.dev라는 가짜 세션 객체를 만들어 로그인 없이도 데모가 굴러가게 한다.
app/actions/publish.ts · middleware.ts
실행 중인 샌드박스 URL은 그 자체로는 길고 임시적이다. publish() 서버 액션은 URL이 *.e2b.app 도메인인지 검증하고, Sandbox.setTimeout()으로 만료 시간을 최대 24시간까지 늘린 뒤, nanoid로 짧은 id를 만들어 KV에 fragment:{id} → 실제 URL로 저장한다. 이후 /s/{id}로 접속하면 middleware.ts가 KV를 조회해 실제 샌드박스 URL로 302 리다이렉트한다. KV 환경변수가 없으면 짧은 URL 기능 자체가 조용히 꺼지고 원본 긴 URL이 그대로 반환된다.
이 저장소에는 모델 가중치나 추론 엔진이 없다. 실제 코드 생성은 외부 LLM API 호출(lib/models.ts)이, 실제 코드 실행은 별도 서비스인 E2B 클라우드 샌드박스(e2b/@e2b/code-interpreter SDK로 호출)가 담당한다.
따라서 이 레포에서 배울 것은 "AI 모델 자체"가 아니라 구조화 출력 파이프라인 설계, 외부 실행 인프라 오케스트레이션, 스트리밍 UI 상태 관리, 선택적 부가기능(레이트리밋·인증·짧은 URL)을 환경변수로 켜고 끄는 패턴이다.
| 영역 | 사용 기술 · 버전 (package.json 기준) |
|---|---|
| 프레임워크 | Next.js 14.2(App Router, Server Actions) + React 18.3 + TypeScript 5.5 |
| AI 오케스트레이션 | Vercel AI SDK ai v3(streamObject·generateObject·experimental_useObject) + zod 3(스키마) |
| LLM 제공자 SDK | @ai-sdk/openai·@ai-sdk/anthropic·@ai-sdk/google·@ai-sdk/google-vertex·@ai-sdk/mistral·@ai-sdk/fireworks·ollama-ai-provider(로컬) |
| 코드 실행 | e2b 2.8 + @e2b/code-interpreter 1.0 — 샌드박스 생성·파일쓰기·명령실행·Jupyter 셀 실행 |
| UI | shadcn/ui + Radix Primitives(Dialog·DropdownMenu·Select·Tabs·Toast 등) + Tailwind CSS 3 + lucide-react 아이콘 + prismjs(코드 하이라이트) |
| 인증 · 데이터 | Supabase(@supabase/supabase-js) — 로그인·팀 관리 |
| 레이트리밋 · 저장소 | @upstash/ratelimit + @vercel/kv — 요청 제한 및 짧은 URL 매핑 저장 |
| 코드 편집(선택) | Morph(morph-v3-large, OpenAI 호환 API) — diff 기반 코드 병합 |
| 분석 | PostHog(posthog-js) + @vercel/analytics |
lib/models.json에는 11개 제공자, 50개 넘는 모델 항목이 등록돼 있다(OpenAI GPT-5 계열, Anthropic Claude Opus/Sonnet/Haiku, Google Gemini(AI Studio + Vertex 이중 경로), Mistral/Magistral, Groq, Fireworks, Together AI, xAI Grok, DeepSeek, Ollama 로컬 모델). 각 항목은 id·provider·providerId·multiModal 필드를 가지며, providerId가 lib/models.ts의 providerConfigs 키와 매칭돼 실제 클라이언트가 만들어진다.
ai). Fragments는 이 라이브러리를 통해 어떤 모델이든 같은 코드로 부를 수 있다.fragmentSchema가 대표적 예다.Fragments 자체(웹앱)를 로컬에서 띄우는 것과, 새 스택 템플릿을 만드는 것은 완전히 다른 두 개의 설치 절차다. 대부분은 전자만 하면 된다.
git clone https://github.com/e2b-dev/fragments.gitcd fragments && npm i — Node.js(최신 LTS 권장)와 npm이 필요하다..env.local 파일을 만들고 최소 두 개 값을 채운다: E2B_API_KEY(e2b.dev에서 발급)와, 쓰고 싶은 LLM 제공자 중 최소 하나의 API 키(예: ANTHROPIC_API_KEY 또는 OPENAI_API_KEY).npm run dev(개발 서버, Turbo 모드) 또는 npm run build && npm run start(프로덕션 빌드).| 기능 | 필요한 환경변수 |
|---|---|
| 레이트리밋 · 짧은 URL | KV_REST_API_URL / KV_REST_API_TOKEN(Vercel/Upstash KV) |
| 로그인 · 팀 | SUPABASE_URL / SUPABASE_ANON_KEY |
| 분석 | NEXT_PUBLIC_POSTHOG_KEY / NEXT_PUBLIC_POSTHOG_HOST |
| Morph 코드 편집 | MORPH_API_KEY(또는 UI 설정에서 직접 입력) |
| 레이트리밋 세부 조정 | RATE_LIMIT_MAX_REQUESTS(기본 10) / RATE_LIMIT_WINDOW(기본 1d) |
sandbox-templates/ 아래 새 폴더를 만들고 E2B CLI(e2b template init → Dockerfile 수정 → e2b template build --name …)로 E2B 클라우드에 이미지를 미리 올린 다음, 그 템플릿 id를 lib/templates.ts에 손으로 추가해야 한다. 이건 npm 의존성 설치와 무관한 별도의 빌드타임 작업이다.
Supabase·KV·PostHog·Morph는 전부 없어도 무방하다. 로그인은 데모 세션으로 대체되고, 레이트리밋과 짧은 URL은 조용히 꺼진다. 진짜로 필요한 건 E2B_API_KEY와 LLM 키 하나뿐이다.
채팅창(components/chat-input.tsx)에 "할 일 목록 앱 만들어줘" 같은 문장을 쓴다. 상단 ChatPicker에서 템플릿을 "auto"(LLM이 알아서 고름)로 두거나 Next.js·Vue·Streamlit 등으로 직접 고정할 수 있고, ChatSettings에서 모델(기본값 claude-sonnet-4-20250514)과 temperature 같은 파라미터를 조정한다.
useObject가 /api/chat으로 요청을 보내고, 응답이 도착하는 대로 commentary(지금 뭘 하는지 설명) → title → code 순으로 필드가 차오른다. components/fragment-code.tsx가 이 부분 코드를 문법 강조와 함께 그대로 보여줘, 마치 AI가 눈앞에서 타이핑하는 것처럼 보인다.
스트리밍이 끝나면 onFinish가 즉시 /api/sandbox로 완성된 fragment를 넘긴다. 사용자는 버튼을 누를 필요가 없다 — isPreviewLoading 상태가 켜지며 "실행 중" 표시가 뜨고, 결과가 오면 components/preview.tsx가 웹앱이면 fragment-web.tsx(iframe 미리보기), Python 실행이면 fragment-interpreter.tsx(stdout·차트 결과)를 보여준다.
components/deploy-dialog.tsx에서 발행하면 publish() 서버 액션이 샌드박스 만료 시간을 늘리고 /s/{짧은id} 링크를 만들어준다. 이 링크는 최대 24시간 후 자동 만료된다 — 영구 배포가 아니라 임시 공유용이라는 점을 기억해야 한다.
이미 만들어진 앱을 계속 다듬을 때 "Morph Apply" 토글을 켜면, 다음 메시지부터는 /api/chat이 아니라 /api/morph-chat이 불려 전체 재생성 없이 필요한 부분만 diff로 patch된다. 토글을 끄면 다시 전체 재생성 방식으로 돌아온다.
이 저장소는 문서(README)와 실제 코드 사이에 실제로 대조 확인한 불일치가 여러 군데 있다. 문서만 보고 작업하면 헤매기 쉬운 지점들이다.
README의 "Adding custom personas" 절 7번 항목은 "Open lib/templates.json in your code editor"라고 안내하지만, 저장소에는 lib/templates.json이라는 파일이 존재하지 않는다. 실제로 템플릿 목록은 lib/templates.ts 안에 하드코딩된 TypeScript 객체(const templates = {...})로 정의돼 있다. JSON 파일을 찾다가는 시간을 버린다 — 편집할 곳은 .ts 파일이다.
README의 "Adding custom LLM models" 절은 링크 글자로는 "lib/models.json"이라 써놓고 실제 href는 lib/models.ts를 가리킨다. 헷갈리기 쉽지만 실제로는 두 파일이 공존한다 — lib/models.json은 화면에 보여줄 모델 목록 데이터(id·이름·제공자), lib/models.ts는 그 providerId를 받아 실제 SDK 클라이언트를 만드는 로직이다. 모델을 추가하려면 models.json에 항목을 넣고, 새 제공자 자체를 추가하려면 models.ts의 providerConfigs를 고쳐야 한다.
getDefaultMode 함수는 현재 소스에 없다README는 "getDefaultMode 함수에서 구조화 출력 모드를 조정하라"고 안내하지만, 실제 lib/models.ts 소스를 열어보면 그런 함수가 존재하지 않는다. 과거 버전의 흔적이 문서에만 남은 사례로 보인다 — 실제로 구조화 출력 방식은 Vercel AI SDK의 streamObject/generateObject 기본 동작에 맡겨져 있다.
app/api/sandbox/route.ts에는 Array.isArray(fragment.code)를 검사해 여러 파일을 순회하며 쓰는 분기가 있다. 하지만 lib/schema.ts의 fragmentSchema에서 code 필드는 z.string()으로 정의돼 있어 배열이 될 수 없다 — 즉 이 분기는 죽은 코드(dead code)이며, 실제로는 항상 else 분기(sbx.files.write(fragment.file_path, fragment.code))만 실행된다. 다중 파일 생성 기능이 실험되다 만 흔적으로 보인다.
README 기능 목록에는 8개 제공자(OpenAI·Anthropic·Google AI·Mistral·Groq·Fireworks·Together AI·Ollama)만 나열돼 있지만, 실제 lib/models.ts의 providerConfigs에는 Google Vertex AI·xAI·DeepSeek까지 11개가 이미 구현돼 있다. 코드가 문서보다 앞서 나간 흔한 사례다.
레이트리밋(lib/ratelimit.ts)·인증(lib/auth.ts)·짧은 URL(middleware.ts)은 전부 관련 환경변수가 없으면 에러를 던지지 않고 그냥 기능을 비활성화한 채로 넘어간다. "왜 로그인이 안 되지?"가 아니라 애초에 로그인 없이도 데모(demo@e2b.dev 가짜 세션)로 굴러가도록 설계됐다는 점을 알면 로컬 개발이 훨씬 편하다.
.github/workflows/에는 Renovate(의존성 자동 업데이트 봇) 설정을 검증하는 워크플로 하나만 있고, 단위 테스트나 E2E 테스트 파이프라인은 확인되지 않는다. 이 레포는 "엄격하게 테스트된 라이브러리"가 아니라 실사용 서비스(fragments.e2b.dev)로 직접 운영하며 다듬어지는 레퍼런스 애플리케이션에 가깝다는 점을 감안해야 한다.
| 프로젝트 | Fragments와의 차이 |
|---|---|
| Vercel v0 | Vercel의 폐쇄형 SaaS. 모델·인프라가 Vercel에 고정돼 있고 소스가 공개되지 않는다. Fragments는 모델·호스팅을 전부 사용자가 고른다는 점이 다르다. |
| bolt.new (StackBlitz) | 브라우저 안에서 도는 WebContainer(가상 Node.js 환경)로 실행한다 — 서버 인프라가 필요 없는 대신 진짜 리눅스 격리는 아니다. Fragments는 E2B의 실제 마이크로VM 샌드박스에서 실행해, 임의의 시스템 패키지 설치나 Python 등 비-Node 스택도 자연스럽게 다룬다. |
| dyad | 로컬 데스크탑에서 도는 오픈소스 AI 앱 빌더로, 자기 컴퓨터의 파일시스템에 직접 코드를 생성한다. Fragments는 클라우드 샌드박스에서 실행하는 웹 서비스형 구조라, 로컬 환경을 더럽히지 않고 누구나 브라우저로 접근할 수 있다. |
| OpenUI | 주로 UI 컴포넌트/디자인 생성과 미리보기에 초점을 맞춘 프로젝트. Fragments는 UI뿐 아니라 Python 데이터분석 · 백엔드 포함 풀스택 앱 실행까지 다룬다는 점에서 범위가 더 넓다. |
| Anthropic Claude Artifacts | Claude.ai 안에서만 동작하는 폐쇄형 기능. Fragments는 애초에 이를 오픈소스로 재현하겠다고 README에서 명시한 프로젝트다. |
Apache-2.0 라이선스로 조건 없이 포크·수정·재배포가 가능하고, LLM 제공자·실행 스택·인증/레이트리밋 인프라를 전부 자기 것으로 바꿔 끼울 수 있다. 대신 그만큼 직접 운영 부담(E2B 사용료, 서버 배포, 보안 설정)을 사용자가 진다는 트레이드오프가 있다.
Fragments는 "프롬프트 한 줄이 눈에 보이는 실행 결과로 바뀌는" 경험을 어떻게 만드는지를 처음부터 끝까지 실제 소스로 보여주는 프로젝트다. 핵심은 세 겹이다 — ① zod 스키마로 LLM 출력을 강제하는 구조화 스트리밍(streamObject), ② 그 결과를 격리된 클라우드 샌드박스(E2B)에서 안전하게 실행하는 오케스트레이션, ③ 레이트리밋·인증·짧은 URL 같은 부가 기능을 환경변수 하나로 켜고 끄는 선택적 설계.
이런 사람에게 특히 도움이 된다.
streamObject/generateObject)을 실전 코드로 배우고 싶은 개발자 — lib/schema.ts·app/api/chat/route.ts가 그대로 참고 예제가 된다.반대로, 이미 완성된 제품을 안정적으로 그냥 쓰고 싶다면 공식 데모(fragments.e2b.dev)나 v0·Claude Artifacts 같은 관리형 서비스가 더 맞을 수 있다. 이 레포는 구조를 이해하고 직접 운영할 사람을 위한 참고 구현이다.