Artisan 문제 해결
한눈에 보기
섹션 제목: “한눈에 보기”모든 브리지 오류는 정형화된 예외로 드러납니다. 예외와 메시지를 아래 표와 대조하십시오. 각 행은 정확한 소스 검사를 가리키므로 증상이 아닌 원인을 해결할 수 있습니다.
예외별 진단
섹션 제목: “예외별 진단”ChromeNotAvailableException
섹션 제목: “ChromeNotAvailableException”
chrome-php/chrome is not installed. Install it via: composer require chrome-php/chrome:^1.15
CDP 클라이언트 라이브러리가 오토로더에 없습니다. BrowserPool::getBrowser()는 Chrome을 실행하기 전에 이 예외를 발생시킵니다. 설치 명령을 실행하십시오. 이는 바이너리 누락과는 별개입니다. 라이브러리 검사와 바이너리 검사는 별도의 단계입니다.
ChromeRenderException — 실행 또는 시간 초과
섹션 제목: “ChromeRenderException — 실행 또는 시간 초과”
Chrome renderer failed: <cause>
Chrome이 시작되지 못했거나, 시간이 초과되었거나, 충돌했습니다. 원래 원인은 이전 예외에 담겨 있습니다. 일반적인 원인:
- 바이너리를 찾을 수 없거나 실행할 수 없습니다.
chromium --headless --dump-dom about:blank로 확인하십시오.chrome_binary를 절대 경로로 설정하십시오. - 샌드박스를 초기화할 수 없습니다(컨테이너). 원인에 샌드박스 또는 네임스페이스가 언급됩니다. 샌드박스를 지원하는 컨테이너를 프로비저닝하거나(권장), /integrations/artisan/security-and-operations/.을 읽은 후
no_sandbox: true로 설정하십시오. - 시간 초과. 무거운 문서가
render_timeout을 초과했습니다. 해당 워크로드의 제한 시간을 늘리거나 문서를 줄이십시오. 사용자 대면 경로에서는 서비스 거부와 관련된 트레이드오프를 고려하십시오. - 공유 라이브러리 누락. Chrome이 즉시 종료됩니다. 배포판의 Chrome 의존성 세트를 설치하십시오.
ChromeRenderException — 빈 출력
섹션 제목: “ChromeRenderException — 빈 출력”
Chrome printToPDF returned empty data
Chrome이 시작되었고 printToPDF가 0 바이트를 반환했습니다. 일반적인 원인은 렌더링된 박스를 생성하지 않는 입력(빈 body, 모든 콘텐츠가 display:none)이나 인쇄 도중 발생한 Chrome 충돌입니다. HTML이 보이는 박스로 렌더링되는지 확인하십시오. 호스트 메모리 압박을 확인하십시오.
RuntimeException — Chrome 이전 단계에서 입력 거부됨
섹션 제목: “RuntimeException — Chrome 이전 단계에서 입력 거부됨”| 메시지 포함 내용 | 원인 | 해결 방법 |
|---|---|---|
exceeds maximum allowed size | HTML이 maxHtmlSize 한도를 초과함 | 입력을 줄이거나 max_html_size를 높이십시오(리소스 고갈에 노출되는 표면이 넓어짐) |
oversized base64 data URI | 인라인 base64 ≥ 13 MB | 포함된 자산을 줄이십시오. 더 작은 이미지를 참조하십시오. |
forbidden meta refresh redirect | <meta http-equiv="refresh"> 존재 | 해당 태그를 제거하십시오. 이는 SSRF 탐색 벡터이므로 항상 거부됩니다 |
이러한 예외는 ChromeSecurityPolicy::validate()에서 Chrome에 연결되기 전에 발생하므로, 테스트에서 빠르고 저렴하게 재현할 수 있습니다.
PdfParseException
섹션 제목: “PdfParseException”
Page <n> has no content stream
Chrome이 파서가 페이지를 추출할 수 없는 PDF를 생성했습니다. 이는 드물게 발생하며, Chrome 출력이 잘못되었거나 예상치 못한 구조를 생성하는 Chrome 버전을 가리킵니다. Chrome 버전과 입력을 기록하십시오. 바이너리가 지원되는 Chrome/Chromium 빌드인지 확인하십시오.
원격 자산이 비어 있게 렌더링됨
섹션 제목: “원격 자산이 비어 있게 렌더링됨”이는 버그가 아닙니다. 브리지는 모든 하위 리소스 가져오기를 차단합니다(CSP default-src 'none'와 CDP setBlockedURLs('*') 차단). 원격 <img>, 스타일시트, 글꼴, 스크립트, iframe은 로드되지 않습니다. 자산을 data: URI로 인라인하고, CSS는 defaultCss 또는 <style>을 통해 인라인하십시오. /integrations/artisan/security-and-operations/.에서 네트워크 모델을 참조하십시오.
하단에서 콘텐츠가 잘림
섹션 제목: “하단에서 콘텐츠가 잘림”문서가 두 번째 Chrome 페이지로 넘어갔지만, 브리지는 페이지 0만 가져왔습니다. 자동 맞춤 버퍼가 비정상적으로 긴 리플로를 감당하기에 너무 작았거나, 명시적 높이가 너무 작았습니다. 콘텐츠에 맞는 명시적 높이를 지정하거나, 명시적 높이를 제거하여 안전 버퍼가 있는 자동 맞춤을 사용하십시오. /integrations/artisan/production-usage/.에서 높이 처리를 참조하십시오.
약 100회 렌더링마다 발생하는 지연 시간 급증
섹션 제목: “약 100회 렌더링마다 발생하는 지연 시간 급증”이는 예상된 동작입니다. BrowserPool은 메모리를 제한하기 위해 100회 렌더링마다 Chrome을 다시 시작합니다. notice 수준의 로그 행에는 렌더링 횟수와 함께 다시 시작이 기록됩니다. 이를 인시던트가 아니라 SLO에서 알려진 주기적 비용으로 취급하십시오. 100회 렌더링보다 잦은 다시 시작 빈도는 문서가 예상보다 무겁다는 뜻입니다.
긴 배치 동안 메모리가 증가함
섹션 제목: “긴 배치 동안 메모리가 증가함”BrowserPool은 100회 렌더링마다 다시 시작하여 증가를 제한하지만, 매우 오래 실행되는 워커에서는 여전히 누적될 수 있습니다. 큰 배치 사이에 close()를 호출하여 Chrome 프로세스를 일찍 재활용하고, 워커를 호스트 메모리 제한 내에서 실행하십시오.
진단 체크리스트
섹션 제목: “진단 체크리스트”- 신뢰할 수 있는 최소 HTML 조각으로 재현하여 입력을 환경과 분리하십시오.
- 호스트에서 워커 사용자 권한으로
chromium --headless --dump-dom about:blank을 실행하십시오. - PSR-3 로거를 주입하고
info/notice행(바이너리 경로, 다시 시작 횟수)을 읽으십시오. - 패키지
chrome-php/chrome이 설치되어 있는지 확인하십시오.BrowserPool::getBrowser()가ChromeNotAvailableException을 던지지 않으면 설치되어 있는 것입니다. - 근본적인 Chrome 원인은 예외의 이전 예외에서 확인하십시오.
참고 항목
섹션 제목: “참고 항목”- 설치: /integrations/artisan/install/
- 구성: /integrations/artisan/configuration/
- 보안 및 운영: /integrations/artisan/security-and-operations/
- Chrome 렌더러 설정: /integrations/artisan/chrome-renderer-setup/
- 프로덕션 사용: /integrations/artisan/production-usage/