SSD Nodes Learn 🎉 VPS $5.50/월부터
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-21

VPS에서 Moli 헤드리스 브라우저 자가 호스팅하기

소규모 VPS에서 Headless Chrome의 높은 메모리 점유율 문제를 해결하는 Moli 설치 방법을 안내합니다. CDP를 활용해 기존 에이전트와 연동하는 방법과 GUI 미지원 등 실제 운영 시 고려해야 할 기술적 제약 사항을 상세히 정리했습니다.

소규모 VPS에 적합한 헤드리스 브라우저

Moli는 AI 에이전트를 위한 헤드리스 브라우저이며, 헤드리스 Chrome을 실행하기 어려운 VPS 환경에서도 자가 호스팅이 가능할 만큼 가볍습니다. 이 브라우저 엔진은 Rust로 작성되었으며 Chromium을 단순히 감싼 형태가 아닙니다. 자동화 라이브러리가 이미 지원하는 Chrome DevTools Protocol(CDP)을 그대로 사용합니다. 바이너리 하나를 설치하고 moli serve을 실행한 뒤, Playwright나 에이전트 코드에서 http://127.0.0.1:9222을 가리키기만 하면 됩니다.

설치하기 전에 트레이드오프를 먼저 확인하십시오. 이 프로젝트는 GUI 브라우저, GPU 컴포지터, Chrome과의 픽셀 단위 일치, 고충실도 Canvas나 미디어 재생 기능을 지원하지 않는다는 점을 명확히 밝히고 있습니다. 이러한 기능이 필요한 페이지는 정상적으로 동작하지 않습니다. Playwright에서 실제 Chrome을 사용하는 방식이 여전히 대안이며, 마지막 섹션에서 어떤 페이지에 Chrome이 필요한지 판단하는 방법을 설명합니다.

아래의 모든 명령어는 2026년 8월 기준으로 확인된 프로젝트의 README 및 공개된 스킬 파일에서 가져왔습니다. 차트에 포함된 모든 수치는 본 사이트의 측정값이 아닌 프로젝트 측에서 자사 엔진에 대해 발표한 수치이며, 각 차트 캡션에 명시되어 있습니다. 엔진 선택을 고민 중이라면 VPS 에이전트용 헤드리스 브라우저에 대한 더 넓은 범위의 조사 내용을 참고하십시오.

Headless Chrome은 왜 그렇게 많은 메모리를 사용합니까?

Chrome은 멀티 프로세스 브라우저입니다. 각 탭과 교차 사이트 iframe은 고유한 렌더러 프로세스를 가지며, 모든 렌더러는 자체 V8 힙과 그래픽 버퍼를 유지합니다. 이러한 설계는 탭 하나가 충돌해도 전체 창이 닫히지 않아야 하는 데스크톱 환경에는 적합합니다. 하지만 2 GB VPS 환경에서는 단 한 번의 브라우징 단계가 실제 실행 중인 애플리케이션보다 더 많은 메모리를 소모할 수 있음을 의미합니다.

이 프로젝트는 4개의 엔진을 사용하여 192개의 혼합된 공개 URL을 크롤링하고 그 결과를 발표했습니다.

ChartMixed public web crawl, 192 URLs, figures published by the Moli project
The data behind this chart
[
  {
    "engine": "Moli",
    "useful_pages": 103,
    "median_rss_mib": 73
  },
  {
    "engine": "Chrome Headless",
    "useful_pages": 101,
    "median_rss_mib": 773
  },
  {
    "engine": "Lightpanda",
    "useful_pages": 85,
    "median_rss_mib": 40
  },
  {
    "engine": "Obscura",
    "useful_pages": 57,
    "median_rss_mib": 39
  }
]

Chrome Headless는 101개의 유용한 페이지를 반환했고 Moli는 103개를 반환했으므로, 해당 샘플에서 두 엔진은 웹의 거의 동일한 비율을 읽어 들였습니다. 메모리 사용량은 두 엔진이 확연히 차이 나는 지점입니다. Chrome의 중앙값 RSS(resident set size, 프로세스가 실제로 RAM에 점유하는 메모리)는 773 MiB인 반면, Moli는 73 MiB입니다. 이러한 결과는 프로세스 아키텍처에서 기인하므로 신뢰할 수 있습니다. 귀하의 페이지에서 나타나는 정확한 비율을 미리 단정해서는 안 됩니다.

