Puppeteer와 Chrome DevTools Protocol의 이해

박기찬·3일 전
0

Web tech

목록 보기
10/10
post-thumbnail

Puppeteer는 Chrome DevTools Protocol(CDP)을 추상화한 고수준 Node.js 라이브러리이다. CDP를 직접 다루는 것보다 사용하기 쉬운 API를 제공하지만, 때로는 CDP를 직접 사용해야 하는 경우가 있다.

CDP란? 쉽게 말해서, 개발자 도구(Chrome DevTools)가 브라우저와 통신하는 방식이다. 우리가 Chrome 개발자 도구에서 할 수 있는 모든 작업(요소 검사, 네트워크 모니터링, 자바스크립트 디버깅 등)을 프로그래밍 방식으로 수행할 수 있게 해준다.

Puppeteer의 내부 동작 원리

Puppeteer는 내부적으로 Chrome DevTools Protocol(CDP)을 사용하여 Chrome/Chromium 브라우저와 통신한다. 마치 레고 블록처럼 구성되있다.

Browser (Chrome/Chromium)
    ├── Browser Context (incognito)
    │   ├── Page
    │   │   ├── Frame
    │   │   │   └── Execution Context
    │   │   └── Worker
    │   └── CDP Session
    └── Target
// Puppeteer의 high-level API
await page.click('.button');

// 실제 내부에서는 이런 CDP 명령어들이 실행됨
// 1. DOM 요소 찾기
// 2. 요소가 보이는지 확인
// 3. 클릭 이벤트 발생

또한, Chrome/Chromium은 멀티 프로세스 아키텍처를 사용한다.

  • Browser Process: 브라우저 UI와 리소스 관리
  • Renderer Process: 웹 콘텐츠 렌더링
  • GPU Process: GPU 작업 처리
  • Utility Process: 오디오, 네트워크 등 처리
// 프로세스 정보 확인
const client = await page.target().createCDPSession();
const processes = await client.send('SystemInfo.getProcessInfo');
console.log('현재 실행 중인 프로세스:', processes);

1. 추상화 계층

// Puppeteer 방식 (High-level)
await page.goto('https://example.com');
await page.type('#input', 'hello! world');

// 동일한 작업의 CDP 방식 (Low-level)
const client = await page.target().createCDPSession();
await client.send('Page.navigate', { url: 'https://example.com' });
await client.send('Input.insertText', { text: 'hello! wolrd' });

2. 두 가지 방식의 병행 사용

// Puppeteer와 CDP를 함께 사용하는 예
const page = await browser.newPage();
const client = await page.target().createCDPSession();

// Puppeteer API 사용
await page.goto('https://example.com');

// CDP 직접 사용으로 세밀한 제어
await client.send('Network.enable');
await client.send('Network.emulateNetworkConditions', {
  offline: false,
  latency: 100,
  downloadThroughput: 1024 * 1024,
  uploadThroughput: 1024 * 1024
});

실제 사용 사례로 보는 차이점

1. 네트워크 요청 처리

// Puppeteer 방식
await page.setRequestInterception(true);
page.on('request', request => {
  request.continue();
});

// CDP 방식
const client = await page.target().createCDPSession();
await client.send('Network.enable');
await client.send('Network.setRequestInterception', { patterns: [{ urlPattern: '*' }] });
client.on('Network.requestIntercepted', async ({ interceptionId, request }) => {
  await client.send('Network.continueInterceptedRequest', { interceptionId });
});

2. 성능 모니터링

// Puppeteer 방식
const metrics = await page.metrics();

// CDP 방식 - 더 상세한 정보 접근
const client = await page.target().createCDPSession();
await client.send('Performance.enable');
const performanceMetrics = await client.send('Performance.getMetrics');

CDP는 브라우저의 거의 모든 기능에 접근할 수 있는 "저수준" 인터페이스를 제공하며, Puppeteer는 이를 사용하기 쉽게 추상화한 "고수준" 인터페이스를 제공한다.

따라서, 딱 보기에도 CDP 방식이 다루기엔 더 까다로워보인다. 그렇다면 언제 어떤 방식을 사용하는것이 좋을까?

Puppeteer API를 사용하는 경우

  • 일반적인 웹 자동화 작업
  • 간단한 스크린샷이나 PDF 생성
  • 기본적인 페이지 탐색과 상호작용
// 간단한 자동화 작업
await page.goto('https://example.com');
await page.screenshot({ path: 'screenshot.png' });
await page.pdf({ path: 'page.pdf' });

CDP를 직접 사용해야 할 때

  • 보다 세밀한 브라우저 제어가 필요한 경우
  • Puppeteer API에서 제공하지 않는 기능이 필요한 경우
  • 성능 최적화가 필요한 경우
// 세밀한 제어가 필요한 작업
const client = await page.target().createCDPSession();
await client.send('Emulation.setDeviceMetricsOverride', {
  width: 375,
  height: 812,
  deviceScaleFactor: 3,
  mobile: true
});

물론 같이 사용할 경우도 존재한다.

async function setupBrowserAutomation() {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  const client = await page.target().createCDPSession();

  // Puppeteer로 기본 설정
  await page.setViewport({ width: 1200, height: 800 });
  
  // CDP로 세밀한 제어
  await client.send('Network.enable');
  await client.send('Network.setBypassServiceWorker', { bypass: true });
  
  // 두 API를 조합한 고급 기능 구현
  client.on('Network.responseReceived', async ({ requestId, response }) => {
    if (response.status === 404) {
      // Puppeteer API로 스크린샷 캡처
      await page.screenshot({ 
        path: `error-${requestId}.png`
      });
    }
  });
}

이러한 아키텍처 이해를 바탕으로 Puppeteer와 CDP를 더 효과적으로 활용할 수 있으며, 특히 성능 최적화와 리소스 관리에 있어 더 좋은 선택을 할 수 있다.


https://jsoverson.medium.com/using-chrome-devtools-protocol-with-puppeteer-737a1300bac0
https://chromedevtools.github.io/devtools-protocol/
https://github.com/ChromeDevTools/devtools-protocol

profile
프론트엔드 개발자 🧑

0개의 댓글