Lightpanda가 하는 일: 크롬을 띄우지 않는 헤드리스 브라우저

AI 에이전트에게 웹 페이지를 읽히거나 크롤러를 돌리다 보면 결국 헤드리스 크롬을 띄우게 됩니다. 요즘 사이트는 자바스크립트가 내용을 채우기 때문에 단순한 HTTP 요청으로는 빈 껍데기만 받기 때문입니다. 문제는 크롬이 무겁다는 점입니다. 탭 몇 개만 열어도 메모리가 기가바이트 단위로 올라가고, 서버 여러 대에서 수백 개를 돌리면 비용이 바로 늘어납니다.

Lightpanda는 이 자리를 노린 브라우저입니다. 크롬이나 웹킷을 고쳐 쓴 것이 아니라 Zig 언어로 처음부터 새로 만들었고, 화면을 그리는 렌더링 엔진을 아예 넣지 않았습니다. 자바스크립트는 크롬과 같은 V8 엔진으로 실행하고, HTML 해석은 Servo 프로젝트의 html5ever, 네트워크는 libcurl을 씁니다. 사람이 보는 화면은 없고 DOM, 자바스크립트, 쿠키, 폼 입력, 클릭처럼 자동화에 필요한 부분만 남긴 구조입니다.

11월 2일 오후 GitHub 트렌딩 일간 목록에서 Lightpanda 저장소는 두 번째 자리에 올라 있었고, 그날 하루에만 별이 825개 붙었습니다. 누적 별은 4만 개를 넘었습니다. 2023년 2월에 저장소가 만들어졌고, 10월 2일에 1.0.0이 나온 뒤 10월 15일 1.0.1, 10월 23일 1.0.2까지 3주 사이 세 번의 정식 릴리스가 이어졌습니다.

1.0.2에서는 페이지의 JSON-LD와 오픈그래프 정보를 그대로 뽑는 structured_data 출력, 섀도 DOM 안쪽 버튼까지 닿는 Playwright 클릭, Web Crypto의 Ed25519와 X25519 지원이 들어갔습니다. 공식 X 계정이 올린 릴리스 소개는 아래와 같습니다.

GitHub 트렌딩 일간 저장소 목록. 1위 thedotmack/claude-mem 아래 2위에 lightpanda-io/browser가 있고 Zig, 별 40,482개, 오늘 825개 별이 표시돼 있다
GitHub 트렌딩 일간 목록 두 번째 줄이 Lightpanda 저장소다.GitHub · 원문
Lightpanda 공식 X 게시물X에서 원문 보기

근거 [1] [2] [6]

Lightpanda 설치: 실행 파일 하나, 윈도우는 WSL 안에서

설치는 생각보다 단순합니다. 리눅스와 맥용 실행 파일이 매일 nightly 빌드로 올라오고, 이 파일 하나를 내려받아 실행 권한만 주면 됩니다. 맥은 Homebrew, 아치 리눅스는 AUR 패키지로도 받을 수 있고, 공식 도커 이미지도 있습니다. 소스에서 직접 빌드하려면 Zig 0.17.0과 Rust, V8 빌드에 필요한 라이브러리가 따로 필요하니 처음에는 실행 파일을 받는 쪽이 낫습니다.

윈도우용 실행 파일은 없습니다. 공식 안내는 WSL 안에서 리눅스와 같은 명령으로 설치하라고 하고, Puppeteer나 Playwright 같은 자동화 코드는 WSL 안에서 돌려도 되고 윈도우 쪽에서 돌려도 된다고 설명합니다. WSL이 localhost:9222 포트를 윈도우로 자동으로 넘겨 주기 때문입니다.

이번에는 윈도우 서버의 WSL1 우분투 24.04에서 그대로 따라 해 봤습니다. 내려받은 파일은 약 77MB였고 다운로드에 20초 남짓 걸렸습니다. 공식 문서는 WSL2를 기준으로 쓰여 있지만 WSL1에서도 version 명령과 페이지 읽기가 문제없이 돌았습니다. 다만 로그 수준을 warn으로 두면 데이터 폴더를 만들지 못했다는 경고가 한 줄 찍혔고, 결과물에는 영향이 없었습니다.

