REPO DEEP DIVE · 2026-07-29 · ONLOOK-DEV/ONLOOK · 브라우저에서 코드를 직접 그리는 "코드용 Figma"

onlook-dev/onlook 딥다이브
"클릭한 곳이 곧 소스 코드" 시각 편집기 해부

Onlook은 실행 중인 Next.js + Tailwind 앱을 브라우저 안에서 Figma처럼 클릭·드래그로 편집하면 그 결과가 그대로 실제 소스 코드(JSX/CSS 클래스)에 반영되는 오픈소스 비주얼 코드 에디터다. AI 채팅으로 코드를 생성·수정하는 것도 지원해, Bolt.new·Lovable·v0 같은 "AI로 앱 만들기" 도구들의 오픈소스 대안으로 자리를 잡았다.

가장 중요한 사실 하나: 이 저장소는 원래 Electron 데스크탑 앱이었다가, 지금은 브라우저에서 도는 Next.js 웹 앱으로 완전히 전환됐다. 예전 컴포넌트 감지 기능 설명에는 아직 Previously in Onlook Desktop이라는 문구가 README에 남아 있어, 이 아키텍처 전환 자체가 좋은 학습 재료다.

(저장소 onlook-dev/onlook · 라이선스 Apache-2.0 · 모노레포: apps/ 3개 + packages/ 19개 · 패키지 매니저 Bun 1.3.1 워크스페이스 · 웹앱=Next.js 16 + React 19.2 + Tailwind v4 · DB=Postgres(Supabase)+Drizzle · AI=Vercel AI SDK+OpenRouter · 최신 커밋 423e2e9, 2026-07-21)
목차
  1. 한 줄 정체
  2. 왜 지금 뜨는가
  3. 무엇을 해결하나
  4. 전체 구조
  5. 핵심 설계·동작 원리
  6. 기술 스택·의존성
  7. 설치·요구사항
  8. 실제 사용 흐름
  9. 함정·오해 방지
  10. 대안 비교
  11. 정리 — 누가 쓰면 좋은가

1한 줄 정체

"브라우저 미리보기를 직접 만지면, 그게 곧 진짜 소스 코드 편집이 되는 도구"

Onlook은 실행 중인 웹앱의 화면을 캔버스처럼 다루는 비주얼 에디터다. 사용자가 프로젝트를 만들면(텍스트 프롬프트로 처음부터, 또는 기존 Next.js 저장소를 가져와서) Onlook은 그 코드를 실제로 실행시키고, 그 실행 결과(iframe으로 렌더링된 화면)를 캔버스 위에 띄운다. 사용자가 캔버스에서 버튼 하나를 클릭해 색을 바꾸거나 문구를 고치면, 화면 뒤편의 .tsx 파일이 실제로 수정된다. 왼쪽에는 AI 채팅창이 있어 "네비게이션 바를 추가해줘" 같은 문장으로도 같은 결과를 만들 수 있다.

즉 Onlook은 디자인 툴도 아니고 단순 AI 챗봇도 아니다. "화면(DOM) ↔ 코드(JSX 소스)"를 실시간으로 양방향 연결해주는 번역기 겸 편집기이며, 그 위에 AI 코드 생성이 얹힌 형태다.

한 줄 비유

"완성된 케이크(화면)의 크림을 직접 만지면, 레시피(소스 코드)가 자동으로 다시 쓰이는" 주방

보통은 레시피(코드)를 먼저 고치고 나서 다시 구워야(빌드) 케이크(화면) 모양이 바뀐다. Onlook은 반대로, 이미 구워진 케이크를 손으로 매만지면 그 변화를 읽어 레시피 쪽을 자동으로 되돌려 쓴다.

이걸 가능하게 하는 것이 케이크의 크림 한 조각 한 조각에 몰래 붙여둔 보이지 않는 꼬리표(data-oid)다. 이 꼬리표가 "이 크림은 레시피 몇 번째 줄에서 나왔는지"를 정확히 알고 있다.

2왜 지금 뜨는가

"AI로 앱 만들기" 열풍 속 유일한 오픈소스 + 코드 소유권 유지 노선

① Bolt.new·Lovable·v0 열풍의 "오픈소스 & 셀프호스트" 대안

