Puppeteer 완벽 가이드 | 웹 스크래핑·자동화·PDF 생성·테스트·실전 활용
이 글의 핵심
Puppeteer로 웹 자동화를 구현하는 완벽 가이드. 스크래핑, 스크린샷, PDF 생성, 폼 자동화, 테스트까지 실전 예제로 정리. Puppeteer·Web Scraping·Automation 중심으로 설명합니다. Start now.
이 글의 핵심
Puppeteer로 웹 자동화를 구현하는 완벽 가이드입니다. 스크래핑, 스크린샷, PDF 생성, 폼 자동화, 테스트까지 실전 예제로 정리했습니다.
실무 경험 공유: 수동 데이터 수집을 Puppeteer로 자동화하면서, 작업 시간이 10시간에서 10분으로 단축된 경험을 공유합니다.
들어가며: “수동 작업이 많아요”
실무 문제 시나리오
시나리오 1: 데이터 수집이 번거로워요
수동 복사는 느립니다. Puppeteer로 자동화할 수 있습니다. 시나리오 2: PDF 생성이 필요해요
라이브러리는 제한적입니다. Puppeteer로 완벽한 PDF를 생성할 수 있습니다. 시나리오 3: E2E 테스트가 필요해요
수동 테스트는 비효율적입니다. Puppeteer로 자동화할 수 있습니다.
1. Puppeteer란?
Chrome DevTools Protocol의 고수준 래퍼 (2017~)
Puppeteer는 2017년 Google Chrome 팀이 공개한 Node.js 라이브러리입니다. 브라우저 자동화 도구의 역사는 Selenium(2004)부터 시작되지만, Selenium은 WebDriver API(W3C 표준)를 통해 브라우저를 제어하므로 추가 드라이버(chromedriver, geckodriver)가 필요했습니다.
Puppeteer의 차별점:
- Chrome DevTools Protocol(CDP)을 직접 사용 → 드라이버 불필요
- Headless Chrome 내장 →
npm install puppeteer하나로 Chrome까지 설치 - Chrome 팀 공식 → Chrome 신기능을 가장 빠르게 지원
CDP(Chrome DevTools Protocol)란?
CDP는 브라우저와 외부 도구가 통신하는 프로토콜입니다. Chrome DevTools(F12)도 이 프로토콜로 브라우저와 통신합니다.
Puppeteer (Node.js)
↓ WebSocket (CDP)
Chrome Browser
↓ 렌더링·JS 실행
웹 페이지
Puppeteer가 할 수 있는 것 = DevTools가 할 수 있는 것:
- DOM 조작·쿼리
- 네트워크 요청 가로채기 (Request interception)
- CPU·메모리 프로파일링
- 커버리지 측정
- 모바일 에뮬레이션
Puppeteer vs Playwright vs Selenium
| 측면 | Puppeteer | Playwright | Selenium |
|---|---|---|---|
| 개발사 | Microsoft | 오픈소스 | |
| 출시 | 2017 | 2020 | 2004 |
| 프로토콜 | CDP | CDP + WebKit | WebDriver |
| 브라우저 | Chrome·Chromium | Chrome·Firefox·Safari | 모든 브라우저 |
| API 스타일 | Promise 기반 | Promise + Async Context | Callback·Promise |
| 자동 대기 | 부분적 | ✅ 강력 | ❌ 수동 |
| 병렬 테스트 | 수동 구현 | ✅ 내장 | 수동 구현 |
| 사용 사례 | Chrome 전용 자동화 | 크로스 브라우저 E2E | 레거시 브라우저 지원 |
선택 기준:
- Chrome만 지원해도 됨 → Puppeteer (가볍고 빠름)
- 크로스 브라우저 필요 → Playwright (Firefox·Safari까지)
- IE11 지원 필요 → Selenium (레거시)
핵심 특징
Puppeteer는 Headless Chrome 제어 라이브러리입니다. 주요 기능:
- 웹 스크래핑: 데이터 수집 (동적 콘텐츠·인증 포함)
- 스크린샷: 페이지 캡처 (전체 페이지·viewport·특정 요소)
- PDF 생성: 웹 페이지를 PDF로 (CSS 레이아웃 완벽 재현)
- 폼 자동화: 자동 입력·제출 (반복 작업 제거)
- E2E 테스트: 자동화 테스트 (사용자 시나리오 검증)
- 성능 분석: Network·CPU·Memory 프로파일링
2. 설치 및 기본 사용
설치
npm install puppeteer
기본 예제
import puppeteer from 'puppeteer';
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
const title = await page.title();
console.log('Title:', title);
await browser.close();
})();
3. 스크래핑
텍스트 추출
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://news.ycombinator.com');
const titles = await page.$$eval('.titleline > a', (elements) =>
elements.map((el) => el.textContent)
);
console.log(titles);
await browser.close();
복잡한 스크래핑
const products = await page.$$eval('.product', (elements) =>
elements.map((el) => ({
name: el.querySelector('.name')?.textContent,
price: el.querySelector('.price')?.textContent,
image: el.querySelector('img')?.src,
}))
);
console.log(products);
4. 스크린샷
전체 페이지
// 실행 예제
await page.goto('https://example.com');
await page.screenshot({
path: 'screenshot.png',
fullPage: true,
});
특정 요소
const element = await page.$('.header');
await element?.screenshot({ path: 'header.png' });
5. PDF 생성
await page.goto('https://example.com', {
waitUntil: 'networkidle0',
});
await page.pdf({
path: 'page.pdf',
format: 'A4',
printBackground: true,
margin: {
top: '20px',
right: '20px',
bottom: '20px',
left: '20px',
},
});
6. 폼 자동화
로그인
await page.goto('https://example.com/login');
await page.type('#email', '[email protected]');
await page.type('#password', 'password123');
await page.click('button[type="submit"]');
await page.waitForNavigation();
console.log('Logged in!');
파일 업로드
const fileInput = await page.$('input[type="file"]');
await fileInput?.uploadFile('./file.pdf');
7. 대기
waitForSelector
await page.waitForSelector('.content', {
visible: true,
timeout: 5000,
});
waitForNavigation
await Promise.all([
page.waitForNavigation(),
page.click('a.link'),
]);
커스텀 대기
await page.waitForFunction(
() => document.querySelector('.data')?.textContent?.length > 0
);
8. 실전 예제: 뉴스 스크래핑
import puppeteer from 'puppeteer';
import fs from 'fs/promises';
async function scrapeNews() {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://news.ycombinator.com');
const articles = await page.$$eval('.athing', (elements) =>
elements.slice(0, 10).map((el) => {
const titleEl = el.querySelector('.titleline > a');
const scoreEl = el.nextElementSibling?.querySelector('.score');
return {
title: titleEl?.textContent || ',
url: titleEl?.href || ',
score: scoreEl?.textContent || '0',
};
})
);
await fs.writeFile('news.json', JSON.stringify(articles, null, 2));
console.log(`Scraped ${articles.length} articles`);
await browser.close();
}
scrapeNews();
정리 및 체크리스트
핵심 요약
- Puppeteer: Headless Chrome 제어
- 웹 스크래핑: 데이터 수집
- 스크린샷: 페이지 캡처
- PDF 생성: 웹을 PDF로
- 폼 자동화: 자동 입력
- E2E 테스트: 자동화
구현 체크리스트
- Puppeteer 설치
- 브라우저 실행
- 페이지 이동
- 스크래핑 구현
- 스크린샷 생성
- PDF 생성
- 폼 자동화
같이 보면 좋은 글
- Playwright 완벽 가이드
- Cypress E2E 테스트 가이드
- 웹 스크래핑 가이드
이 글에서 다루는 키워드
Puppeteer, Web Scraping, Automation, PDF, Testing, Node.js, Chrome
내부 동작과 핵심 메커니즘
이 글의 주제는 「Puppeteer 완벽 가이드 | 웹 스크래핑·자동화·PDF 생성·테스트·실전 활용」입니다. 여기서는 앞선 설명을 구현·런타임 관점에서 한 번 더 압축합니다. 요청 경로와 상태 전이를 기준으로 생각하면, “입력이 어디서 검증되고, 핵심 연산이 어디서 일어나며, 부작용(I/O·네트워크·디스크)이 어디서 터지는가”가 한눈에 드러납니다.
처리 파이프라인(개념도)
flowchart TD A[입력·요청·이벤트] --> B[파싱·검증·디코딩] B --> C[핵심 연산·상태 전이] C --> D[부작용: I/O·네트워크·동시성] D --> E[결과·관측·저장]
알고리즘·프로토콜 관점에서의 체크포인트
- 불변 조건(Invariant): 각 단계가 만족해야 하는 조건(예: 버퍼 경계, 프로토콜 상태, 트랜잭션 격리)을 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
- 결정성: 동일 입력에 동일 출력이 보장되는 순수한 층과, 시간·네트워크에 의해 달라질 수 있는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
- 경계 비용: 직렬화/역직렬화, 문자 인코딩, syscall 횟수, 락 경합처럼 “한 번의 호출이 아니라 누적되는 비용”을 의심 목록에 넣습니다.
프로덕션 운영 패턴
실서비스에서는 기능 구현과 함께 관측·배포·보안·비용이 동시에 요구됩니다. 아래는 팀에서 자주 쓰는 최소 체크리스트입니다.
| 영역 | 운영 관점에서의 질문 |
|---|---|
| 관측성 | 요청 단위 상관 ID, 에러율/지연 분위수, 주요 의존성 타임아웃이 보이는가 |
| 안전성 | 입력 검증·권한·비밀 관리가 코드 경로마다 일관적인가 |
| 신뢰성 | 재시도는 멱등한 연산에만 적용되는가, 서킷 브레이커·백오프가 있는가 |
| 성능 | 캐시 계층·배치 크기·풀링·백프레셔가 데이터 규모에 맞는가 |
| 배포 | 롤백 룬북, 카나리, 마이그레이션 호환성이 문서화되어 있는가 |
운영 환경에서는 “개발자 PC에서는 재현되지 않던 문제”가 시간·부하·데이터 크기 때문에 드러납니다. 따라서 스테이징의 데이터 양·네트워크 지연을 가능한 한 현실에 가깝게 맞추는 것이 중요합니다.
문제 해결(Troubleshooting)
| 증상 | 가능 원인 | 조치 |
|---|---|---|
| 간헐적 실패 | 레이스 컨디션, 타임아웃, 외부 의존성 불안정 | 최소 재현 스크립트 작성, 분산 트레이스·로그 상관관계 확인 |
| 성능 저하 | N+1 쿼리, 동기 I/O, 잠금 경합, 과도한 직렬화 | 프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거 |
| 메모리 증가 | 캐시 무제한, 클로저/이벤트 구독 누수, 대용량 객체의 불필요한 복사 | 상한·TTL·스냅샷 비교(힙 덤프/트레이스) |
| 빌드·배포만 실패 | 환경 변수·권한·플랫폼 차이 | CI 로그와 로컬 diff, 컨테이너/런타임 버전 핀(pin) |
권장 디버깅 순서: (1) 최소 재현 만들기 (2) 최근 변경 범위 좁히기 (3) 의존성·환경 변수 차이 확인 (4) 관측 데이터로 가설 검증 (5) 수정 후 회귀·부하 테스트.
자주 묻는 질문 (FAQ)
Q. Playwright와 비교하면 어떤가요?
A. Playwright가 더 빠르고 크로스 브라우저 지원이 좋습니다. Puppeteer는 Chrome에 특화되어 있습니다.
Q. 합법적인가요?
A. 스크래핑은 사이트의 robots.txt와 이용약관을 확인해야 합니다.
Q. Headless 모드가 뭔가요?
A. UI 없이 백그라운드에서 실행되는 모드입니다. 더 빠르고 서버에 적합합니다.
Q. 프로덕션에서 사용해도 되나요?
A. 네, Google에서 만든 안정적인 라이브러리입니다.