한 가지 걸리는 조건은 glibc 버전입니다. 리눅스 실행 파일은 x86_64 기준 glibc 2.35 이상이 필요해서, 알파인 같은 musl 기반 배포판에서는 실행 자체가 안 됩니다. 우분투 24.04는 2.39라 그대로 됩니다. 도커로 감쌀 때는 debian:bookworm-slim 이상을 쓰라고 README가 안내합니다.

bash · README의 리눅스 설치 명령. 윈도우에서는 WSL 터미널에서 같은 명령을 쓴다.
# 리눅스 또는 윈도우 WSL 안에서
curl -L -o lightpanda https://github.com/lightpanda-io/browser/releases/download/nightly/lightpanda-x86_64-linux
chmod a+x ./lightpanda
./lightpanda version

# 사용 통계 전송 끄기
export LIGHTPANDA_DISABLE_TELEMETRY=true

근거 [1]

첫 실행: fetch로 마크다운 뽑기와 networkidle 대기

가장 먼저 써 볼 명령은 fetch입니다. 주소 하나를 주면 페이지를 불러오고 자바스크립트를 실행한 뒤 결과를 표준 출력으로 내보냅니다. --dump 뒤에 html을 주면 실행 뒤의 DOM을, markdown을 주면 읽기 좋은 마크다운을 받습니다. 에이전트에게 웹 페이지를 넘길 때 HTML 대신 마크다운을 주면 토큰이 크게 줄어서 이 옵션이 특히 쓸모 있습니다.

Lightpanda가 공개해 둔 데모 쇼핑몰 페이지로 해 보면 차이가 바로 보입니다. 이 페이지는 처음에 Loading...만 띄워 두고 상품 정보와 리뷰를 두 번의 XHR 요청으로 나중에 채웁니다. 옵션 없이 fetch를 돌리면 2.29초 만에 끝나지만 결과에는 Loading...만 세 군데 남고 가격은 하나도 없습니다. 기본 대기 기준이 load 이벤트라서 그 뒤에 오는 요청을 기다리지 않기 때문입니다.

같은 명령에 --wait-until networkidle을 붙이면 네트워크 요청이 잠잠해질 때까지 기다린 다음 내용을 뽑습니다. 이번에는 2.05초 만에 244.99달러짜리 배낭과 연관 상품 세 개의 가격까지 모두 나왔습니다. 처음 써 보는 사이트라면 일단 networkidle을 붙이고, 특정 요소가 나타나야 하는 경우에는 --wait-selector로 CSS 선택자를 지정하면 됩니다. 계속 무언가를 불러오는 사이트는 done 조건에 영영 닿지 않으니 --wait-ms로 상한을 두는 편이 안전합니다.

출력 형식은 그 밖에도 여럿입니다. structured_data는 JSON-LD와 오픈그래프, 트위터 카드, 메타 태그를 JSON으로 묶어 주고, semantic_tree는 에이전트가 읽기 좋게 줄인 의미 구조를 줍니다. png와 pdf도 있는데, 렌더링 엔진이 없어서 글자만 배치한 화면이 나옵니다. 아래 두 번째 그림이 그 결과로, 레이아웃과 상품 사진 없이 제목과 가격, 리뷰 글만 세로로 늘어서 있습니다.

터미널에서 lightpanda fetch를 두 번 실행한 결과. 옵션 없이 실행하면 Loading...만 나오고, --wait-until networkidle을 붙이면 $244.99, $79.99, $129.99, $19.99 가격이 나온다
같은 페이지라도 networkidle을 붙여야 나중에 불러오는 가격까지 나온다.BlueBWorks · 원문
Lightpanda의 --dump png 결과. 데모 쇼핑몰의 상품명 Outdoor Odyssey Nomad Backpack 60 liters, 가격 $244.99, 상품 설명과 연관 상품 목록이 이미지 없이 글자로만 배치돼 있다
--dump png 결과. 사진과 레이아웃 없이 글자만 그린다.BlueBWorks · 원문

근거 [1] [3]

에이전트에 붙이는 세 가지 방법: CDP 서버, MCP 서버, PandaScript