사용자를 괴롭히는 것은 중앙값이 아니라 최댓값입니다. 2 GB 서버의 메모리가 부족해지면 커널은 프로세스 하나를 선택해 강제로 종료하며, 해당 기록은 dmesg -T 또는 journalctl -k에 남습니다.

Out of memory: Killed process 4211 (chrome) total-vm:2318936kB, anon-rss:1418324kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:3540kB oom_score_adj:0

귀하의 에이전트는 해당 로그 라인을 직접 보지 못합니다. 대신 응답을 멈춘 브라우저를 보게 되며, 보통 page.goto: Page crashed과 같은 Playwright 오류나 대상이 닫혔다는 메시지로 나타납니다. 오류 메시지 어디에도 메모리 관련 언급이 없기 때문에, 소규모 서버에서 에이전트가 무작위로 실패할 경우 가장 먼저 OOM(out of memory) 킬러를 확인해야 합니다. 최댓값에 맞춰 리소스를 산정하는 것은 에이전트 VPS를 위한 RAM 및 CPU 선택과 같은 작업입니다.

Moli 바이너리 설치 및 특정 버전 고정

이 프로젝트는 GitHub releases를 통해 셸 설치 프로그램과 미리 빌드된 tarball을 배포합니다. 2026년 8월 기준으로 최신 릴리스는 2026년 8월 18일에 게시된 1.0.1 버전입니다. 이 가이드에 인용된 벤치마크 수치는 프로젝트 측에서 0.1.1 버전을 기준으로 측정한 것이므로, 설치할 빌드에 대한 보장이 아닌 엔진의 대략적인 성능 지표로 참고하십시오.

버전을 고정하십시오. 항상 latest를 확인하는 설치 프로그램을 사용하면 다음 재빌드 시 에이전트가 다른 브라우저 엔진으로 변경될 수 있습니다. 브라우저 동작의 변화는 예기치 않게 발견하기보다 계획을 세워 적용해야 하는 변경 사항입니다.

셸 설치 프로그램은 가장 빠르게 설치하는 방법이며, 실행하기 전에 내용을 읽어볼 가치가 있습니다.

curl --proto '=https' --tlsv1.2 -fsSL \
  -o /tmp/moli-installer.sh \
  https://github.com/lexmount/moli/releases/download/v1.0.1/moli-installer.sh
less /tmp/moli-installer.sh
sh /tmp/moli-installer.sh

스크립트를 실행하기 전에 내용을 읽어보십시오. 분량이 짧습니다. 이 스크립트는 uname -m에서 아카이브를 선택한 다음, 단일 바이너리를 ~/.local/bin에 압축 해제합니다. x86_64 환경에서는 moli-x86_64-unknown-linux-gnu.tar.gz를 사용하고, Arm 서버에서는 aarch64 아카이브를 사용하므로 Arm 및 x86 VPS 플랜 모두 지원됩니다. 다른 위치에 설치하려면 MOLI_INSTALL_DIR을 설정하십시오. 스크립트가 버전을 결정하는 방식을 확인하십시오. 스크립트를 가져온 태그가 아니라 최신 릴리스를 선택합니다. 처음 살펴볼 때는 괜찮지만, 재현 가능한 재빌드를 원한다면 적절하지 않습니다.

따라서 영구적인 환경을 구축할 때는 설치 프로그램이 수행하는 작업을 직접 수동으로 실행하고 아카이브 이름을 정확히 지정하십시오. 이 방식은 시스템 서비스가 접근할 수 있는 위치에 바이너리를 배치하는 방법이기도 하며, 다운로드한 스크립트를 파이프로 셸에 전달하는 과정을 생략할 수 있습니다.

cd /tmp
curl --proto '=https' --tlsv1.2 -fsSLO \
  https://github.com/lexmount/moli/releases/download/v1.0.1/moli-x86_64-unknown-linux-gnu.tar.gz
