본문으로 건너뛰기
5분 AI.
REPO DEEP DIVE · 2026-07-29 · E2B-DEV/FRAGMENTS · 프롬프트 한 줄을 살아있는 앱으로

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

웹앱

빠른 판단

무엇
프롬프트에서 구조화된 앱 코드를 생성해 E2B 샌드박스에서 실행·미리보기하는 AI 앱 빌더
이럴 때
생성된 코드를 격리 환경에서 바로 실행해 보고 템플릿·모델을 바꿔 앱 시제품을 반복 제작할 때
도입 전 확인
E2B 샌드박스와 연결할 LLM의 API 키가 필요하다
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. 정리 · 누가 쓰면 좋은가
  12. 직접 해볼 수 있는 실습 과제
  13. 관련 기술 심화 학습 로드맵
  14. 핵심 키워드 사전

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.ts의 providerConfigs가 제공자별 클라이언트 생성 로직을 한곳에 모아두고, 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.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분짜리 격리 샌드박스를 하나 만든 뒤:

  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번 포트가 열릴 때까지 기다려라"고 정의해둔다. 이렇게 만든 템플릿의 id가 lib/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.ts가 generateObject로 morphEditSchema(변경 설명 + // ... existing code ... 표기가 섞인 부분 diff)를 먼저 뽑는다.
  2. lib/morph.ts의 applyPatch()가 그 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 필드를 가지며, providerId가 lib/models.ts의 providerConfigs 키와 매칭돼 실제 클라이언트가 만들어진다.

용어
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(지금 뭘 하는지 설명) → title → code 순으로 필드가 차오른다. 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.ts의 providerConfigs를 고쳐야 한다.

함정 ③
README가 언급하는 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의 제공자 목록이 실제 코드보다 짧다

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 가짜 세션)로 굴러가도록 설계됐다는 점을 알면 로컬 개발이 훨씬 편하다.

함정 ⑥
테스트 코드 · 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 같은 관리형 서비스가 더 맞을 수 있다. 이 레포는 구조를 이해하고 직접 운영할 사람을 위한 참고 구현이다.

12직접 해볼 수 있는 실습 과제

목록 탐색 → 스키마 검증 → 템플릿 대조 → 실패 흐름 분석으로 넓혀가는 네 단계

아래 경로와 명령은 모두 Fragments 저장소 루트를 기준으로 한다. 소스 읽기와 메모리 안의 검증으로 진행하므로 API 키나 서버 실행은 필요하지 않다. 두 번째 과제의 실행 명령은 package.json의 의존성이 이미 설치된 환경을 전제로 한다.

입문 · 과제 1

모델 목록과 제공자 연결 지도 만들기

목표: 화면에 표시할 데이터와 실제 SDK 클라이언트를 만드는 코드의 역할을 구분한다.

  1. 다음 명령으로 lib/models.json에서 제공자별 대표 모델을 하나씩 출력한다. 모델 API를 호출하지 않고 JSON 파일만 읽는다.
  2. lib/models.ts의 providerConfigs에서 출력된 providerId를 찾는다. OpenAI와 Groq를 골라 어떤 클라이언트 생성 함수를 쓰는지, baseURL 지정이 있는지 대조한다.
  3. lib/models.json의 id·name·providerId를 각각 모델 식별자·표시 이름·제공자 연결 키로 나누어 설명한다.
node <<'NODE'
const fs = require("node:fs")
const { models } = JSON.parse(fs.readFileSync("lib/models.json", "utf8"))
const providers = [...new Set(models.map(m => m.providerId))]
for (const providerId of providers) {
  const model = models.find(m => m.providerId === providerId)
  console.log(providerId, model.id, model.name)
}
NODE
rg -n 'providerConfigs|createOpenAI|baseURL' lib/models.ts

완료 기준: 두 제공자의 모델 식별자·연결 키·클라이언트 생성 함수를 표로 정리하고, 모델 항목 추가와 제공자 구현 추가가 왜 다른 작업인지 설명한다.

중급 · 과제 2

정상 데이터와 잘못된 데이터를 실제 스키마에 넣기

