macOS에서 사용 중인 Chrome을 AppleScript로 조작하는 작업과, Puppeteer로 헤드리스 Chrome을 띄우는 작업을 함께 실행할 때 생기는 충돌을 정리합니다.
증상
AppleScript가 사용 중인 Chrome의 창과 탭을 찾지 못합니다.
tell application "Google Chrome"의windows에 헤드리스 쪽 창 1개만 보임- 열려 있던 탭을 URL로 찾으면 결과 없음
execute javascript가 “자바스크립트 실행 기능이 꺼져 있습니다” 오류를 반환 (Chrome 메뉴에서는 허용 상태)
tell application "Google Chrome"
return URL of tabs of window 1
end tell
-- http://localhost:8130/ ← 헤드리스 Chrome이 연 페이지
헤드리스 프로세스가 종료되면 같은 스크립트가 다시 정상 동작합니다.
원인
Puppeteer에 일반 Chrome 실행 파일을 지정하면 헤드리스 Chrome도 같은 앱 번들에서 실행됩니다.
puppeteer.launch({
executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
headless: true, // --headless=new 로 실행됨
});
이 경우 시스템에는 같은 앱(Google Chrome)의 프로세스가 두 개 존재합니다.
AppleScript는 앱 이름으로 대상을 찾기 때문에 두 프로세스 중 어느 쪽으로 명령이 전달될지 보장되지 않습니다.
실제로는 헤드리스 프로세스가 떠 있는 동안 명령이 그쪽으로 전달됐습니다.
확인 방법
같은 실행 파일에서 뜬 프로세스를 나열하면 헤드리스 프로세스를 바로 구분할 수 있습니다.
pgrep -fl "Google Chrome.app/Contents/MacOS/Google Chrome"
# 71191 /Applications/Google Chrome.app/.../Google Chrome --no-startup-window
# 46083 /Applications/Google Chrome.app/.../Google Chrome --headless=new ...
어떤 스크립트가 띄웠는지는 부모 프로세스를 따라가면 확인할 수 있습니다.
ps -o pid,ppid,command -p 46083
해결: chrome-headless-shell 사용
헤드리스 작업에는 chrome-headless-shell을 사용합니다.
Chrome 팀이 헤드리스 전용으로 배포하는 실행 파일로, .app 번들이 아니기 때문에 AppleScript의 Google Chrome 대상에 포함되지 않습니다.
npx @puppeteer/browsers install chrome-headless-shell@stable --path ~/.cache/puppeteer
import puppeteer from 'puppeteer-core';
import { computeExecutablePath, Browser } from '@puppeteer/browsers';
import { homedir } from 'node:os';
const executablePath = computeExecutablePath({
browser: Browser.CHROMEHEADLESSSHELL,
buildId: '156.0.8078.80', // 설치 시 출력된 버전
cacheDir: `${homedir()}/.cache/puppeteer`,
});
const browser = await puppeteer.launch({ executablePath });
try {
// 페이지 작업
} finally {
await browser.close();
}
변경 후 chrome-headless-shell이 실행 중인 상태에서 확인한 결과입니다.
| 확인 항목 | 결과 |
|---|---|
pgrep -fl chrome-headless-shell |
헤드리스 프로세스 실행 중 |
AppleScript windows · 탭 URL |
사용 중인 Chrome의 창과 탭 반환 |
execute javascript "1+1" |
2 |
다른 방법
- Chrome for Testing: 앱 이름이
Google Chrome for Testing이라 대상이 겹치지 않습니다. 화면이 있는 브라우저가 필요한 경우에 적합합니다. - 작업 시간 분리: 헤드리스 작업이 끝날 때까지 AppleScript 작업을 미루는 방법입니다. 여러 작업이 동시에 실행되는 환경에서는 유지하기 어렵습니다.
어느 방법이든 헤드리스 브라우저는 작업이 끝나면 바로 종료하는 것이 좋습니다.