mkdir -p moli-pkg
tar -xzf moli-x86_64-unknown-linux-gnu.tar.gz -C moli-pkg --strip-components=1
sudo install -m 0755 moli-pkg/moli /usr/local/bin/moli
moli --version

moli --version을 사용하여 고정한 버전을 출력하는 것이 전체 확인 과정입니다. 설치 프로그램 직후에 moli: command not found가 발생한다면 설치 디렉터리가 PATH에 포함되지 않은 것입니다. 설치 프로그램은 추가해야 할 디렉터리 이름을 출력하는 줄을 표시합니다.

moli fetch를 이용한 일회성 추출

에이전트가 브라우저에 부여하는 작업 중 상당수는 "이 URL을 불러와서 내용을 알려줘"라는 단순한 요청입니다. 이런 작업에는 서버가 전혀 필요하지 않습니다. moli fetch은 엔진을 시작하고, 페이지 하나를 불러온 뒤, 아티팩트 하나를 표준 출력으로 내보내고 종료합니다. 따라서 호출 사이에 메모리를 점유하는 것이 없습니다.

moli fetch --dump markdown --wait-until networkidle https://example.com
moli fetch --dump semantic_tree_text --wait-selector "main" https://example.com
moli fetch --dump json --wait-until networkidle https://example.com > page.json

첫 번째 명령은 페이지를 Markdown으로 출력하며, # Example Domain로 시작합니다. Markdown은 마크업을 제거하고 텍스트만 남기므로 모델에 전달하기 가장 효율적인 형식입니다. semantic_tree_text은 역할과 구조를 유지합니다. 이는 링크가 본문만큼 중요한 내비게이션 중심 페이지에서 유용합니다. --dump json는 HTTP 상태와 요청 추적 정보를 포함하므로, 가져오기 결과가 비어 있고 그 이유를 확인해야 할 때 사용하십시오.

대기 전략은 콘텐츠를 가져올지, 아니면 빈 껍데기만 가져올지를 결정합니다. --wait-until networkidle는 네트워크가 조용해지면 반환합니다. --wait-until domstable은 DOM 변경이 멈추면 반환합니다. 이는 백그라운드에서 폴링이 계속되어 네트워크가 조용해지지 않는 페이지에서 더 나은 선택입니다. --wait-selector은 지정한 선택자(selector)를 기다립니다. 이는 가져오려는 페이지의 정보를 알고 있는 유일한 전략이며, 대상 페이지를 알고 있을 때 가장 신뢰할 수 있는 방법입니다.

스크린샷과 PDF는 실제 레이아웃이 필요하며, 레이아웃은 기본적으로 꺼져 있습니다:

moli fetch --layout --dump screenshot https://example.com > page.png
moli fetch --layout --dump screenshot_full https://example.com > full-page.png
moli fetch --layout --dump pdf https://example.com > page.pdf

README는 기본 레이아웃 정책을 LayoutPolicy::Mock로 명시합니다. 레이아웃과 페인트는 브라우저 작업 중 비용이 많이 드는 절반을 차지하므로, 기하학적 구조는 가짜로 처리되고 아무것도 그려지지 않습니다. 위에서 언급한 메모리 수치가 낮은 이유는 바로 이 기본 설정 때문입니다. 또한 PNG가 비어 있다면 페이지가 깨진 것이 아니라 --layout 플래그가 누락되었을 가능성이 큽니다.

사용자가 직접 선택한 URL이 아니라 에이전트가 발견한 URL을 처리할 때는 --block-private-networks을 추가하십시오. 페이지에서 읽은 링크를 따라가는 에이전트는 클라우드 인스턴스 자격 증명을 위한 http://169.254.169.254/이나, 웹에 노출되어서는 안 될 localhost의 데이터베이스 포트를 가져오도록 유도될 수 있습니다. 이 플래그는 사설 주소 공간으로의 내비게이션을 거부하며, --block-cidrs는 이를 더욱 제한합니다. 작업이 페이지 하나를 읽는 것이 아니라 크롤링하는 형태라면, 해당 파이프라인의 구성은 자체 호스팅 Firecrawl 대안에서 다루며, 그 이전 단계인 URL 탐색은 에이전트를 위한 SearXNG 기반 검색 기술에서 설명합니다.