2024~2026년 사이 "프롬프트 한 줄로 웹앱을 만들어주는" 서비스들이 폭발적으로 늘었다. 문제는 대부분이 폐쇄형 SaaS라 코드가 자기 계정 밖으로 잘 나오지 않거나, 특정 벤더 인프라에 묶인다는 점이다. Onlook README는 스스로를 "Bolt.new, Lovable, V0, Replit Agent, Figma Make, Webflow 등의 오픈소스 대안"이라 규정한다. 소스가 완전히 공개돼 있고 Apache-2.0이라 자유롭게 셀프호스트·수정할 수 있다.

② "AI가 만든 코드"와 "내가 직접 만지는 코드"의 간극을 메운다

AI 코드 생성 도구의 흔한 불만은 "결과물이 마음에 안 들 때 미세 조정이 어렵다"는 것이다. Onlook은 AI 채팅으로 크게 만들고, 캔버스에서 손으로 세밀하게 다듬는 두 방식을 같은 화면에서 오간다. 디자이너가 Figma 감각으로 여백·색·타이포를 만지면, 그 결과가 실제 Next.js/Tailwind 코드로 바로 저장된다.

③ 데스크탑 → 웹으로의 아키텍처 피벗

이 저장소는 원래 Electron 기반 데스크탑 앱(onlook-dev/desktop)이었다. 지금 보이는 onlook-dev/onlook은 그 후계로, 완전히 브라우저에서 도는 웹 서비스(Next.js 앱 + 클라우드 샌드박스)로 다시 지어졌다. README에는 "Detect and use Components – Previously in Onlook Desktop"처럼 옛 데스크탑판 기능을 웹판으로 이식했다는 흔적이 그대로 남아 있어, "로컬 앱을 웹 서비스로 재설계"하는 실제 사례를 볼 수 있다.

현재 위치 정리
"OSS 비주얼 에디터"와 "차기 호스티드 제품"은 다른 것

README 상단에는 "이 저장소는 Onlook을 시작하게 한 오픈소스 비주얼 에디터이고, 지금 만드는 중인 호스티드 제품은 별도로 얼리 액세스 대기 중"이라는 안내가 있다. 즉 이 레포는 계속 살아있는 오픈소스 프로젝트이면서, 동시에 회사가 그 위에 새 상용 제품을 준비 중인 전환기의 레포다. "지금 이 코드가 회사의 최종 상용 제품"이라고 오해하면 안 된다.

3무엇을 해결하나

"코드-화면 왕복 비용"과 "AI 생성 결과의 미세 조정 불가" 문제

전통적인 웹 개발에서 디자인을 한 픽셀 바꾸려면 코드 열기 → 클래스 수정 → 저장 → 브라우저 새로고침 → 확인을 반복해야 한다. AI 코드 생성 도구를 쓰면 이 왕복은 줄지만, 대신 "생성된 결과물이 정확히 원하는 모습이 아닐 때 어떻게 고칠지"라는 새 문제가 생긴다. Onlook이 정면으로 겨냥하는 지점이 이 둘이다.

4전체 구조

Bun 워크스페이스 모노레포 — apps 3개 + packages 19개

