REPO DEEP DIVE · 2026-07-29 · E2B-DEV/FRAGMENTS · 프롬프트 한 줄을 살아있는 앱으로

e2b-dev/fragments 딥다이브
"AI가 코드를 짜는 걸 눈으로 본다" 오픈소스 Claude Artifacts

Fragments는 채팅창에 프롬프트를 치면 LLM이 구조화된 JSON으로 코드를 만들고, 그 코드를 진짜 클라우드 컴퓨터(E2B 샌드박스)에서 즉시 실행해 결과 화면을 그대로 보여주는 오픈소스 웹앱이다. Anthropic Claude Artifacts, Vercel v0, GPT Engineer와 같은 부류지만, 소스 전체가 Apache-2.0로 공개돼 있어 그대로 뜯어보고 내 서버에 셀프호스팅할 수 있다.

기술적으로는 "Vercel AI SDK의 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)해 소스코드를 읽고 작성)
목차
  1. 한 줄 정체
  2. 왜 지금 뜨는가
  3. 무엇을 해결하나
  4. 전체 구조
  5. 핵심 설계 · 동작 원리
  6. 기술 스택 · 의존성
  7. 설치 · 요구사항
  8. 실제 사용 흐름
  9. 함정 · 오해 방지
  10. 대안 비교
  11. 정리 · 누가 쓰면 좋은가

1한 줄 정체

"프롬프트 → 구조화된 JSON 코드 → 클라우드 샌드박스 실행 → 미리보기"까지 한 번에

Fragments는 "채팅으로 앱을 만들고 그 자리에서 실행까지 보는" 웹앱이다. 사용자가 "할 일 목록 앱 만들어줘" 같은 문장을 입력하면, 선택된 LLM(Claude·GPT·Gemini 등)이 자유로운 텍스트가 아니라 미리 정해진 필드를 가진 JSON(제목·설명·코드·실행 포트 등)을 스트리밍으로 채워 넣는다. 그 JSON이 완성되는 즉시 서버가 E2B 샌드박스라는 진짜 리눅스 컴퓨터를 하나 만들어, 거기에 코드를 파일로 써넣고 실행해 화면(웹앱이면 접속 URL, 데이터분석 코드면 실행 결과)을 사용자에게 돌려준다.

README가 스스로 밝히듯 이 프로젝트는 Anthropic Claude Artifacts, Vercel v0, GPT Engineer의 오픈소스 버전을 표방한다. 다만 이들과 달리 소스 전체가 공개돼 있어 구조를 그대로 읽을 수 있고, Apache-2.0 라이선스라 조건 없이 포크·수정·재배포가 가능하다.

한 줄 비유

"레시피대로 요리해주는 로봇 셰프"가 아니라 "레시피(JSON)를 정확히 받아 적고, 그걸 들고 바로 옆 주방(샌드박스)에서 요리까지 해주는" 시스템

일반 챗봇은 "이렇게 코드를 짜세요"라고 말로만 알려준다. 사용자가 그 말을 복사해 자기 컴퓨터에 붙여넣고, 필요한 프로그램을 깔고, 직접 실행해봐야 결과를 알 수 있었다.

Fragments는 그 사이 단계를 없앤다. AI가 "레시피"(코드·설치 명령·실행 포트)를 정해진 양식(zod 스키마)대로 받아 적자마자, 바로 옆에 있는 깨끗한 주방(E2B 샌드박스)에서 그 레시피대로 직접 요리해 접시(실행 결과 화면)를 내온다. 사용자는 주방에 들어갈 필요가 없다.

2왜 지금 뜨는가

"AI가 짠 코드는 눈으로 확인돼야 믿는다" 시대의 표준 3단 패턴을 통째로 공개

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 생성 코드를 안전하게 실행하려면 무엇을 써야 하나"라는 질문에 실물 답을 준다.

③ 벤더 자유 — 10개 넘는 LLM 제공자, 5개 스택

OpenAI·Anthropic·Google(AI Studio/Vertex)·Mistral·Groq·Fireworks·Together AI·xAI·DeepSeek·Ollama(로컬)까지 골라 쓸 수 있고, 생성 대상도 Python 데이터분석·Next.js·Vue·Streamlit·Gradio 다섯 스택 중에서 고를 수 있다. 특정 회사에 종속되지 않고 내 API 키, 내 서버로 똑같은 경험을 재현할 수 있다는 점이 셀프호스팅 수요를 끌어당긴다.