목표: fragmentSchema가 보장하는 형식과 별도로 확인해야 할 실행 조건을 구분한다.

  1. lib/schema.ts에서 code·port·file_path의 타입을 읽고, 아래 네 입력의 통과 여부를 먼저 예상한다.
  2. 이미 설치된 tsx로 실제 스키마를 불러와 safeParse()를 실행한다. 예제의 Python 코드는 문자열로만 다루며 실행하지 않는다.
  3. 실패한 입력은 parsed.error.issues를 출력해 문제 필드를 확인한다. 빈 코드가 통과하는 이유도 z.string() 선언과 연결해 설명한다.
TSX_DISABLE_CACHE=1 ./node_modules/.bin/tsx -e '
import { fragmentSchema } from "./lib/schema"

const fragment = {
  commentary: "덧셈 결과를 출력한다.",
  template: "code-interpreter-v1",
  title: "덧셈 실습",
  description: "두 수를 더하는 예제다.",
  additional_dependencies: [],
  has_additional_dependencies: false,
  install_dependencies_command: "",
  port: null,
  file_path: "script.py",
  code: "print(1 + 2)"
}
const cases = [
  ["정상", fragment],
  ["코드 배열", { ...fragment, code: ["print(3)"] }],
  ["문자열 포트", { ...fragment, port: "8501" }],
  ["빈 코드", { ...fragment, code: "" }]
]
for (const [label, value] of cases) {
  const parsed = fragmentSchema.safeParse(value)
  console.log(label, parsed.success)
}
'

완료 기준: 결과가 순서대로 true·false·false·true인지 확인한다. 스키마 통과만으로 코드의 실행 가능성이나 파일 경로의 적절성까지 보장되지는 않는다는 점을 설명한다.

중급 · 과제 3

템플릿의 파일·포트·시작 명령 맞춰보기

목표: LLM에 알려주는 실행 조건과 미리 준비된 샌드박스 환경이 어디서 연결되는지 찾는다.

  1. 아래 명령으로 lib/templates.ts와 Next.js·Streamlit 템플릿의 관련 설정을 모아 읽는다.
  2. 각 템플릿의 기본 파일, 작업 디렉터리, 시작 명령, 준비 확인 포트를 표로 만든다. Next.js의 pages/index.tsx와 Streamlit의 app.py가 샌드박스 안의 어느 위치에 놓이는지 계산한다.
  3. app/api/sandbox/route.ts에서 sbx.files.write()와 sbx.getHost()에 전달되는 값을 추적한다. 템플릿이 기다리는 포트와 생성 결과의 port가 다르면 어떤 문제가 생길지 예상한다.
  4. 각 템플릿의 build.dev.ts·build.prod.ts에서 alias를 읽고, 앱이 선택하는 템플릿 이름과 대조한다. 빌드는 실행하지 않는다.
rg -n 'file:|port:|setWorkdir|setStartCmd|waitForPort|alias:' \
  lib/templates.ts \
  sandbox-templates/nextjs-developer \
  sandbox-templates/streamlit-developer \
  -g '*.ts'
sed -n '1,180p' app/api/sandbox/route.ts

완료 기준: Next.js는 3000, Streamlit은 8501을 기준으로 설정이 이어짐을 설명한다. Fragments 본체의 App Router와 생성 대상 Next.js 템플릿의 Pages Router도 구분한다.

심화 · 과제 4

실행 단계의 실패를 나누고 복구 조건 설계하기

목표: 코드 생성 완료와 코드 실행 성공을 별개의 사건으로 다루는 상태 전이표를 만든다.

  1. app/page.tsx의 onFinish에서 setIsPreviewLoading(true)부터 결과 저장, 탭 전환, 로딩 종료까지 순서를 적는다.
  2. lib/types.ts와 components/fragment-preview.tsx를 읽어 웹 결과와 Python 결과가 어느 화면으로 전달되는지 연결한다.
  3. 아래 네 상황을 소스에 대입해 실행되는 분기와 도달하지 못하는 줄을 기록한다. 실제 요청 대신 응답이나 오류가 주어졌다고 가정한다.
  4. 통신 실패에서도 로딩을 끝내려면 response.ok 확인과 try/catch/finally를 어디에 둘지 의사코드로 작성한다. 현재 동작과 개선안을 구분해서 적는다.
