Chrome 헤드리스 모드

Peter Kvitek
Peter Kvitek

2017년, Chrome 59에서는 표시되는 UI 없이 무인 환경에서 브라우저를 실행할 수 있는 헤드리스 모드를 도입했습니다. 기본적으로 Chrome 없이도 Chrome을 실행할 수 있습니다.

헤드리스 모드는 Puppeteer 또는 ChromeDriver와 같은 프로젝트를 통한 브라우저 자동화에 널리 사용되는 모드입니다. 다음은 헤드리스 모드를 사용하여 지정된 URL의 PDF 파일을 만드는 최소한의 명령줄 예입니다.

chrome --headless --print-to-pdf https://developer.chrome.com/

헤드리스 작동 방식

지금 헤드리스의 작동 방식을 검토하기 전에 '이전' 헤드리스의 작동 방식을 이해하는 것이 중요합니다. 이전의 명령줄 스니펫은 --headless 명령줄 플래그를 사용하여 헤드리스가 단지 일반 Chrome 브라우저의 작업 모드일 뿐임을 나타냅니다. 하지만 놀랍게도 이 주장은 사실이 아니었습니다. 실제로 이전 Headless는 동일한 Chrome 바이너리의 일부로 제공되는 별도의 대체 브라우저 구현이었습니다. //chrome의 Chrome 브라우저 코드는 공유하지 않습니다.

별도의 헤드리스 브라우저를 구현하고 유지관리하려면 많은 엔지니어링 오버헤드가 수반되었습니다. 또한 Headless는 별도의 구현이므로 헤드풀 Chrome에는 없는 자체 버그와 기능이 있었습니다. 이로 인해 자동화된 브라우저 테스트가 혼란스러웠습니다. 이 테스트는 헤드풀 모드에서는 통과할 수 있지만 헤드리스 모드에서는 실패할 수 있으며, 그 반대의 경우도 가능합니다.

또한 Headless는 브라우저 확장 프로그램 설치에 의존하는 자동 테스트를 제외했습니다. 다른 브라우저 수준 함수도 마찬가지입니다. Headless에 별도의 자체 구현이 없다면 지원되지 않았습니다.

이제 Chrome팀은 헤드리스 모드와 헤드풀 모드를 통합했습니다.

새로운 Chrome Headless는 더 이상 별도의 브라우저 구현이 아니며 대신 Chrome과 코드를 공유합니다.

Chrome 112부터 새로운 헤드리스 모드를 사용할 수 있습니다. 이 모드에서 Chrome은 플랫폼 창을 만들지만 표시하지는 않습니다. 기존 함수와 향후의 다른 모든 함수는 제한 없이 사용할 수 있습니다.

헤드리스 모드 사용

새로운 헤드리스 모드를 사용하려면 --headless=new 명령줄 플래그를 전달합니다.

chrome --headless=new

현재 이전의 헤드리스 모드는 다음에서 계속 사용할 수 있습니다.

chrome --headless=old

Puppeteer에서

Puppeteer에서 새로운 헤드리스 모드를 선택하려면 다음 단계를 따르세요.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
  headless: 'new',
  // `headless: true` (default) enables old Headless;
  // `headless: 'new'` enables new Headless;
  // `headless: false` enables "headful" mode.
});

const page = await browser.newPage();
await page.goto('https://developer.chrome.com/');

// …

await browser.close();

Selenium-WebDriver에서

Selenium-WebDriver에서 새로운 헤드리스 모드를 사용하려면 다음을 실행하세요.

const driver = await env
  .builder()
  .setChromeOptions(options.addArguments('--headless=new'))
  .build();

await driver.get('https://developer.chrome.com/');

// …

await driver.quit();

다른 언어 바인딩의 사용 예를 포함하여 자세한 내용은 Selenium팀의 블로그 게시물을 참고하세요.

명령줄 플래그

새로운 헤드리스 모드에서는 다음 명령줄 플래그를 사용할 수 있습니다.

--dump-dom

--dump-dom 플래그는 타겟 페이지의 직렬화된 DOM을 stdout에 출력합니다. 예를 들면 다음과 같습니다.

chrome --headless=new --dump-dom https://developer.chrome.com/

이는 curl로 할 수 있는 HTML 소스 코드를 출력하는 것과는 다릅니다. --dump-dom의 출력을 가져오기 위해 Chrome은 먼저 HTML 코드를 DOM으로 파싱하고 DOM을 변경할 수 있는 <script>를 실행한 다음 이 DOM을 직렬화된 HTML 문자열로 다시 변환합니다.

--screenshot

--screenshot 플래그는 타겟 페이지의 스크린샷을 찍어 현재 작업 디렉터리에 screenshot.png로 저장합니다. 이는 --window-size 플래그와 함께 사용할 때 특히 유용합니다.