경쟁 지형에서의 위치
폐쇄형 SaaS와 오픈소스 참고 구현 사이

Claude Artifacts·v0·bolt.new는 각 회사의 클라우드·모델에 묶인 폐쇄형 제품이다. Fragments는 그 UX를 그대로 재현하면서도 모델·인프라를 자유롭게 고를 수 있는 오픈소스 레퍼런스라는 자리를 차지한다. "이런 앱을 어떻게 만드는지"를 배우려는 개발자와, 자기 팀 전용 사내 도구로 포크해 쓰려는 회사 양쪽에서 참고된다.

3무엇을 해결하나

"AI 코드는 눈으로 봐야 믿는다" · "실행 환경 안전하게 분리" · "모델·스택 자유"

Fragments가 실제로 없애주는 마찰은 크게 세 가지다.

문제 ① — "코드를 받았는데 돌려볼 방법이 없다"

일반 챗봇에서 코드를 받으면 사용자가 직접 파일을 만들고, 의존성을 설치하고, 실행해야 결과를 알 수 있다. Fragments는 /api/sandbox가 그 전 과정(패키지 설치 → 파일 작성 → 실행/URL 발급)을 자동으로 처리해, LLM 응답이 끝나는 순간 바로 눈으로 보이는 결과를 내놓는다.

문제 ② — "AI가 짠 임의 코드를 실행하면 위험하다"

서버가 직접 사용자 프롬프트로 생성된 코드를 실행하면 서버 자체가 뚫릴 수 있다. Fragments는 매 요청마다 E2B의 격리된 샌드박스(마이크로VM)를 새로 만들어 그 안에서만 실행하고, 10분 타임아웃까지 걸어둔다(sandboxTimeout = 10 * 60 * 1000). 메인 서버와 실행 환경이 물리적으로 분리된다.

문제 ③ — "특정 모델·스택에 갇힌다"

lib/models.tsproviderConfigs가 제공자별 클라이언트 생성 로직을 한곳에 모아두고, lib/templates.ts가 생성 대상 스택을 한곳에 모아둔다. 새 모델이나 새 스택을 추가하는 지점이 코드베이스 안에서 명확히 하나로 정해져 있어, 포크해서 회사 내부 모델이나 내부 전용 스택으로 바꿔 끼우기 쉽다.

4전체 구조

"브라우저(React) → /api/chat(구조화 스트리밍) → /api/sandbox(E2B 실행)" 3단 파이프라인

Fragments의 심장은 "LLM 호출과 코드 실행을 완전히 분리된 두 개의 API 라우트로 나눈다"는 설계다. 채팅 UI는 자신이 지금 스트리밍 중인 JSON이 아직 완성되지 않았다는 것도, 완성되자마자 실행 요청이 나간다는 것도 모두 하나의 리액트 훅(useObject) 하나로 처리한다.

┌────────────────────────────────────────────────────────────────┐ │ FRAGMENTS 3단 파이프라인 │ └────────────────────────────────────────────────────────────────┘ [1] 브라우저 (app/page.tsx, React 18 + Next.js App Router) const { object, submit } = useObject({ api: '/api/chat', schema }) · 스트리밍 중인 부분 JSON(DeepPartial<FragmentSchema>)을 그대로 실시간 렌더(코드가 한 줄씩 채워지는 것처럼 보임) │ fetch POST (messages, template, model, config) ▼ [2] /api/chat (app/api/chat/route.ts, Edge/Node 함수) streamObject({ model, schema: fragmentSchema, system: toPrompt(template) }) · Vercel AI SDK가 LLM 응답을 zod 스키마 형태로 강제 스트리밍 · 응답이 끝나면 브라우저의 onFinish 콜백이 실행됨 │ onFinish → fetch POST { fragment, userID, teamID } ▼ [3] /api/sandbox (app/api/sandbox/route.ts) Sandbox.create(fragment.template, { timeoutMs: 10분 }) · 필요하면 fragment.install_dependencies_command 실행 · sbx.files.write(fragment.file_path, fragment.code) · code-interpreter 템플릿이면 sbx.runCode() 실행 결과 반환 · 그 외 템플릿이면 sbx.getHost(port)로 접속 URL 반환 │ ▼ [4] E2B 클라우드 샌드박스 — 격리된 리눅스 마이크로VM에서 실제 실행