CDP를 통해 Moli에 에이전트 연결하기

여러 단계에 걸쳐 탐색하고 클릭하는 에이전트의 경우, 대신 서버를 실행하십시오.

moli serve --host 127.0.0.1 --port 9222

127.0.0.1와 포트 9222는 기본값이므로, moli serve만 입력해도 루프백에만 바인딩됩니다. 하지만 영구적인 설정이라면 두 값을 모두 명시하십시오. 서비스 파일을 읽는 다음 사람이 기본값을 기억할 필요가 없도록 하기 위함입니다.

클라이언트를 연결하기 전에 서버를 확인하십시오:

curl -s http://127.0.0.1:9222/json/version

정상적인 서버는 webSocketDebuggerUrl 필드를 포함한 JSON 객체로 응답하며, 해당 URL이 CDP 클라이언트가 연결할 대상입니다. curl: (7) Failed to connect to 127.0.0.1 port 9222: Connection refused은 아무것도 수신 대기 중이지 않다는 뜻이므로, 서버를 시작한 터미널을 확인하거나 서비스로 등록된 경우 journalctl -u moli -n 50을 확인하십시오. /json/list은 열려 있는 타겟을 나열하며, /json/protocol는 현재 빌드에서 구현된 도메인을 나열합니다. 이를 통해 의존하는 CDP 메서드가 이 빌드에 존재하는지 확인할 수 있습니다.

Playwright는 자체 브라우저를 실행하는 대신 해당 엔드포인트에 연결합니다:

import { chromium } from "playwright";

const browser = await chromium.connectOverCDP("http://127.0.0.1:9222");
const context = browser.contexts()[0];
const page = context.pages()[0] ?? await context.newPage();

await page.goto("https://example.com");
console.log(await page.locator("body").innerText());

await browser.close();

중요한 줄은 chromium.launch()이 아니라 connectOverCDP입니다. 여기에는 자식 Chromium 프로세스가 없으므로, executablePath--no-sandbox과 같은 일반적인 컨테이너 플래그는 적용되지 않습니다. 같은 이유로 프록시, 쿠키, 사용자 에이전트 설정은 Moli 서버의 자체 플래그로 전달해야 합니다. 전체 Chrome 프로토콜이 아닌 선별된 CDP 지원을 예상하십시오. 명시적인 지원되지 않는 메서드 오류는 엔진의 경계일 뿐, 코드의 버그가 아닙니다.

두 가지 서버 플래그가 에이전트의 기능을 결정합니다. --layout는 좌표 클릭과 스크린샷에 필요한 실제 지오메트리를 활성화합니다. --resource는 선택적인 이미지, 폰트, 미디어를 가져오며 페이지 로드 시마다 대역폭과 메모리를 소모하므로, 페이지에서 반드시 필요하다는 것이 증명되기 전까지는 끄십시오. --profile-dir은 실행 간에 쿠키와 저장소를 유지하며, 이 옵션이 없으면 모든 실행은 일회성으로 처리됩니다.

ChartOne agent episode, Moli against Chromium, figures published by the Moli project
The data behind this chart
[
  {
    "engine": "Moli",
    "cdp_ready_ms": 34.85,
    "peak_pss_mib": 102.46,
    "processes": 1
  },
  {
    "engine": "Chromium",
    "cdp_ready_ms": 169.37,
    "peak_pss_mib": 348.82,
    "processes": 11
  }
]

프로젝트의 샘플 에이전트 워크로드에서 Moli는 34.85 ms 만에 CDP 연결을 수락했습니다(Chromium은 169.37 ms). 최대 PSS(공유 페이지를 프로세스 간에 분할하여 계산한 메모리 사용량)는 102.46 MiB를 기록했습니다(Chromium은 348.82 MiB). 구조적인 차이는 마지막 열에 나타납니다. 1개의 프로세스 대 11개입니다. 하나의 프로세스는 systemd가 관리하고 cgroup으로 제한할 대상이 하나라는 의미이며, 이는 다음 섹션을 짧게 만드는 이유입니다.