기존 자동화 코드가 있다면 serve 명령으로 CDP 서버를 여는 방법이 가장 손이 덜 갑니다. CDP는 크롬 개발자 도구 프로토콜로, Puppeteer와 Playwright가 크롬을 조종할 때 쓰는 통로입니다. lightpanda serve --host 127.0.0.1 --port 9222로 띄운 다음 Puppeteer의 browserWSEndpoint를 ws://127.0.0.1:9222로 바꾸면 나머지 코드는 그대로 둘 수 있다고 README가 설명합니다. --protocol webdriver를 주면 WebDriver BiDi로도 붙습니다.

클로드 코드나 커서 같은 에이전트 도구에 바로 연결하고 싶다면 MCP 서버가 있습니다. MCP 설정 파일에 command로 실행 파일 경로를, args로 mcp를 넣으면 됩니다. 이번에 stdio로 띄워서 도구 목록을 받아 보니 goto, markdown, click, fill, extract, screenshot, structuredData, detectForms, login 등 39개가 나왔습니다. --port를 주면 HTTP로도 열리는데, 이때는 연결마다 쿠키와 페이지가 따로인 세션이 배정돼 여러 에이전트가 같은 프로세스를 나눠 써도 서로의 페이지를 덮어쓰지 않습니다.

세 번째는 Lightpanda 자체 에이전트와 PandaScript입니다. lightpanda agent는 앤트로픽, OpenAI, 제미나이, OpenRouter, Ollama 같은 모델 제공자의 키를 환경 변수에서 찾아 자연어 지시로 브라우저를 움직입니다. 키가 없으면 로컬에서 돌고 있는 Ollama나 llama.cpp 서버를 찾아보고, --no-llm을 주면 슬래시 명령만 받는 입력 창으로 동작합니다. 작업이 끝난 뒤 /save로 저장하면 PandaScript라는 자바스크립트 파일이 남고, 이 파일은 lightpanda run으로 모델 없이 다시 돌릴 수 있습니다.

PandaScript는 직접 써도 됩니다. 해커뉴스 첫 페이지 제목을 뽑는 네 줄짜리 스크립트를 만들어 lightpanda run으로 돌려 보니, 모델 호출 없이 4초 남짓 만에 제목 30개가 JSON으로 나왔습니다. 처음 한 번은 에이전트로 흐름을 잡고, 반복 작업은 저장한 스크립트로 돌리면 토큰 비용 없이 같은 결과를 얻을 수 있다는 것이 공식 문서가 권하는 사용 방식입니다.

터미널에서 hn.js 스크립트 내용을 보여 주고 lightpanda run hn.js를 실행한 결과. count 30과 해커뉴스 상위 제목 세 개가 JSON으로 출력됐다
모델 없이 PandaScript만으로 해커뉴스 제목 30개를 뽑은 결과.BlueBWorks · 원문
javascript · page.extract에 CSS 선택자를 넘기면 일치하는 요소의 글자를 배열로 돌려준다.
// hn.js : lightpanda run hn.js 로 실행
const page = new Page();
await page.goto("https://news.ycombinator.com/");
const data = await page.extract({ titles: [".titleline > a"] });
return { count: data.titles.length, top3: data.titles.slice(0, 3) };

근거 [1] [4]

헤드리스 크롬과 비교: 공개 벤치마크 숫자 읽는 법

README 맨 위의 표는 100페이지를 읽을 때 메모리 최고치 123MB 대 2GB, 걸린 시간 5초 대 46초로 크롬보다 16배 가볍고 9배 빠르다고 적고 있습니다. 이 숫자는 Lightpanda 팀이 직접 잰 것이고, 측정 방법은 별도 벤치마크 문서에 공개돼 있습니다. Go로 만든 크롤러가 데모 사이트의 페이지 933개를 인터넷으로 받아 오는 동안 smem으로 메모리를, ps로 CPU 사용률을 0.1초마다 쟀습니다. 크롬은 143 버전입니다.

README 표의 숫자는 동시에 25개를 돌린 줄에서 나왔습니다. 크롬은 탭 25개로 46.70초에 최고 2.0GB, Lightpanda는 프로세스 25개로 4.81초에 123.0MB였습니다. 하나씩 돌리면 차이가 줄어서, 크롬 탭 1개는 1분 22초에 1.3GB, Lightpanda 1개는 51.68초에 27.2MB입니다. Lightpanda는 탭을 여러 개 열지 못해 프로세스를 여러 개 띄우는 방식으로 비교했다는 점도 문서에 적혀 있습니다. README는 시험 서버를 m5.large로, 상세 문서는 m5.xlarge로 적고 있어 둘이 다릅니다.