이 흐름에서 중요한 건 "/api/chat은 코드를 만들기만 하고, /api/sandbox는 실행만 한다"는 역할 분리다. LLM 호출 비용(시간이 오래 걸릴 수 있음, maxDuration = 300)과 샌드박스 실행 비용(maxDuration = 60)이 서로 다른 타임아웃 정책을 갖는 것도 이 분리 때문에 가능하다. 코드 편집을 위한 /api/morph-chat 라우트가 별도로 하나 더 있는데, 이는 5번 섹션에서 자세히 다룬다.

용어
구조화 출력 (structured output)
LLM이 자유로운 문장 대신, 미리 정의된 필드(JSON 스키마)를 정확히 채워서 답하도록 강제하는 방식. Fragments는 zod로 스키마를 정의하고 Vercel AI SDK의 streamObject로 이를 스트리밍하며 강제한다.
용어
샌드박스 (sandbox)
본체 서버와 분리된, 깨끗하고 격리된 임시 실행 환경. 여기서 무슨 일이 벌어져도(코드가 잘못 짜여도, 무한루프가 돌아도) 본체 서버는 안전하다. E2B는 이를 마이크로VM으로 구현한다.

5핵심 설계 · 동작 원리

zod 스키마 → streamObject → 부분 렌더 → E2B 샌드박스 실행 → Morph 편집 → 레이트리밋/인증/짧은 URL

① 스키마가 진실원 — lib/schema.tsfragmentSchema