moli serve를 루프백에서 systemd 서비스로 실행하기

에이전트가 대기 중인 브라우저를 필요로 할 때 서버를 서비스로 실행하십시오. 그렇지 않은 경우에는 moli fetch을 계속 사용하여 URL당 실행하십시오. 유휴 상태의 서버도 메모리를 점유하기 때문입니다.

포트 9222를 공용 인터페이스에 노출하지 마십시오. CDP에는 어떠한 인증 단계도 없습니다. 해당 포트에 접근할 수 있는 사람은 누구나 브라우저를 제어할 수 있으며, 프로필 디렉터리에 있는 쿠키를 포함하여 브라우저가 접근할 수 있는 모든 정보를 읽을 수 있습니다. 127.0.0.1에만 유지하십시오. SSH 터널(ssh -L 9222:127.0.0.1:9222 user@your-vps)이나 사설 VPN 인터페이스를 통해 다른 머신에서 접근하고, 에이전트가 터널의 자기 측에서 http://127.0.0.1:9222에 연결하도록 하십시오.

서비스 사용자를 생성한 다음 유닛 파일을 작성하십시오:

sudo useradd --system --home-dir /var/lib/moli --shell /usr/sbin/nologin moli

/etc/systemd/system/moli.service을 작성하십시오:

[Unit]
Description=Moli headless browser CDP server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=moli
Group=moli
ExecStart=/usr/local/bin/moli serve --host 127.0.0.1 --port 9222 --profile-dir /var/lib/moli/profile --block-private-networks
Restart=on-failure
RestartSec=2
StateDirectory=moli
MemoryAccounting=yes
MemoryMax=768M
NoNewPrivileges=yes
PrivateTmp=yes
ProtectHome=yes
ProtectSystem=strict

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now moli.service
systemctl status moli.service
curl -s http://127.0.0.1:9222/json/version

systemctl statusactive (running)을 표시해야 하며, curl는 discovery JSON을 반환해야 합니다. ProtectSystem=strict는 이 유닛에 대해 전체 파일 시스템을 읽기 전용으로 마운트합니다. 이것이 StateDirectory=moli이 여기서 선택 사항이 아닌 이유입니다. 이는 서비스 사용자가 소유한 /var/lib/moli을 생성하고 해당 경로를 쓰기 가능하게 만듭니다. journalctl -u moli에서 권한 오류로 시작했다가 종료되는 유닛은 거의 항상 ProtectSystem가 읽기 전용으로 만든 곳에 쓰기를 시도하는 경우이므로, 해당 경로를 상태 디렉터리 아래로 옮기십시오.

MemoryMax=768M은 애플리케이션과 함께 실행해도 안전하게 만드는 요소입니다. 유닛은 자체 cgroup을 가지며, 해당 cgroup이 제한을 초과하면 커널은 그 안의 프로세스를 종료하고 나머지 시스템은 그대로 둡니다. 저널에 기록된 내용은 다음과 같습니다:

moli.service: A process of this unit has been killed by the OOM killer.

해당 줄을 사이징 신호로 읽으십시오. 페이지가 계획보다 무겁거나 제한이 너무 낮은 경우입니다. 다음 섹션에서 다룰 실제 페이지 측정값을 기반으로 숫자를 설정하십시오. 동일한 계정 플래그가 서버의 다른 모든 서비스를 제한하며, systemd로 메모리 및 CPU 제한하기를 통해 나머지 서비스에도 적용할 수 있습니다.

최대 메모리 사용량 직접 측정하기

공개된 수치는 다른 사람의 하드웨어와 다른 페이지를 기준으로 측정된 것입니다. 최대 메모리 사용량은 서버의 생존 여부를 결정하며, 이는 전적으로 어떤 데이터를 로드하느냐에 따라 달라집니다. 서버 규모를 산정하기 전에 반드시 직접 측정하십시오.

일회성 요청의 경우 time 바이너리를 사용하십시오. 이는 셸 내장 명령어보다 훨씬 더 많은 정보를 제공합니다.