데모 쇼핑몰 페이지를 Puppeteer로 100번 불러온 시험에서는 한 번에 평균 16밀리초 대 185밀리초, 메모리 최고치 21.2MB 대 402.1MB였습니다. 이 페이지를 직접 만든 이유에 대해 팀은 Lightpanda가 아직 웹 표준을 다 지원하지 않아서 크롬과 똑같이 실행되는 페이지가 필요했다고 설명합니다. 실제 서비스 사이트에서도 같은 차이가 날지는 각자 대상 사이트로 돌려 봐야 아는 부분입니다.

이 서버의 WSL1에서는 데모 쇼핑몰과 해커뉴스 첫 페이지를 각각 2초대에 읽었고, time 명령이 보고한 최대 메모리는 15MB 안팎이었습니다. WSL1은 메모리를 리눅스와 다른 방식으로 집계하기 때문에 이 숫자는 다른 환경과 바로 견주기보다 대략의 감으로 보는 편이 맞습니다.

Lightpanda README의 벤치마크 표. 100페이지 기준 메모리 최고치 Lightpanda 123MB, 헤드리스 크롬 2GB, 실행 시간 5초와 46초, 그 아래 설치 안내가 이어진다
README의 벤치마크 표와 설치 안내 첫 부분.GitHub lightpanda-io/browser · 원문
시험Lightpanda헤드리스 크롬
933페이지 크롤링, 동시 1개51.68초, 27.2MB1분 22.83초, 1.3GB
933페이지 크롤링, 동시 25개4.81초, 123.0MB46.70초, 2.0GB
데모 쇼핑몰 100회, 1회 평균16ms, 최고 21.2MB185ms, 최고 402.1MB

Lightpanda 팀이 AWS 서버에서 크롬 143과 비교해 공개한 수치. 메모리는 smem PSS 최고치.

근거 [1] [3]

쓰기 전에 알아둘 점: 호환성, 텔레메트리, AGPL 라이선스

가장 먼저 따질 것은 호환성입니다. Lightpanda는 매일 웹 플랫폼 테스트 결과를 공개하고 릴리스마다 지원하는 웹 API를 늘려 가고 있지만, 크롬처럼 모든 사이트가 그대로 돌아간다고 보기는 이릅니다. 복잡한 로그인 흐름이나 캔버스, 화면 좌표에 의존하는 사이트라면 크롬이 여전히 안전합니다. 픽셀 그대로의 스크린샷이 필요한 작업도 렌더링 엔진이 없으니 맞지 않습니다. 반대로 글과 링크, 가격처럼 텍스트를 뽑는 크롤링과 에이전트의 웹 읽기에는 잘 맞습니다.

텔레메트리는 기본으로 켜져 있습니다. 사용 통계를 Lightpanda 쪽으로 보내는데, LIGHTPANDA_DISABLE_TELEMETRY=true 환경 변수를 주면 꺼집니다. 서버에서 돌릴 계획이라면 셸 설정이나 서비스 파일에 미리 넣어 두는 편이 좋습니다. 남의 사이트를 읽을 때는 --obey-robots 옵션으로 robots.txt를 따르게 할 수 있고, 내부망 주소로 새어 나가는 요청은 --block-private-networks로 막을 수 있습니다.

라이선스는 AGPL-3.0입니다. 내 컴퓨터에서 도구로 쓰는 데는 걸릴 일이 거의 없지만, 소스를 고쳐서 네트워크 서비스로 내놓는다면 고친 소스를 공개해야 하는 조건이 붙습니다. 저장소에 별도의 LICENSING.md가 있으니 회사 서비스에 넣을 계획이라면 먼저 읽어 보는 것이 좋습니다. 기여할 때는 CLA 서명이 필요합니다.

이미 Puppeteer나 Playwright로 크롤러를 돌리고 있다면 접속 주소만 바꿔서 같은 스크립트를 한 번 돌려 보는 것이 가장 빠른 판단 방법입니다. 결과가 같고 메모리가 줄면 옮길 이유가 생기고, 빠지는 내용이 있으면 대기 옵션부터 바꿔 보고 그래도 안 되는 사이트만 크롬에 남겨 두면 됩니다.

근거 [1] [2] [5]