루트 package.jsonworkspacespackages/*, apps/*, tooling/*, apps/web/*, docs를 묶는다. 실제 소스 파일은 .ts/.tsx 기준 약 1,290개(전체 추적 파일은 약 1,700개)로, 결코 작은 레포가 아니다.

onlook/ ├── package.json # packageManager: bun@1.3.1, workspaces 정의 ├── LICENSE.md # Apache-2.0 ├── CLAUDE.md / AGENTS.md # 기여 에이전트용 규칙 문서 ├── docker-compose.yml · Dockerfile ├── docs/ # Fumadocs 기반 공식 문서 사이트(워크스페이스 멤버) ├── apps/ │ ├── web/ │ │ ├── client/ # ★ 본체 — Next.js 16 App Router (React 19.2) │ │ ├── server/ # 샌드박스 tRPC 서버(별도 프로세스) │ │ └── preload/ # 미리보기 iframe 안에 주입되는 스크립트 │ ├── backend/ # 백엔드 보조 서비스 │ └── admin/ # 운영 콘솔 └── packages/ # 19개 공유 패키지 ├── parser/ # ★ JSX AST 파싱 · data-oid 주입 · 코드 수정 ├── ai/ # ★ AI 채팅 · 에이전트 도구 · 프롬프트 ├── code-provider/ # ★ 샌드박스 실행 백엔드(CodeSandbox 등) 추상화 ├── penpal/ # iframe ↔ 부모 창 postMessage RPC ├── db/ # Drizzle ORM 스키마(Postgres/Supabase) ├── models · types · constants · utility ├── ui/ # 디자인 시스템 컴포넌트 ├── git · github · stripe · email · fonts · image-server · growth · rpc · scripts

구조가 말해주는 것: "편집 로직(parser)"과 "AI 로직(ai)"과 "실행 환경(code-provider)"이 완전히 분리된 패키지로 나뉘어 있고, 이들을 Next.js 앱인 apps/web/client가 조립해서 쓴다. 미리보기용 iframe에 심는 스크립트(apps/web/preload)까지 별도로 빌드되는 것도 특징이다.

5핵심 설계·동작 원리

"모든 JSX 태그에 몰래 ID 달기" → "그 ID로 화면과 소스를 잇기" → "코드를 실제로 고쳐쓰기"

Onlook을 이해하는 열쇠는 세 단계 파이프라인이다. ① 소스 코드의 모든 JSX 요소에 고유 ID를 심는다. ② 그 ID를 화면(DOM)과 소스(AST) 양쪽에 동시에 유지해 서로를 찾아갈 수 있게 한다. ③ 화면에서 발생한 편집을, ID로 찾은 정확한 소스 위치에 실제 코드 변경으로 적용한다. 이 전부가 독자적인 컴파일러 플러그인이 아니라, @babel/standalone으로 소스 파일을 직접 파싱·수정·재출력하는 방식으로 구현되어 있다.

┌───────────────────────────────────────────────────────────────┐ │ ONLOOK "화면 ↔ 코드" 3단계 파이프라인 │ └───────────────────────────────────────────────────────────────┘ [1] ID 주입 (packages/parser/src/ids.ts → addOidsToAst) 모든 <JSXOpeningElement> 순회 · 이미 data-oid가 있으면 충돌만 검사, 없으면 새로 발급(createOid) · 결과: <button data-oid="a1b2c3">저장</button> │ ▼ [2] 위치 지도 만들기 (packages/parser/src/template-node/map.ts → createTemplateNodeMap) AST를 다시 순회하며 data-oid → TemplateNode 매핑 생성 TemplateNode = { 파일 경로, 시작/끝 줄·컬럼, 소속 컴포넌트명, 배열(map)/조건부 렌더링 여부 } │ (빌드 시 이 data-oid는 그대로 DOM 속성으로 렌더링됨) ▼ [3] 브라우저 iframe (apps/web/preload/script) preload 스크립트가 실행 중인 화면(DOM)에서 클릭된 요소의 data-oid / data-odid(DOM id) / data-oiid(인스턴스 id)를 읽어 penpal(postMessage RPC)로 부모 창(에디터 UI)에 전달 │ ▼ [4] 실제 코드 수정 (packages/parser/src/code-edit/*.ts) oid로 TemplateNode를 찾아 정확한 줄·컬럼의 JSX 노드를 다시 찾고 style.ts / text.ts / move.ts / insert.ts / remove.ts 등이 AST를 직접 변형 → prettier로 재포맷 → 파일에 씀

설계 포인트 ① — 4종의 데이터 속성으로 "같은 요소, 다른 렌더링"까지 구분

packages/constants/src/editor.tsEditorAttributesdata-oid(요소 고유 ID) 외에도 data-oiid(인스턴스 ID), data-odid(실제 렌더링된 DOM 인스턴스 ID), data-ocname(컴포넌트 이름)을 정의한다. 같은 <Card> 컴포넌트를 리스트에서 .map()으로 5번 그려도 소스상의 JSX는 하나뿐이다. data-oid는 "이 코드가 어느 소스 줄에서 왔는가"를, data-oiid는 "화면에 실제로 찍힌 5개 중 몇 번째 인스턴스인가"를 구분해준다. 이 구분이 없으면 리스트의 3번째 카드만 색을 바꾸고 싶어도 전체가 바뀌어버린다.

용어
AST (Abstract Syntax Tree, 추상 구문 트리)
소스 코드를 "글자 나열"이 아니라 "이 태그 안에 저 속성이 있고, 그 안에 이 텍스트가 있고…" 같은 트리 구조로 표현한 것. Onlook은 @babel/standalone으로 .tsx 파일을 AST로 바꾼 뒤, 이 트리를 직접 조작해서 코드를 고친다.

설계 포인트 ② — 컴파일러 플러그인이 아니라 "AST를 직접 다시 쓰는" 방식

많은 시각 편집기는 Babel/SWC 컴파일 플러그인으로 빌드 시점에 소스 위치 정보를 주입한다. Onlook의 방식은 조금 다르다. packages/parser@babel/standalone(브라우저/Node에서 그대로 도는 순수 JS Babel)으로 파일 자체를 파싱해 AST를 얻고, 그 AST를 프로그램적으로 변형한 뒤 다시 문자열 코드로 뽑아 파일에 쓴다. 즉 빌드 파이프라인에 끼어드는 게 아니라, "코드를 읽고 → 고치고 → 다시 저장"하는 별도의 오프라인 변환 단계에 가깝다. 그래서 Next.js의 next.config.ts를 건드릴 필요가 없다는 장점이 있지만, 반대로 수정 후 반드시 파일이 다시 저장되고, 실행 중인 개발 서버가 그 변화를 감지(HMR)해야 화면에 반영된다는 제약도 생긴다.

비유

보통의 "빌드 시점 주입" 방식이 인쇄소에서 책을 찍을 때마다 자동으로 쪽번호 도장을 찍는 기계라면, Onlook의 방식은 이미 인쇄된 책을 한 장씩 펼쳐 손으로 쪽번호를 적어 넣고, 다시 제본하는 편집자에 가깝다. 매번 손으로 하는 대신, addOidsToAst라는 자동화된 절차로 이 편집을 순식간에 해치운다.

설계 포인트 ③ — 실행 환경은 "내 컴퓨터"가 아니라 클라우드 샌드박스

Onlook은 프로젝트를 로컬에서 실행하지 않는다. packages/code-provider가 실행 백엔드를 추상화하는데, CodeProvider enum에는 CodeSandbox·E2B·Daytona·VercelSandbox·Modal·NodeFs 여섯 값이 있지만, 실제로 구현된 프로바이더 폴더는 providers/codesandboxproviders/nodefs 둘 뿐이다. @codesandbox/sdk(^1.1.6)로 클라우드에 컨테이너를 띄우고 그 안에서 bun run dev로 Next.js 개발 서버를 실행 — 그 화면을 iframe으로 캔버스에 붙인다.

설계 포인트 ④ — iframe과 에디터를 잇는 postMessage RPC (penpal)

실행 중인 미리보기는 iframe 안에서 돈다(apps/web/preload/script가 그 iframe에 주입되는 스크립트). 부모 창(에디터 UI)과 자식 iframe은 서로 다른 origin일 수 있으므로 직접 함수 호출을 못 하고, penpal 라이브러리로 감싼 postMessage 기반 RPC를 쓴다. packages/penpal이 부모/자식 양쪽의 타입 안전한 메서드 인터페이스를 정의하고, preload/script/index.tsfindOnlookParent()는 "Next.js를 바로 감싼 단일 iframe"과 "CodeSandbox 안에 Storybook까지 중첩된 iframe" 두 시나리오를 구분해 올바른 부모 창을 찾는다.

설계 포인트 ⑤ — AI 채팅은 "도구 호출"로 같은 편집 함수를 부른다

packages/ai는 Vercel AI SDK(ai@5.0.60)와 OpenRouter(@openrouter/ai-sdk-provider)로 LLM 응답을 스트리밍하면서, tools/ 아래 정의된 도구들(파일 읽기/쓰기, 셸 명령 등)을 호출한다. 결국 AI가 "버튼 색을 바꿔줘"라는 요청을 처리할 때도, 캔버스에서 사람이 직접 드래그했을 때와 같은 code-edit/*.ts 함수들을 거쳐 AST를 고친다. "사람이 만지든 AI가 만지든 최종적으로 코드를 고치는 경로는 하나"라는 설계다.

주의 — 최근 보안 수정 이력
HEAD 커밋 자체가 IDOR 보안 패치

이 분석 시점 기준 최신 커밋(423e2e9)은 "fix(security): enforce project-membership authorization across all tRPC routers (IDOR)"다. 즉 얼마 전까지 일부 tRPC 라우터가 프로젝트 멤버십 검증 없이 ID만으로 다른 사용자의 프로젝트 데이터에 접근을 허용했을 가능성이 있었다는 뜻이다(IDOR = Insecure Direct Object Reference).

셀프호스트해서 실제 사용자 데이터를 다룰 계획이라면, verifyProjectAccess 같은 권한 검증 헬퍼가 실제로 호출되는 라우터가 어디까지인지 직접 점검하고 최신 커밋으로 유지하는 것이 안전하다.

6기술 스택·의존성

Next.js 16 + React 19 + Tailwind v4 · tRPC · Drizzle/Supabase · OpenRouter

① 웹 앱 본체 — apps/web/client

요소무엇 / 왜
프레임워크Next.js 16.0.7(App Router) + React 19.2 + TypeScript ^5.5
스타일Tailwind CSS v4 — 시각 편집으로 바뀐 스타일이 결국 Tailwind 클래스 문자열로 저장됨(customTwMerge 유틸로 병합)
서버 통신tRPC + Zod 검증. 라우터는 chat·project·publish·domain·github·subscription·usage·user 등으로 도메인별 분리
상태 관리MobX(mobx-react-lite) — 옵저버블 스토어로 에디터 상태(캔버스·선택 요소·채팅) 관리
i18nnext-intlmessages/*에 다국어 문자열 분리
인증Supabase Auth(서버/브라우저 클라이언트 분리, utils/supabase/*)

② 편집·실행 핵심 패키지

패키지핵심 의존성 / 역할
@onlook/parser@babel/standalone, @babel/types — JSX AST 파싱·oid 주입·코드 재작성·Prettier 재포맷
@onlook/aiai@5.0.60(Vercel AI SDK), @openrouter/ai-sdk-provider, openai — 채팅·에이전트 도구·프롬프트
@onlook/code-provider@codesandbox/sdk@^1.1.6 — 클라우드 샌드박스 실행(현재 실제 동작하는 유일한 원격 프로바이더)
@onlook/penpalpenpal — iframe ↔ 부모 창 타입 안전 postMessage RPC
@onlook/dbdrizzle-orm + postgres + drizzle-kit — Postgres(Supabase) 스키마: 사용자·프로젝트·브랜치·캔버스·채팅·구독·도메인
@onlook/stripestripe@^18.2.1 — 구독/결제(subscription 스키마와 연동)
용어
tRPC
프론트엔드와 백엔드가 같은 TypeScript 타입을 공유해서, REST API 스펙 문서 없이도 함수 호출하듯 서버 API를 부르고 타입 체크까지 받는 방식. Onlook은 채팅·프로젝트·배포 등 거의 모든 서버 기능을 tRPC 라우터로 노출한다.
용어
Drizzle ORM
TypeScript로 데이터베이스 스키마와 쿼리를 타입 안전하게 작성하게 해주는 경량 ORM. Onlook은 Supabase의 Postgres를 이 Drizzle로 다룬다.
용어
OpenRouter
여러 AI 모델 제공사(Anthropic·OpenAI 등)를 하나의 API로 중계해주는 서비스. Onlook의 AI 채팅은 Anthropic/OpenAI에 직접 붙지 않고 전부 OpenRouter를 통해 모델을 호출한다.

7설치·요구사항

Bun 1.3.1 필수 · Postgres(Supabase) · CodeSandbox 계정 · 다수의 API 키
항목요구사항
패키지 매니저Bun 1.3.1(packageManager 필드로 고정) — npm/yarn/pnpm 혼용 금지가 CLAUDE.md에 명시됨
기본 실행bun installbun dev(@onlook/web-client + @onlook/web-preload 동시 기동)
DBPostgres(로컬 또는 Supabase 프로젝트). bun db:push/db:migrate로 스키마 반영, db:gen은 관리자 전용으로 문서에 명시
환경변수packages/scriptssetup:env 스크립트로 초기화. Supabase 키·OPENROUTER_API_KEY·CodeSandbox API 키·Stripe 키 등 다수 필요
Dockerdocker compose up -d / docker:build / docker:logs 스크립트 제공
타입체크/테스트bun run typecheck, bun test(Vitest, Storybook 인터랙션 테스트 포함, Playwright 브라우저 러너 사용)
주의
"그냥 클론해서 바로 써보기"는 어렵다

Onlook은 단일 바이너리 CLI 도구가 아니라 Supabase(DB+Auth) + CodeSandbox(실행 샌드박스) + OpenRouter(AI) + Stripe(결제)가 얽힌 풀스택 SaaS형 애플리케이션이다. 각 외부 서비스의 키를 발급받아 넣어야 실제로 프로젝트를 만들고 편집하는 흐름까지 갈 수 있다. "가벼운 로컬 도구"를 기대하고 클론하면 초기 설정 단계에서 막히기 쉽다.

8실제 사용 흐름

가입 → 프로젝트 생성(텍스트/템플릿) → 캔버스 편집 + AI 채팅 → 배포
단계 ①

프로젝트 시작 — 텍스트 프롬프트 또는 템플릿

Supabase Auth로 로그인한 뒤, README의 체크리스트대로 텍스트 설명이나 이미지, 또는 미리 만들어진 템플릿으로 새 Next.js 프로젝트를 만든다. 이 시점에 @codesandbox/sdk가 클라우드에 컨테이너를 만들고 그 안에 프로젝트 파일을 올린다.

단계 ②

캔버스 편집 — 클릭·드래그로 스타일/텍스트/레이아웃 수정

샌드박스 안에서 bun run dev로 뜬 Next.js 개발 서버 화면이 iframe으로 캔버스에 표시된다. 레이어를 클릭해 선택하면 data-oid를 통해 정확한 소스 위치가 잡히고, 색상·간격·텍스트·위치를 바꾸면 code-edit 함수들이 즉시 해당 .tsx 파일을 고쳐 쓴다.

단계 ③

AI 채팅 — 문장으로 기능 추가·리팩터링 요청

왼쪽 채팅 패널에 "가격 섹션 추가해줘" 같은 요청을 하면, packages/ai의 에이전트가 프로젝트 컨텍스트(선택된 요소·에러·파일)를 참고해 도구를 호출하고, 같은 code-edit 경로로 코드를 수정한다. 여러 메시지를 큐에 쌓아 순차 처리하는 것도 지원한다.

단계 ④

배포 — 공유 링크 또는 커스텀 도메인

publish tRPC 라우터가 Deployment 레코드를 만들어 배포를 실행하고, 기본적으로 onlook.live 도메인 아래 공유 링크를 발급하거나 사용자의 커스텀 도메인을 연결한다(domain 라우터 + project-custom-domain 스키마).

9함정·오해 방지

README의 옛 흔적 · enum과 실제 구현의 괴리 · 느슨한 iframe 보안 · 꺼진 lint
함정 ①
"컴포넌트 감지 기능은 데스크탑에 있던 것" — README의 시대 흔적

README 기능 체크리스트의 "Detect and use Components" 항목에는 Previously in Onlook Desktop이라는 주석이 달려 있다. 이건 지금 이 저장소가 다루는 웹판이 아니라, 이미 별도 저장소로 분리된 옛 Electron 데스크탑판에서 먼저 구현됐던 기능이라는 뜻이다. 문서를 훑다가 "Onlook Desktop"이라는 단어가 나오면 이 저장소 코드가 아니라 onlook-dev/desktop이라는 별개 프로젝트를 가리킨다는 점을 기억해야 한다.

함정 ②
CodeProvider enum 6종 vs 실제 구현 2종

packages/code-provider/src/providers.tsCodeProvider enum은 CodeSandbox·E2B·Daytona·VercelSandbox·Modal·NodeFs 여섯 값을 나열하지만, packages/code-provider/src/providers/ 폴더 안에 실제로 존재하는 구현체는 codesandboxnodefs 둘뿐이다. "다양한 샌드박스 백엔드를 지원한다"는 인상과 달리, 실제로 클라우드에서 프로젝트를 돌리는 경로는 CodeSandbox 하나로 좁혀져 있다. enum만 보고 "E2B로 바꿔 쓸 수 있겠다"고 가정하면 안 된다.

함정 ③
미리보기 iframe의 postMessage가 origin을 가리지 않는다

apps/web/preload/script/index.ts의 penpal WindowMessenger 설정에는 allowedOrigins: ['*']와 함께 // TODO: Use a proper origin이라는 주석이 그대로 남아 있다. 즉 편집기(부모 창)와 실행 중인 미리보기(iframe, 사용자/AI가 만든 임의 코드가 도는 곳) 사이의 통신 채널이 아직 출처(origin) 검증을 하지 않는다. 셀프호스트해서 신뢰할 수 없는 콘텐츠를 다룰 계획이라면 이 지점을 직접 점검·강화해야 한다.

함정 ④
CI에 lint 잡(job)이 있어 보이지만 꺼져 있다

.github/workflows/ci.yml에는 lint 잡 전체가 주석 처리돼 있고, 그 위에 "TODO: Enable lint job after applying lint fixes…"라는 메모가 달려 있다. ESLint 설정(tooling/eslint)과 각 패키지의 lint 스크립트는 존재하지만, PR·push 시 실제로 강제되는 건 타입체크와 유닛 테스트뿐이다. "CI 워크플로 파일에 lint가 정의돼 있으니 코드 스타일이 강제되겠지"라고 넘겨짚으면 안 된다.

참고 — 버전 진실원(source of truth)이 없다

루트 package.json과 대부분의 packages/*/package.json은 버전이 전부 0.0.0(비공개 패키지)이고, 별도의 CHANGELOG.md도 없다. 즉 이 프로젝트는 semver 릴리스 태그가 아니라 git 커밋 이력 자체가 사실상의 버전 진실원이다. "v1.x 기준"처럼 버전을 인용하는 대신, 항상 커밋 해시(예: 이 문서는 423e2e9, 2026-07-21) 기준으로 이야기하는 편이 안전하다.