rg -n 'onFinish|setIsPreviewLoading|response.json|setResult' app/page.tsx
cat lib/types.ts components/fragment-preview.tsx
sed -n '1,180p' components/fragment-interpreter.tsx
가정한 상황확인할 지점
정상 웹 결과url이 있는 결과의 저장, 미리보기 탭 전환, 로딩 종료 순서
생성 완료 콜백의 오류onFinish의 error가 있으면 샌드박스 요청 분기에 진입하는지
응답 JSON 해석 실패response.json()에서 예외가 나면 로딩 종료 줄까지 도달할 수 있는지
Python 실행 오류runtimeError를 받은 FragmentInterpreter가 오류를 어떻게 표시하는지

완료 기준: 네 상황의 상태 전이표와 복구 의사코드를 완성한다. Python 실행 오류를 결과 객체로 받는 경우와 요청 처리 자체가 예외로 끊기는 경우를 구별한다.

13관련 기술 심화 학습 로드맵

여섯 주 동안 데이터 계약에서 실행 환경과 운영 경계까지 한 층씩 연결한다

매주 개념 이해 → 소스 추적 → 결과물 검증 순서로 진행한다. 버전 번호를 외우기보다 어떤 파일이 값을 만들고 다음 단계가 무엇을 기대하는지 설명하는 데 집중한다.

주차배울 개념읽을 파일·폴더결과물·완료 기준
1주차 TypeScript의 객체 타입, JSON 데이터, Next.js 프로젝트의 실행 스크립트 package.json
tsconfig.json
lib/models.json
lib/models.ts
모델 목록과 제공자 구현의 연결표. 루트의 dev·build·start가 각각 무엇을 하는지 설명한다.
2주차 zod 검증, 타입 추론, 구조화 출력과 시스템 프롬프트의 역할 lib/schema.ts
lib/templates.ts
lib/prompt.ts
app/api/chat/route.ts
프래그먼트 필드별 타입·사용처 표와 과제 2의 검증 결과. 프롬프트의 요청과 스키마의 검증 규칙을 구분한다.
3주차 리액트 상태, 부분 객체, 비동기 스트리밍과 완료 콜백 app/page.tsx
components/preview.tsx
components/fragment-code.tsx
입력부터 코드 표시, 생성 완료, 실행 요청까지의 흐름도. isLoading과 isPreviewLoading이 나타내는 단계를 구분한다.
4주차 격리 실행, 이미지 사전 빌드, 작업 디렉터리, 포트 준비 확인 sandbox-templates/nextjs-developer/
sandbox-templates/streamlit-developer/
app/api/sandbox/route.ts
lib/types.ts
두 템플릿의 실행 조건 대조표. 웹 URL을 반환하는 경로와 runCode() 결과를 반환하는 경로를 각각 설명한다.
5주차 제공자 어댑터, 전체 생성과 변경분 편집, 편집 결과의 형식 통일 lib/models.ts
app/api/morph-chat/route.ts
lib/morph.ts
app/page.tsx
일반 생성과 Morph 편집의 호출 순서 비교도. shouldUseMorph 조건과 updatedFragment가 공통 실행 흐름에 합류하는 지점을 표시한다.
6주차 선택적 인증, 요청 제한, 서버 액션, 키·값 저장소와 만료 시간 lib/auth.ts·lib/supabase.ts
lib/ratelimit.ts
app/actions/publish.ts
middleware.ts
기능별 활성화 조건표와 공유 링크의 수명 흐름도. 짧은 주소의 매핑 저장과 샌드박스 수명 연장이 서로 다른 작업임을 설명한다.
학습 결과 확인
하나의 프래그먼트를 끝까지 추적할 수 있으면 연결된 것이다

template·file_path·code·port가 프롬프트, 스키마, 화면 상태, 샌드박스 실행에서 각각 어떻게 쓰이는지 설명해 본다. 마지막에는 과제 4의 실패 상황도 같은 흐름도에 덧붙인다.

