2026 OpenClaw 프론트 실전:
원격 Mac에서 게이트웨이 Webhook으로 프리뷰 배포 URL을 받고 Lighthouse·임계·종료 코드·PR 요약까지 한 줄로 재현
대상: 배포 플랫폼의 프리뷰 URL을 원격 Mac으로 보내 Lighthouse CLI와 저장소 임계 JSON으로 게이트하고 PR Markdown으로 요약하는 팀입니다. OpenClaw 게이트웨이는 서명 Webhook·큐·시크릿·NDJSON을 한곳에 모읍니다. 슬러그 2026-openclaw-remote-mac-preview-lighthouse-webhook.html. 연관: Deployments 연동, 배포 훅 스모크, Lighthouse 임계 알림.
프리뷰는 캐시·HTTP/3·지역 때문에 리눅스 러너와 숫자가 갈립니다. 원격 Mac에서 Lighthouse를 돌리고 판정을 PR로 돌리려면 OpenClaw 게이트웨이 Webhook으로 배포 알림을 검증·큐잉하는 단계가 필요합니다. 여기서는 hook → CLI → 임계 JSON → 종료 코드 → Markdown 요약 순서만 고정합니다.
Lighthouse는 Chromium 기준입니다. 같은 Mac에서 Safari·WebKit 스모크(예: Playwright webkit)를 짧게 이어 붙이면 실기 체감과 자동화 게이트를 한 런 id로 맞출 수 있습니다.
01 게이트웨이가 Webhook으로 맡는 일
본문의 preview_url·SHA·PR·벤더 라벨을 파싱한 뒤 HMAC 또는 mTLS로 출처를 확인하고, 비 TLS·알 수 없는 호스트는 거절합니다. Idempotency-Key: ${GIT_SHA}:${OPENCLAW_RUN_ID}:preview-lh로 재전송 중복을 막고, 검증 후에는 Mac 에이전트에 URL·SHA·PR 튜플만 넘깁니다.
02 재현 HowTo 단계
- 식별자 export.
GIT_SHA·PREVIEW_URL·PR_NUMBER·REPO_SLUG·OPENCLAW_RUN_ID를 한 번에 고정합니다. - Webhook 검증. 게이트웨이에서 타임스탬프 드리프트·서명·허용 IP 대역을 통과한 요청만 워커로 넘깁니다.
- 프리뷰 워밍. Lighthouse가 쓸 User-Agent와 동일하게 HTML과 메인 번들에
GET을 두 번 보냅니다.429면 짧게 백오프합니다. - Lighthouse CLI. 예:
npx lighthouse "${PREVIEW_URL}" --only-categories=performance --output=json --output-path=".openclaw/reports/${OPENCLAW_RUN_ID}.lhr.json" --chrome-flags="--headless=new". Chromium 채널은 락파일 또는 환경 변수로 고정합니다. - 임계 로드. 같은 커밋의
perf/thresholds.json(또는 팀 규약 경로)을 읽어 아래 표의 지표와 비교합니다. - 종료 코드 매핑. 스크립트 예외는 1, 임계 미달은 2, 로드 타임아웃·DNS 등 인프라는 3, 전부 통과는 0으로
exit합니다. CI가 이 규약만 알면 머지 큐가 안정됩니다. - PR 요약. 아래 Markdown 템플릿을 채워 코멘트 upsert(숨은 마커
<!-- openclaw-preview-lh:${GIT_SHA} -->권장) 또는 Checks 어노테이션에 동일 문자열을 붙입니다. - 관측 한 줄. OpenClaw NDJSON에
phase=preview_lighthouse·verdict·duration_ms·preview_host를 append하면 토큰·E2E 요약과 같은 런 id로 합류합니다.
# 워밍 예시 (실제 헤더는 벤더 스모크와 동일하게 맞출 것)
curl -fsS -A "${LIGHTHOUSE_UA}" -o /dev/null "${PREVIEW_URL}"
curl -fsS -A "${LIGHTHOUSE_UA}" -o /dev/null "${PREVIEW_URL%/}/_next/static/chunks/main.js" || true
03 임계 JSON 예시와 종료 코드 표
저장소에 버전 관리되는 JSON은 “측정값이 이 선을 넘으면 실패”만 담고, 비밀·URL TTL은 넣지 않습니다. 숫자 단위(lhr 필드명과 일치)를 주석 README에 적어 두면 리뷰어가 diff만으로 의미를 읽습니다.
{
"performance": { "minScore": 0.88 },
"metrics": {
"largest-contentful-paint": { "maxNumericValue": 2800 },
"cumulative-layout-shift": { "maxNumericValue": 0.08 },
"total-blocking-time": { "maxNumericValue": 350 }
}
}
| 지표 | JSON 키(예) | 권장 방향 | 비고 |
|---|---|---|---|
| 성능 점수 | categories.performance.score |
≥ minScore |
가중치 변경에 민감 → 보조 지표와 병행 |
| LCP | audits[largest-contentful-paint].numericValue |
≤ ms 예산 | 프리뷰 콜드 스타트 시 중앙값 비교 권장 |
| CLS | audits[cumulative-layout-shift].numericValue |
≤ 예산 | 광고·폰트 스왑 회귀에 강함 |
| TBT | audits[total-blocking-time].numericValue |
≤ ms 예산 | 메인 스레드 장시간 작업 탐지 |
| 코드 | 의미 | 머지 큐 해석 |
|---|---|---|
| 0 | 모든 임계 통과 | 초록, 요약만 갱신 |
| 1 | 스크립트·파싱 오류 | 즉시 실패, 로그 수정 우선 |
| 2 | 성능 회귀(임계 미달) | 의도적 품질 게이트 실패 |
| 3 | 인프라(타임아웃·DNS·TLS 핸드셰이크) | 재시도·플랫폼 장애 분리 |
Lighthouse 기본 실패는 1입니다. 회귀·인프라를 2·3으로 나누려면 임계 비교 후 exit 2 등을 명시하세요.
04 PR 가독 요약 Markdown 템플릿
코멘트 본문은 네 줄 안팎이 가장 읽힙니다. 숫자·단위·프리뷰 호스트만 바꾸고 나머지 문장은 고정해 팀이 패턴을 외웁니다.
<!-- openclaw-preview-lh:${GIT_SHA} -->
### OpenClaw · 프리뷰 Lighthouse (${OPENCLAW_RUN_ID})
- **판정:** ${VERDICT} · **호스트:** ${PREVIEW_HOST}
- **Perf:** ${PERF_SCORE} (min ${MIN_SCORE}) · **LCP:** ${LCP_MS} ms (max ${LCP_MAX_MS}) · **CLS:** ${CLS} (max ${CLS_MAX})
- **아티팩트:** \`.openclaw/reports/${OPENCLAW_RUN_ID}.lhr.json\` 동일 커밋
- **다음:** WebKit 스모크 ${WEBKIT_STATUS}
05 Safari·WebKit과 자동화 결합
Chromium 측정 직후 동일 PREVIEW_URL에 WebKit 스모크를 짧게 붙이면 Safari 출시 리스크를 같은 Mac 비용으로 덮습니다. NDJSON·PR에 chromium_lab+webkit_smoke 태그를 남기세요. Deployments와 묶는 그림은 연동 글을 참고합니다.
06 403·타임아웃 FAQ
프리뷰에서 Lighthouse가 403을 냅니다
배포 보호(Basic·OIDC·헤더 토큰)·지역 차단·봇 차단이 흔한 원인입니다. 해결은 (1) 스모크와 동일한 Authorization·쿠키를 게이트웨이 환경 변수로만 주입하고 PR 본문에는 절대 붙이지 않기, (2) 원격 Mac 고정 출구 IP를 프리뷰 허용 목록에 추가, (3) 보호를 전역 해제하는 대신 스테이징 전용 호스트를 쓰기 순으로 검토하세요.
간헐적 타임아웃만 올라옵니다
동일 OPENCLAW_RUN_ID로 한 번만 재시도하고, Lighthouse의 대기 시간을 늘리며 Chromium 리비전을 잠급니다. 두 번 연속 타임아웃이면 종료 코드 3으로 기록해 회귀(2)와 구분하세요. 콜드 스타트가 잦은 프리뷰는 최근 세 번의 초록 런 중앙값과 비교하는 편이 단일 골든 숫자보다 안정적입니다.
게이트웨이 없이 Mac만 두면 안 되나요?
가능하지만 서명·멱등·시크릿이 스크립트마다 흩어집니다. 게이트웨이에 모으면 정책이 한곳에 남습니다.