10대안 비교

"코드 소유권 + 오픈소스" 축에서 Onlook의 위치
도구성격Onlook과의 차이
webstudio오픈소스 비주얼 웹 빌더. 노코드에 가까운 방식으로 페이지를 만들고 코드/정적 사이트로 내보냄Onlook은 기존 Next.js 소스 파일을 그대로 두고 실시간으로 왕복 편집하는 쪽에 가깝다. webstudio는 자체 편집 모델 위에서 작업하다 결과물을 내보내는 흐름이 더 강하다.
v0 (Vercel)프롬프트로 React/Tailwind 컴포넌트를 생성해주는 폐쇄형 SaaSv0는 컴포넌트 생성에 강하지만 비공개 서비스다. Onlook은 오픈소스이며 생성 이후에도 캔버스에서 직접 미세 조정이 가능하다.
dyad로컬에서 도는 오픈소스 AI 앱 빌더. 클라우드 종속 없이 자기 컴퓨터에서 실행Onlook은 기본적으로 클라우드 샌드박스(CodeSandbox)에서 프로젝트를 실행하는 구조라, "완전 로컬"을 원한다면 dyad 쪽이 더 가깝다.
Bolt.new / Lovable브라우저에서 AI로 풀스택 앱을 생성·배포하는 폐쇄형 SaaS사용 경험(채팅+미리보기)은 비슷하지만 비공개 소스다. Onlook은 같은 경험을 오픈소스·셀프호스트 가능한 형태로 제공한다.
비유로 정리