sudo apt update && sudo apt install -y time
/usr/bin/time -v moli fetch --dump markdown --wait-until networkidle https://example.com > /dev/null

출력 결과의 마지막에는 Maximum resident set size (kbytes)를 포함한 리소스 통계 블록이 표시됩니다. 이 값을 1024로 나누면 MiB 단위가 됩니다. example.com 대신 에이전트가 실제로 방문하는 10개의 페이지를 대상으로 실행하고, 평균값이 아닌 최악의 결과값을 기준으로 삼으십시오. OOM killer는 최대 사용량에 반응하기 때문입니다.

서비스의 경우 커널이 cgroup을 위해 유지하는 카운터를 확인하십시오.

cat /sys/fs/cgroup/system.slice/moli.service/memory.peak
systemd-cgtop -m

memory.peak는 바이트 단위의 수치이며, 해당 유닛이 마지막으로 시작된 이후의 최고 사용량(high-water mark)을 나타냅니다. 따라서 재시작하면 이 값은 초기화됩니다. 이 수치는 MemoryMax가 확보해야 할 최소 메모리이며, 아직 방문하지 않은 가장 무거운 페이지를 처리할 여유 공간까지 고려해야 합니다. systemd-cgtop -m은 유닛별 실시간 사용량을 보여주며, 현재 서버에서 어떤 서비스가 가장 많은 메모리를 점유하고 있는지 가장 빠르게 확인할 수 있는 방법입니다.

Moli는 어디에서 실패하며, 어떤 경우에 여전히 Chrome이 필요한가?

이 프로젝트는 1,308개의 비교 가능한 브라우저 자동화 작업을 벤치마크하고 여러 엔진에 대한 점수를 공개합니다.

ChartLexbench headless browser suite, 1,308 tasks, figures published by the Moli project
The data behind this chart
[
  {
    "engine": "Chrome",
    "success_rate_pct": 99.85
  },
  {
    "engine": "Moli 0.1.1",
    "success_rate_pct": 81.88
  },
  {
    "engine": "Kitesurf",
    "success_rate_pct": 62.08
  },
  {
    "engine": "Lightpanda",
    "success_rate_pct": 53.29
  },
  {
    "engine": "Obscura",
    "success_rate_pct": 44.88
  }
]

5개의 엔진 전반에서 Moli 0.1.1은 작업의 81.88 퍼센트를 완료했으며, 참조 엔진인 Chrome은 99.85 퍼센트를 완료했습니다. 이는 프로젝트가 자체 제품군을 대상으로 스스로 점수를 매긴 것이므로, 독립적인 결과라기보다는 하나의 주장으로 읽어야 합니다.

실질적인 해석은 간단합니다. Chrome이 완료한 작업 중 대략 5개 중 1개꼴로 Moli에서 실패했습니다. 만약 에이전트가 직접 제어하는 고정된 페이지 집합만 방문한다면, 이 비율은 큰 의미가 없습니다. 해당 페이지들은 작동하거나 작동하지 않거나 둘 중 하나이며, 오늘 오후 중으로 바로 확인할 수 있기 때문입니다. 하지만 에이전트가 개방된 웹을 탐색한다면, 이는 설계 시 반드시 고려해야 할 실제 실패율입니다.

무엇이 실패하는지는 프로젝트가 명시한 범위 내에서 예측 가능합니다.

  • 인터페이스를 DOM이 아닌 Canvas 요소에 그리는 애플리케이션: Canvas 충실도는 명시적으로 범위 밖입니다.
  • WebGL이나 GPU 컴포지팅이 필요한 모든 것: GPU 컴포지터가 없기 때문입니다.
  • DRM으로 보호되는 영상 및 고사양 미디어 재생.
  • Chrome과 픽셀 단위로 정확히 일치하는지 확인하는 시각적 테스트: Chrome과의 동일성 유지는 목표가 아닙니다.

프로젝트가 언급한 또 다른 수치인 161만 2천 개의 웹 플랫폼 테스트 통과는 표준 준수 범위에 대한 설명입니다. 이는 에이전트가 방문할 사이트에 대한 보장이 아닙니다. 페이지가 잘 지원되는 표준만을 사용하더라도 봇 탐지에서 실패할 수 있으며, 어떠한 엔진 점수도 이를 보장하지 않습니다.