14핵심 키워드 사전

처음 보는 개념을 이 저장소의 실제 파일·함수와 연결해 읽는 사전
프래그먼트
생성할 코드와 실행에 필요한 정보를 한데 묶은 데이터다. 이 레포에서는 lib/schema.ts의 FragmentSchema가 제목·템플릿·파일 경로·코드 등의 모양을 정의한다.
스키마와 zod
스키마는 데이터가 따라야 하는 형식의 규칙이고, zod는 그 규칙을 선언하고 검사하는 도구다. fragmentSchema는 code를 문자열로, port를 숫자 또는 null로 정의한다.
구조화 출력
LLM의 답을 자유로운 문장 대신 정해진 필드가 있는 데이터로 받는 방식이다. app/api/chat/route.ts는 streamObject()에 스키마를 넘겨 실행 단계가 사용할 프래그먼트를 생성한다.
스트리밍
응답이 모두 완성될 때까지 기다리지 않고 도착한 부분부터 전달하는 방식이다. app/page.tsx는 useObject의 object 변화를 받아 설명과 코드를 갱신한다.
부분 객체와 DeepPartial
일부 필드가 아직 없는 상태도 표현할 수 있도록 만든 객체 타입이다. 스트리밍 중인 fragment는 DeepPartial<FragmentSchema>이므로 화면에서 code나 file_path의 존재를 확인한 뒤 표시한다.
라우트 핸들러
특정 주소로 들어오는 HTTP 요청을 처리하는 서버 함수다. 이 레포의 app/api/chat/route.ts와 app/api/sandbox/route.ts는 각각 POST를 내보내 생성과 실행을 나눈다.
샌드박스
생성된 코드를 앱 본체와 분리해 돌리는 실행 환경이다. app/api/sandbox/route.ts는 E2B의 Sandbox.create()로 환경을 만들고 파일 쓰기와 코드 실행을 요청한다.
샌드박스 템플릿
필요한 라이브러리와 시작 명령을 미리 준비해 두는 실행 환경의 설계다. sandbox-templates/가 빌드 정의를 담고, lib/templates.ts가 생성에 사용할 파일·포트·설명을 LLM에 알려준다.
포트 준비 확인
서버 프로그램을 시작한 뒤 실제로 접속을 받을 준비가 되었는지 기다리는 절차다. 템플릿의 setStartCmd()에 전달하는 waitForPort()가 지정 포트의 준비 상태를 확인한다.
제공자 어댑터
서로 다른 모델 서비스의 호출 방식을 공통 인터페이스에 맞추는 연결 코드다. lib/models.ts의 providerConfigs가 providerId에 따라 사용할 SDK 클라이언트를 만든다.
변경분 병합과 Morph Apply
원본 코드에 변경 지시를 적용해 수정된 전체 코드를 만드는 과정이다. lib/morph.ts의 applyPatch()는 원본·수정 지시·변경 내용을 Morph에 전달하며, 병합된 전체 코드를 반환한다.
레이트리밋
일정 시간 동안 허용할 요청 수를 제한하는 장치다. lib/ratelimit.ts는 KV 설정이 있을 때 Upstash의 슬라이딩 윈도로 최근 구간의 요청을 제한한다.
키·값 저장소와 KV
이름표인 키로 값을 빠르게 찾는 저장 방식이다. publish()는 fragment:로 시작하는 키에 실제 URL을 저장하고, middleware.ts는 짧은 공유 주소의 식별자로 이를 조회한다.
서버 액션
화면에서 호출하되 서버에서 실행되는 Next.js 함수다. app/actions/publish.ts의 publish()는 공유할 주소를 확인하고 샌드박스 수명 연장과 짧은 주소 저장을 처리한다.
만료 시간과 TTL
임시 자원이나 저장된 값이 유지되는 시간이다. 이 레포에서는 샌드박스의 타임아웃과 공유 주소 매핑의 만료가 따로 설정되므로, 짧은 URL을 만들었다고 실행 환경이 영구 보관되는 것은 아니다.