webstudio가 "레고 블록 설명서 위에서 조립하는" 도구라면, Onlook은 "이미 조립된 집을 손으로 고치면서, 그 결과를 다시 설계도(코드)에 옮겨 적는" 도구에 가깝다. dyad가 이 집을 "내 마당(로컬)"에 짓는다면, Onlook은 기본값으로 "임대한 작업실(클라우드 샌드박스)"에서 짓는다.

11정리 — 누가 쓰면 좋은가

"코드는 지키되 디자인은 캔버스로" 원하는 팀에게

Onlook은 ① 결과물이 평범한 Next.js+Tailwind 코드로 남길 원하고, ② AI로 빠르게 초안을 만든 뒤 디자이너가 눈으로 보며 다듬고 싶고, ③ 오픈소스·셀프호스트 가능성을 중요하게 여기는 팀·개인에게 잘 맞는다. 반대로 완전 로컬 실행이 필수이거나, Next.js/Tailwind가 아닌 스택을 써야 한다면(README 자체가 "비-Next.js/비-Tailwind 프로젝트 지원"을 아직 미완료 항목으로 표시) 다른 선택지를 먼저 살펴보는 게 낫다.

이런 사람에게 추천

프론트엔드 개발자 + 디자이너가 같은 화면을 두고 협업하는 팀

디자이너는 캔버스에서 색·간격을 직접 만지고, 개발자는 그 결과가 반영된 .tsx diff를 리뷰하는 식의 협업 모델을 만들고 싶을 때 적합하다. 또한 Babel AST 조작·postMessage 기반 iframe RPC·tRPC+Drizzle 풀스택 구조를 실전 규모 코드로 공부하고 싶은 엔지니어에게도 좋은 레포다.