모든 것의 출발점은 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.tstoPrompt(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.tshandleAPIError()로 넘어가 사용자에게 "레이트리밋"·"과부하"·"인증 실패" 중 어떤 상황인지 구분된 메시지로 전달된다.

④ 프론트엔드의 부분 렌더 — app/page.tsxuseObject

브라우저 쪽은 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분짜리 격리 샌드박스를 하나 만든 뒤:

  1. fragment.has_additional_dependencies가 참이면 sbx.commands.run(fragment.install_dependencies_command)로 패키지를 설치한다.
  2. sbx.files.write(fragment.file_path, fragment.code)로 생성된 코드를 샌드박스 파일시스템에 그대로 써넣는다.
  3. 템플릿이 code-interpreter-v1(순수 Python 실행)이면 sbx.runCode(fragment.code)로 즉시 실행해 stdout/stderr/그래프 결과를 반환한다.
  4. 그 외(Next.js·Vue·Streamlit·Gradio 같은 웹 서버형 템플릿)면 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번 포트가 열릴 때까지 기다려라"고 정의해둔다. 이렇게 만든 템플릿의 idlib/templates.ts의 키(nextjs-developer 등)와 정확히 일치해야 Sandbox.create(fragment.template, …)가 올바른 이미지를 찾아낸다 — 두 파일이 서로 다른 저장소 위치에 있으면서도 문자열 하나로 묶여 있는 셈이다.

⑦ 코드 편집은 재생성이 아니라 diff — Morph Apply (/api/morph-chat, lib/morph.ts)

프래그먼트가 이미 만들어진 뒤 "버튼 색을 파란색으로 바꿔줘"라고 후속 요청을 하면, 매번 전체 코드를 처음부터 다시 생성하는 건 느리고 비싸다. Fragments는 Morph Apply 모델(morph-v3-large, OpenAI 호환 엔드포인트)을 토글로 켤 수 있게 해뒀다. 흐름은:

  1. app/api/morph-chat/route.tsgenerateObjectmorphEditSchema(변경 설명 + // ... existing code ... 표기가 섞인 부분 diff)를 먼저 뽑는다.
  2. lib/morph.tsapplyPatch()가 그 diff와 원본 코드를 Morph의 morph-v3-large 모델에 함께 넘겨 병합된 전체 코드를 받아온다.
  3. 결과를 기존 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라는 가짜 세션 객체를 만들어 로그인 없이도 데모가 굴러가게 한다.

⑩ 짧은 공유 URL — 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이 그대로 반환된다.

설계상 중요한 경계
Fragments ≠ LLM · Fragments ≠ E2B 인프라

이 저장소에는 모델 가중치나 추론 엔진이 없다. 실제 코드 생성은 외부 LLM API 호출(lib/models.ts)이, 실제 코드 실행은 별도 서비스인 E2B 클라우드 샌드박스(e2b/@e2b/code-interpreter SDK로 호출)가 담당한다.

따라서 이 레포에서 배울 것은 "AI 모델 자체"가 아니라 구조화 출력 파이프라인 설계, 외부 실행 인프라 오케스트레이션, 스트리밍 UI 상태 관리, 선택적 부가기능(레이트리밋·인증·짧은 URL)을 환경변수로 켜고 끄는 패턴이다.

6기술 스택 · 의존성

Next.js 14 App Router · Vercel AI SDK v3 · zod · shadcn/ui · E2B SDK · Supabase · Upstash
영역사용 기술 · 버전 (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 셀 실행
UIshadcn/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 필드를 가지며, providerIdlib/models.tsproviderConfigs 키와 매칭돼 실제 클라이언트가 만들어진다.

용어
Vercel AI SDK
여러 LLM 제공자를 통일된 인터페이스로 호출하고, 스트리밍·구조화 출력·리액트 훅까지 한 세트로 제공하는 오픈소스 라이브러리(npm 패키지명 ai). Fragments는 이 라이브러리를 통해 어떤 모델이든 같은 코드로 부를 수 있다.
용어
zod
TypeScript용 스키마 검증 라이브러리. "이 값은 문자열이어야 한다", "이 필드는 null일 수 있다" 같은 규칙을 코드로 선언하면, 그 규칙이 타입 검사와 런타임 검증에 동시에 쓰인다. Fragments의 fragmentSchema가 대표적 예다.

7설치 · 요구사항

git clone → npm i → .env.local(E2B 키 + 최소 1개 LLM 키) → npm run dev

Fragments 자체(웹앱)를 로컬에서 띄우는 것과, 새 스택 템플릿을 만드는 것은 완전히 다른 두 개의 설치 절차다. 대부분은 전자만 하면 된다.

① 웹앱 로컬 실행

  1. git clone https://github.com/e2b-dev/fragments.git
  2. cd fragments && npm i — Node.js(최신 LTS 권장)와 npm이 필요하다.
  3. .env.local 파일을 만들고 최소 두 개 값을 채운다: E2B_API_KEY(e2b.dev에서 발급)와, 쓰고 싶은 LLM 제공자 중 최소 하나의 API 키(예: ANTHROPIC_API_KEY 또는 OPENAI_API_KEY).
  4. npm run dev(개발 서버, Turbo 모드) 또는 npm run build && npm run start(프로덕션 빌드).

② 선택적 환경변수 — 없어도 앱은 뜬다

기능필요한 환경변수
레이트리밋 · 짧은 URLKV_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)

③ 새 스택 템플릿 추가 — E2B CLI가 별도로 필요

sandbox-templates/ 아래 새 폴더를 만들고 E2B CLI(e2b template init → Dockerfile 수정 → e2b template build --name …)로 E2B 클라우드에 이미지를 미리 올린 다음, 그 템플릿 id를 lib/templates.ts에 손으로 추가해야 한다. 이건 npm 의존성 설치와 무관한 별도의 빌드타임 작업이다.

가볍게 시작하는 법
최소 조합: E2B 키 + Anthropic/OpenAI 키 하나

Supabase·KV·PostHog·Morph는 전부 없어도 무방하다. 로그인은 데모 세션으로 대체되고, 레이트리밋과 짧은 URL은 조용히 꺼진다. 진짜로 필요한 건 E2B_API_KEY와 LLM 키 하나뿐이다.

8실제 사용 흐름

프롬프트 입력 → 실시간 코드 스트리밍 → 자동 실행 → 미리보기 → (선택) 공유 · Morph 편집
단계 1

프롬프트 입력 + 템플릿/모델 선택

채팅창(components/chat-input.tsx)에 "할 일 목록 앱 만들어줘" 같은 문장을 쓴다. 상단 ChatPicker에서 템플릿을 "auto"(LLM이 알아서 고름)로 두거나 Next.js·Vue·Streamlit 등으로 직접 고정할 수 있고, ChatSettings에서 모델(기본값 claude-sonnet-4-20250514)과 temperature 같은 파라미터를 조정한다.

단계 2

구조화 JSON이 실시간으로 채워지는 걸 지켜본다

useObject/api/chat으로 요청을 보내고, 응답이 도착하는 대로 commentary(지금 뭘 하는지 설명) → titlecode 순으로 필드가 차오른다. components/fragment-code.tsx가 이 부분 코드를 문법 강조와 함께 그대로 보여줘, 마치 AI가 눈앞에서 타이핑하는 것처럼 보인다.

단계 3

스트림 종료 → 자동으로 샌드박스 생성 · 실행

스트리밍이 끝나면 onFinish가 즉시 /api/sandbox로 완성된 fragment를 넘긴다. 사용자는 버튼을 누를 필요가 없다 — isPreviewLoading 상태가 켜지며 "실행 중" 표시가 뜨고, 결과가 오면 components/preview.tsx가 웹앱이면 fragment-web.tsx(iframe 미리보기), Python 실행이면 fragment-interpreter.tsx(stdout·차트 결과)를 보여준다.

단계 4 (선택)

Deploy/Publish로 24시간짜리 공개 링크 발급

components/deploy-dialog.tsx에서 발행하면 publish() 서버 액션이 샌드박스 만료 시간을 늘리고 /s/{짧은id} 링크를 만들어준다. 이 링크는 최대 24시간 후 자동 만료된다 — 영구 배포가 아니라 임시 공유용이라는 점을 기억해야 한다.

단계 5 (선택)

후속 편집은 Morph Apply 토글로 빠르게

이미 만들어진 앱을 계속 다듬을 때 "Morph Apply" 토글을 켜면, 다음 메시지부터는 /api/chat이 아니라 /api/morph-chat이 불려 전체 재생성 없이 필요한 부분만 diff로 patch된다. 토글을 끄면 다시 전체 재생성 방식으로 돌아온다.

9함정 · 오해 방지

README와 실제 소스코드가 어긋나는 지점들 — 직접 클론해 대조 확인

이 저장소는 문서(README)와 실제 코드 사이에 실제로 대조 확인한 불일치가 여러 군데 있다. 문서만 보고 작업하면 헤매기 쉬운 지점들이다.

함정 ①
"lib/templates.json을 열어라" — 그런 파일은 없다

README의 "Adding custom personas" 절 7번 항목은 "Open lib/templates.json in your code editor"라고 안내하지만, 저장소에는 lib/templates.json이라는 파일이 존재하지 않는다. 실제로 템플릿 목록은 lib/templates.ts 안에 하드코딩된 TypeScript 객체(const templates = {...})로 정의돼 있다. JSON 파일을 찾다가는 시간을 버린다 — 편집할 곳은 .ts 파일이다.

함정 ②
models.json vs models.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.tsproviderConfigs를 고쳐야 한다.

함정 ③
README가 언급하는 getDefaultMode 함수는 현재 소스에 없다

README는 "getDefaultMode 함수에서 구조화 출력 모드를 조정하라"고 안내하지만, 실제 lib/models.ts 소스를 열어보면 그런 함수가 존재하지 않는다. 과거 버전의 흔적이 문서에만 남은 사례로 보인다 — 실제로 구조화 출력 방식은 Vercel AI SDK의 streamObject/generateObject 기본 동작에 맡겨져 있다.

함정 ④
여러 파일 지원 코드가 있지만 실제로는 절대 실행되지 않는다

app/api/sandbox/route.ts에는 Array.isArray(fragment.code)를 검사해 여러 파일을 순회하며 쓰는 분기가 있다. 하지만 lib/schema.tsfragmentSchema에서 code 필드는 z.string()으로 정의돼 있어 배열이 될 수 없다 — 즉 이 분기는 죽은 코드(dead code)이며, 실제로는 항상 else 분기(sbx.files.write(fragment.file_path, fragment.code))만 실행된다. 다중 파일 생성 기능이 실험되다 만 흔적으로 보인다.

함정 ⑤
README의 제공자 목록이 실제 코드보다 짧다

README 기능 목록에는 8개 제공자(OpenAI·Anthropic·Google AI·Mistral·Groq·Fireworks·Together AI·Ollama)만 나열돼 있지만, 실제 lib/models.tsproviderConfigs에는 Google Vertex AI·xAI·DeepSeek까지 11개가 이미 구현돼 있다. 코드가 문서보다 앞서 나간 흔한 사례다.

알아두면 편한 사실
선택적 기능은 "환경변수 없으면 조용히 꺼짐"이 기본 철학

레이트리밋(lib/ratelimit.ts)·인증(lib/auth.ts)·짧은 URL(middleware.ts)은 전부 관련 환경변수가 없으면 에러를 던지지 않고 그냥 기능을 비활성화한 채로 넘어간다. "왜 로그인이 안 되지?"가 아니라 애초에 로그인 없이도 데모(demo@e2b.dev 가짜 세션)로 굴러가도록 설계됐다는 점을 알면 로컬 개발이 훨씬 편하다.

함정 ⑥
테스트 코드 · CI가 사실상 없다

.github/workflows/에는 Renovate(의존성 자동 업데이트 봇) 설정을 검증하는 워크플로 하나만 있고, 단위 테스트나 E2E 테스트 파이프라인은 확인되지 않는다. 이 레포는 "엄격하게 테스트된 라이브러리"가 아니라 실사용 서비스(fragments.e2b.dev)로 직접 운영하며 다듬어지는 레퍼런스 애플리케이션에 가깝다는 점을 감안해야 한다.

10대안 비교

v0 · bolt.new · dyad · openui — "AI가 짠 코드를 바로 실행해 보여준다"는 같은 문제의 다른 답
프로젝트Fragments와의 차이
Vercel v0Vercel의 폐쇄형 SaaS. 모델·인프라가 Vercel에 고정돼 있고 소스가 공개되지 않는다. Fragments는 모델·호스팅을 전부 사용자가 고른다는 점이 다르다.
bolt.new (StackBlitz)브라우저 안에서 도는 WebContainer(가상 Node.js 환경)로 실행한다 — 서버 인프라가 필요 없는 대신 진짜 리눅스 격리는 아니다. Fragments는 E2B의 실제 마이크로VM 샌드박스에서 실행해, 임의의 시스템 패키지 설치나 Python 등 비-Node 스택도 자연스럽게 다룬다.
dyad로컬 데스크탑에서 도는 오픈소스 AI 앱 빌더로, 자기 컴퓨터의 파일시스템에 직접 코드를 생성한다. Fragments는 클라우드 샌드박스에서 실행하는 웹 서비스형 구조라, 로컬 환경을 더럽히지 않고 누구나 브라우저로 접근할 수 있다.
OpenUI주로 UI 컴포넌트/디자인 생성과 미리보기에 초점을 맞춘 프로젝트. Fragments는 UI뿐 아니라 Python 데이터분석 · 백엔드 포함 풀스택 앱 실행까지 다룬다는 점에서 범위가 더 넓다.
Anthropic Claude ArtifactsClaude.ai 안에서만 동작하는 폐쇄형 기능. Fragments는 애초에 이를 오픈소스로 재현하겠다고 README에서 명시한 프로젝트다.
Fragments만의 강점
"내가 소유하는" AI 앱 빌더

Apache-2.0 라이선스로 조건 없이 포크·수정·재배포가 가능하고, LLM 제공자·실행 스택·인증/레이트리밋 인프라를 전부 자기 것으로 바꿔 끼울 수 있다. 대신 그만큼 직접 운영 부담(E2B 사용료, 서버 배포, 보안 설정)을 사용자가 진다는 트레이드오프가 있다.

11정리 · 누가 쓰면 좋은가

"구조화 LLM 출력 + 안전한 코드 실행" 패턴을 배우거나, 사내 전용 AI 코드 빌더를 만들고 싶은 사람

Fragments는 "프롬프트 한 줄이 눈에 보이는 실행 결과로 바뀌는" 경험을 어떻게 만드는지를 처음부터 끝까지 실제 소스로 보여주는 프로젝트다. 핵심은 세 겹이다 — ① zod 스키마로 LLM 출력을 강제하는 구조화 스트리밍(streamObject), ② 그 결과를 격리된 클라우드 샌드박스(E2B)에서 안전하게 실행하는 오케스트레이션, ③ 레이트리밋·인증·짧은 URL 같은 부가 기능을 환경변수 하나로 켜고 끄는 선택적 설계.

이런 사람에게 특히 도움이 된다.

반대로, 이미 완성된 제품을 안정적으로 그냥 쓰고 싶다면 공식 데모(fragments.e2b.dev)나 v0·Claude Artifacts 같은 관리형 서비스가 더 맞을 수 있다. 이 레포는 구조를 이해하고 직접 운영할 사람을 위한 참고 구현이다.