Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Headless Chrome의 사용방법

지난 4월 Chrome에 headless 모드가 추가되었다. 여기서 Headless 모드라는 것은 보통 웹 브라우저가 GUI로 동작하게 되는데 GUI가 없이 프로그램상으로만 돌리는 것을 의미한다. 실제 브라우저와 같게 동작하므로 JavaScript도 잘 동작하고 웹사이트를 크롤링하거나 스크린숏을 찍을 때 유용하고 브라우저 테스트를 할 때도 훨씬 빠르게 돌릴 수 있다.

그동안 headless 브라우저의 유용함을 알린 것은 PhantomJS이다. PhatomJS는 WebKit 기반의 headless 브라우저인데 사용하기 편하고 API로도 이용할 수 있어서 PhatomJS의 등장 이후 브라우저 테스트나 크롤링 등에서 많은 것들이 달라졌다. 하지만 Chrome이 직접 headless 모드를 추가함으로써 더는 PhantomJS의 의미가 없으므로 메인테이너에서 물러나겠다고 공지가 된 바 있다.

Chrome의 Headless 모드

Headless 모드는 Chrome 59부터 지원한다.(Linux, macOS는 59부터이고 Windows는 60부터 지원한다.) 이 글을 쓰는 현재 크롬 Stable의 최신 버전은 58이고 Chrome Canary는 61이다. 그래서 현재는 Headless를 사용하려면 Chrome Canary를 사용해야 한다.

사용방법은 Getting Started with Headless Chrome에 아주 잘 나와 있는데 이를 토대로 내용을 정리한다. 앞으로는 PhantomJS 대신 Headless Chrome을 사용해야 하므로 어떻게 사용하고 어디까지 지원하는지 파악하기 위해서 테스트를 해보았다.

Headless 모드의 사용

headless 모드를 사용한다는 것은 CLI에서 사용하겠다는 의미이므로 macOS에 설치된 크롬(혹은 크롬 Canary)를 사용해야 한다. Bash를 사용한다면 다음과 같이 설치된 크롬에 대한 별칭을 만들어서 CLI에서 사용할 수 있다.

$ alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
$ alias chrome-canary="/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary"

아직 크롬은 58 버전이므로 여기서는 chrome-canary를 사용한다.

DOM 출력

$ chrome-canary --headless --dump-dom https://blog.outsider.ne.kr

[0528/204228.632373:WARNING:dns_config_service_posix.cc(154)] dns_config has unhandled options!
<body id="tt-body-pages">
......

Headless 모드를 사용하려면 --headless 플래그를 지정해야 한다. 문서상으로는 현재는 --disable-gpu도 같이 지정해야 한다고 나와 있는데 Chrome Canary 61에서는 이 부분이 해결되었는지 없어도 잘 동작한다. 여기서는 DOM을 가져와야 하므로 --dump-dom를 지정했다. 출력된 DOM을 확인해 보면 서버에서 내려준 HTML만 받은 것이 아니라 JavaScript까지 다 동작한 최종 HTML을 받을 것을 확인할 수 있다.(여기서는 HTML이 너무 길어서 생략했다.) --dump-dom은 정확히는 document.body.innerHTML를 출력한다.

PDF로 저장

$ chrome-canary --headless --print-to-pdf https://blog.outsider.ne.kr
[0528/205117.667628:WARNING:dns_config_service_posix.cc(154)] dns_config has unhandled options!
[0528/205127.355566:INFO:headless_shell.cc(464)] Written to file output.pdf.

output.pdf로 저장되는데 이를 열어보면 PDF로 인쇄된 내용을 확인할 수 있다.(블로그의 프린트용 CSS도 조정 좀 해야겠네. ㅠ)

내 블로그가 인쇄된 PDF


스크린샷 저장

$ chrome-canary --headless --screenshot https://blog.outsider.ne.kr
[0528/205558.630395:WARNING:dns_config_service_posix.cc(154)] dns_config has unhandled options!
[0528/205607.521082:INFO:headless_shell.cc(464)] Written to file screenshot.png.

--screenshot 플래그를 지정하면 스크린숏을 저장할 수 있다. 자동으로 screenshot.png에 저장이 되고 다음과 같이 headless로 스크린숏을 지정할 수 있다.

headless chrome으로 찍은 스크린숏

$ chrome-canary --headless --screenshot --window-size=1280,1696 https://blog.outsider.ne.kr
[0528/205742.837245:WARNING:dns_config_service_posix.cc(154)] dns_config has unhandled options!
[0528/205752.688997:INFO:headless_shell.cc(464)] Written to file screenshot.png.

스크린숏을 찍을 브라우저 윈도의 크기를 지정하려면 --window-size=w,h로 지정하면 된다. 이를 이용하면 웹사이트를 반응형으로 만들 때 원하는 크기의 스크린숏을 종류별로 찍어서 제대로 나오는지 확인할 수 있다.

headless chrome으로 찍은 스크린숏

좀 더 자세한 플래그는 소스 코드에서 확인해 볼 수 있다. 유용해 보이는 옵션으로는 --hide-scrollbars, --proxy-server, --remote-debugging-address, --remote-debugging-socket-fd, --repl, --timeout, --user-agent가 있다.

원격 디버깅

headless Chrome으로 웹사이트를 띄워놓고 원격으로 디버깅할 수 있다. 서버 등에서 headless Chrome으로 뭔가 작업을 할 때 원격 디버깅 포트를 열 면 데스크톱에 설치된 chrome에서 접속해서 디버깅할 수 있다.

$ chrome-canary --headless --remote-debugging-port=9222 https://blog.outsider.ne.kr
[0528/211315.749706:WARNING:dns_config_service_posix.cc(154)] dns_config has unhandled options!

--remote-debugging-port=9222 플래그로 디버깅 포트를 지정하고 실행해 놓은 상태로 Chrome에서 http://localhost:9222/에 접속하면 다음과 같이 디버깅할 수 있는 목록이 나온다.

크롬에서 원격 디버깅포트에 접속한 화면

디버깅할 사이트를 클릭하면 브라우저에서 디버깅할 때와 같게 Chrome에서 개발자 도구로 디버깅을 할 수 있다.

headless chrome으로 띄운 웹사이트를 Chrome에서 디버깅


프로그래밍하기

문서를 보면 Node.js같은 코드로 headless chrome을 조작할 수 있는 방법도 안내하고 있다. 여기서는 Node.js에서 CLI 프로그램을 코드로 실행하거나 Lighthouse의 chrome launcher를 이용하는 방법을 설명하고 있는데 두 방법 모두 OS에 설치된 크롬을 그대로 이용하는 방법이다.

기존에 PhantomJS도 OS에 설치해 놓고 사용하기도 하지만 보통은 프로젝트에 내장해서 미리 OS별로 빌드된 PantomJS를 사용하는 게 더 일반적이라고 생각한다. 이렇게 하는 이유는 OS에 의존적이지 않게 하면서 애플리케이션을 배포해도 설치 및 구동을 자동화할 수 있어야 하기 때문인데 아직 이런 부분의 활용성은 headless chrome이 PhatomJS보다는 부족하다고 생각된다.

2017/05/28 21:35 2017/05/28 21:35