따라서 설계 시 폴백(fallback)을 유지하십시오. 모든 URL을 먼저 Moli로 보내십시오. 페이지가 비어 있거나 선택자가 나타나지 않으면, 해당 URL 하나만 Playwright로 실제 Chrome을 구동하여 재시도하십시오. 더 큰 사양의 머신을 사용하거나 773 MiB 프로세스를 감당할 수 있는 일정에 맞춰 실행하면 됩니다. 대부분의 에이전트는 일반적인 페이지에서 대부분의 시간을 보내므로, 가벼운 엔진이 전체 물량을 처리하고 무거운 엔진은 예외적인 경우를 처리하도록 구성하십시오.

FAQ

Moli가 제 에이전트를 위한 headless Chrome을 대체할 수 있습니까?

페이지 읽기, 텍스트 추출, 일반적인 클릭 작업의 경우 대체로 가능합니다. 프로젝트 자체 벤치마크인 1,308개 작업에서 Moli는 81.88%의 성공률을 기록했으며, Chrome은 99.85%를 기록했습니다. 즉, 약 5개 작업 중 1개는 Moli가 지원하지 않는 기능이 필요합니다. Canvas로 렌더링되는 애플리케이션, WebGL, DRM 비디오가 알려진 한계점입니다. 모든 것을 되돌리기보다는 해당 URL만 실제 Chrome으로 라우팅하십시오.

VPS에서 Moli는 어느 정도의 RAM을 필요로 합니까?

프로젝트 보고서에 따르면 192개 URL 크롤링 시 중앙값 RSS는 73 MiB이며, 샘플 에이전트 에피소드에서 최대 PSS는 102.46 MiB입니다. 반면 headless Chrome의 중앙값은 773 MiB입니다. 이는 해당 페이지에 명시된 수치입니다. 일회성 사용 시에는 /usr/bin/time -v을 사용하여 moli fetch 호출 전후를 측정하거나, 서비스 운영 시에는 /sys/fs/cgroup/system.slice/moli.service/memory.peak를 확인한 뒤, 관측된 최악의 수치보다 높게 MemoryMax을 설정하십시오.

포트 9222를 인터넷에 노출해도 안전합니까?

아니요. CDP는 인증 기능이 없으므로 해당 포트에 접근할 수 있는 사람은 누구나 브라우저를 제어하고 브라우저가 접근할 수 있는 모든 정보를 읽을 수 있습니다. --host 127.0.0.1 상태를 유지하고, SSH 터널이나 사설 VPN 인터페이스를 통해 다른 머신에서 엔드포인트에 접근하십시오. 다른 주소에 바인딩해야 한다면 사설 인터페이스에 배치하고 방화벽으로 접근을 제어하십시오.

스크린샷이 비어 있거나 클릭이 엉뚱한 곳을 누르는 이유는 무엇입니까?

레이아웃은 기본적으로 꺼져 있습니다. README에 따르면 기본 정책은 LayoutPolicy::Mock이므로 요소의 기하학적 구조가 실제와 다르며, 페이지의 박스 모델에 의존하는 모든 기능이 작동하지 않습니다. 서버를 moli serve --layout으로 시작하거나 moli fetch--layout를 추가하면 스크린샷과 좌표 경로가 정상적으로 작동합니다. 이미지가 누락되는 경우는 다른 플래그인 --resource과 관련이 있습니다.

어떤 버전의 Moli를 설치해야 합니까?

특정 버전을 고정하고 기록해 두십시오. 2026년 8월 기준 현재 릴리스는 1.0.1이지만, 프로젝트가 게시한 벤치마크 수치는 0.1.1 버전에서 측정된 것이므로 다른 사람과 결과를 비교할 때 두 버전을 혼용해서는 안 됩니다. 최신 릴리스를 자동으로 가져오는 셸 설치 프로그램에 의존하지 말고, 해당 태그의 moli-x86_64-unknown-linux-gnu.tar.gz을 다운로드하여 직접 바이너리를 설치한 뒤 moli --version로 확인하십시오.