예를 들면 다음과 같습니다.

chrome --headless=new --screenshot --window-size=412,892 https://developer.chrome.com/

--print-to-pdf

--print-to-pdf 플래그는 대상 페이지를 현재 작업 디렉터리에 output.pdf라는 PDF로 저장합니다. 예를 들면 다음과 같습니다.

chrome --headless=new --print-to-pdf https://developer.chrome.com/

원하는 경우 --no-pdf-header-footer 플래그를 추가하여 인쇄 헤더 (현재 날짜 및 시간 포함)와 바닥글 (URL 및 페이지 번호 포함)을 생략할 수 있습니다.

chrome --headless=new --print-to-pdf --no-pdf-header-footer https://developer.chrome.com/

아니요: 이전에는 --no-pdf-header-footer 플래그 뒤의 기능을 --print-to-pdf-no-header 플래그와 함께 사용할 수 있었습니다. 이전 버전을 사용하는 경우 이전 플래그 이름으로 돌아가야 할 수도 있습니다.

--timeout

--timeout 플래그는 페이지가 계속 로드 중이더라도 --dump-dom, --screenshot, --print-to-pdf가 페이지의 콘텐츠를 캡처하기까지 걸리는 최대 대기 시간 (밀리초)을 정의합니다.

chrome --headless=new --print-to-pdf --timeout=5000 https://developer.chrome.com/

--timeout=5000 플래그는 Chrome에 PDF를 인쇄하기 전에 최대 5초 동안 기다리라고 지시합니다. 따라서 이 프로세스를 실행하는 데 최대 5초가 걸립니다.

--virtual-time-budget

--virtual-time-budget는 시간 종속 코드(예: setTimeout/setInterval)에 대해 '빨리 감기' 역할을 합니다. 페이지가 실제로 시간이 지나간다고 믿도록 하면서 브라우저가 페이지의 코드를 최대한 빠르게 실행하도록 합니다.

사용법을 보여주기 위해 setTimeout(fn, 1000)를 사용하여 매초 카운터를 증가, 로깅, 표시하는 이 데모를 살펴보겠습니다. 다음은 관련 코드입니다.

<output>0</output>
<script>
  const element = document.querySelector('output');
  let counter = 0;
  setInterval(() => {
    counter++;
    console.log(counter);
    element.textContent = counter;
  }, 1_000);
</script>

1초 후에는 페이지에 '1'이 표시되고 2초 후에는 '2' 등으로 표시됩니다. 42초 후 페이지의 상태를 캡처하여 PDF로 저장하는 방법은 다음과 같습니다.

chrome --headless=new --print-to-pdf --virtual-time-budget=42000 https://mathiasbynens.be/demo/time

--allow-chrome-scheme-url

--allow-chrome-scheme-url 플래그는 chrome:// URL에 액세스하는 데 필요합니다. 이 플래그는 Chrome 123부터 사용할 수 있습니다. 예를 들면 다음과 같습니다.

chrome --headless=new --print-to-pdf --allow-chrome-scheme-url chrome://gpu

디버그

Chrome은 헤드리스 모드에서 사실상 표시되지 않으므로 문제를 해결하기가 까다로울 수 있습니다. 헤드리스 Chrome을 헤드풀 Chrome과 매우 유사한 방식으로 디버그할 수 있습니다.

--remote-debugging-port 명령줄 플래그를 사용하여 헤드리스 모드로 Chrome을 실행합니다.

chrome --headless=new --remote-debugging-port=0 https://developer.chrome.com/

이렇게 하면 고유한 WebSocket URL이 stdout에 출력됩니다. 예를 들면 다음과 같습니다.

DevTools listening on ws://127.0.0.1:60926/devtools/browser/b4bd6eaa-b7c8-4319-8212-225097472fd9

그런 다음 헤드리스 Chrome 인스턴스에서 Chrome DevTools 원격 디버깅을 사용하여 헤드리스 대상에 연결하고 검사할 수 있습니다.

  1. chrome://inspect로 이동하여 구성... 버튼을 클릭합니다.
  2. WebSocket URL의 IP 주소와 포트 번호를 입력합니다.
    • 이전 예에서는 127.0.0.1:60926를 입력했습니다.
  3. 완료를 클릭합니다. 모든 탭 및 기타 타겟이 나열된 원격 타겟이 표시됩니다.
  4. 검사를 클릭하여 Chrome DevTools에 액세스하고 페이지의 실시간 뷰를 포함한 원격 헤드리스 타겟을 검사합니다.

Chrome DevTools가 원격 헤드리스 대상 페이지를 검사할 수 있음

의견

새로운 헤드리스 모드에 관한 의견을 기다리겠습니다. 문제가 발생하면 버그를 신고하세요.