이 글에서 배울 내용:
- 순수 Puppeteer로는 사용자 행동 분석에 대응하기에 부족한 이유.
puppeteer-humanize란무엇이며, 이러한 한계를 극복하는 데 어떻게 도움이 되는지.- 단계별 튜토리얼 섹션에서 웹 스크래핑에 활용하는 방법.
- 이 웹 데이터 스크래핑 접근법의 잔여 과제들.
자, 시작해 보겠습니다!
사용자 행동 분석: 표준 Puppeteer가 부족한 이유
사용자 행동 분석 (UBA)은 사용자가 웹 페이지와 상호작용하는 방식에 대한 데이터를 수집하고 분석하는 과정입니다. 웹 스크래핑에서 주요 목표는 비정상적이거나 의심스러운 행동을 포착하여 봇을 식별하는 것입니다.
이 정교한 봇 방지 기술은 점점 인기를 얻고 있습니다. 그 이유는 현대의 AI 기반 봇이 지속적으로 진화하여 더욱 인간처럼 행동하기 때문입니다. 따라서 기존의 봇 탐지 방법은 더 이상 효과적이지 않을 수 있습니다.
UBA에 대응하기 위해 일부 자동화 라이브러리는 인간 행동을 더 현실적으로 모방하려 시도합니다. 예를 들어, 휴리스틱 또는 머신 러닝을 활용해 마우스 움직임을 시뮬레이션합니다. 그러나 대부분의 경우 타이핑은 여전히 기계적으로 보일 수 있어 문제가 됩니다.
이제 Puppeteer 스크립트가 양식을 작성해야 한다고 가정해 보십시오. type() 함수를 사용하여 키 입력 사이에 약간의 지연을 추가하더라도, 그 상호작용은 자연스럽게 보이지 않을 것입니다.
Quotes to Scrape의 로그인 양식을 예로 들어 보겠습니다:
import puppeteer from "puppeteer";
(async () => {
// 헤드리스 모드가 아닌 새 브라우저 인스턴스 설정
const browser = await puppeteer.launch({
headless: false, // 상호작용을 관찰할 수 있도록 false로 설정
defaultViewport: null,
});
const page = await browser.newPage();
// 대상 페이지로 이동
await page.goto("https://quotes.toscrape.com/login");
// 각 문자 입력 사이에 200ms 지연 시간을 두고 입력 시뮬레이션
await page.type("input[name="username"]", "username", { delay: 200 });
await page.type("input[name="password"]", "password", { delay: 200 });
// ...
// 브라우저 닫기 및 리소스 해제
await browser.close();
})();
상호작용은 다음과 같이 보일 것입니다:

위 접근 방식은 입력 필드 값을 직접 설정하는 것보다 현실적이지만, 여전히 인간처럼 보이지 않습니다. 문제는 타이핑이 너무 매끄럽고 일관되며 오류가 없다는 점입니다. 스스로에게 물어보세요—실제 사용자가 망설임이나 오타 없이 정확히 동일한 간격으로 모든 문자를 입력할까요?
예상하셨겠지만, 고급 UBA 시스템은 이런 스크립트를 쉽게 탐지합니다. 바로 이때 puppeteer-humanize 같은 도구가 빛을 발합니다!
puppeteer-humanize란 무엇인가요?
puppeteer-humanize는 Node.js 라이브러리로, 특히 텍스트 입력 필드와 상호작용할 때 Puppeteer 자동화를 더 인간처럼 보이게 합니다. 이는 비현실적이거나 지나치게 정밀한 행동을 감지하는 일반적인 봇 탐지 방법을 우회하는 데 도움을 줍니다.
이를 위해 puppeteer-humanize는 다음과 같은 방식으로 일반적인 Puppeteer 상호작용에 현실적인 불완전성을 주입합니다:
- 오타를 시뮬레이션합니다.
- 오류를 수정하기 위한 백스페이스 키 사용 모방
- 삭제된 텍스트를 무작위 지연 시간과 함께 재입력합니다.
- 키 입력 간 무작위 지연으로 타이핑 속도 변화 유도
이를 통해 자동 타이핑이 더 자연스럽고 기계적이지 않게 보입니다. 그러나 이 라이브러리는 타이핑 행동과 양식 입력만 인간화하는 데 초점을 맞추고 있다는 점을 유의해야 합니다. 따라서 포괄적인 봇 우회 솔루션은 아닙니다.
또한, 마지막 커밋이 2021년이며 GAN 기반 마우스 움직임 시뮬레이션과 같은 고급 기능을 아직 지원하지 않는다는 점을 염두에 두어야 합니다. 따라서 그 범위는 타이핑 행동에만 국한됩니다.
웹 스크래핑을 위한 puppeteer-humanize 사용 방법
puppeteer-humanize를 활용해 보다 인간적인 스크래핑 봇을 구축하는 방법을 아래 단계별로 알아보세요. 이는 특히 스크립트가 양식에 데이터를 입력해야 할 때 UBA 시스템에 탐지될 가능성을 줄여줍니다.
대상은 Quotes to Scrape의 로그인 양식입니다:

이 예시는 현실적인 양식 작성 시뮬레이션 방법을 순수히 보여주기 위한 것입니다. 실제 스크래핑 시나리오에서는 명시적인 허가가 없는 한 로그인 양식 뒤의 콘텐츠를 스크래핑하지 마십시오. 이는 법적 문제를 야기할 수 있습니다.
이제 웹 스크래핑에 puppeteer-humanize를 활용하는 방법을 살펴보겠습니다!
1단계: 프로젝트 설정
아직 Node.js 프로젝트가 설정되어 있지 않다면, 프로젝트 폴더에서 npm init을 실행하여 생성할 수 있습니다:
npm init -y
위 명령어는 프로젝트 디렉토리에 package.json 파일을 생성합니다. 프로젝트 폴더 내에 스크립트 스크래핑 로직을 배치할 script.js 파일을 생성하세요:
your-project-folder/
├── package.json
└── script.js
다음으로, 선호하는 JavaScript IDE에서 폴더를 엽니다. Visual Studio Code가 완벽하게 작동합니다.
IDE에서 package.json 파일을 수정하여 다음 줄을 추가하세요:
"type": "module"
이는 프로젝트가 ESM(ECMAScript Modules)을 사용하도록 설정하는 것으로, 표준 CommonJS 형식보다 현대적인 Node.js 프로젝트에 일반적으로 권장됩니다.
좋습니다! 이제 스크래핑 스크립트에서 현실적인 상호작용을 시뮬레이션하기 위해 puppeteer-humanize를 활용할 준비가 되었습니다.
2단계: puppeteer-humanize 설치 및 시작하기
puppeteer-humanize는 원래 Puppeteer Extra용 플러그인이었지만, 이제는 그렇지 않습니다. 따라서 사용하려면 다음을 설치하기만 하면 됩니다:
@forad/puppeteer-humanize: 인간과 유사한 행동을 시뮬레이션하는 라이브러리.puppeteer: 핵심 브라우저 자동화 라이브러리.
다음 명령어로 둘 다 설치하세요:
npm install @forad/puppeteer-humanize puppeteer
다음으로 script.js 파일을 열고 다음과 같이 기본 Puppeteer 스크립트를 초기화하세요:
import puppeteer from "puppeteer";
(async () => {
// 헤드리스 모드가 아닌 새 브라우저 인스턴스 설정
const browser = await puppeteer.launch({
headless: false, // 상호작용을 관찰할 수 있도록 false로 설정
defaultViewport: null,
});
const page = await browser.newPage();
// ...
// 브라우저를 닫고 리소스를 해제
await browser.close();
})();
훌륭합니다! 이제 인간과 유사한 스크래핑 상호작용을 구현할 수 있습니다.
3단계: 대상 페이지에 접속하고 입력 요소 선택하기
Puppeteer를 사용하여 대상 페이지로 이동합니다:
await page.goto("https://quotes.toscrape.com/login");
이제 브라우저에서 동일한 페이지를 열고 로그인 양식을 마우스 오른쪽 버튼으로 클릭한 후 “검사”를 선택하여 양식 요소를 살펴보세요:

양식에는 다음이 포함되어 있음을 확인할 수 있습니다:
- 사용자 이름 입력 필드(
input[name="username"]로 선택 가능) - 비밀번호 입력 필드(
input[name="password"]로 선택 가능)
스크립트에서 이러한 입력 요소를 선택하려면 Puppeteer의 $() 메서드를 사용하세요:
const usernameInput = await page.$("input[name="username"]");
const passwordInput = await page.$("input[name="password"]");
⚠️ 중요: puppeteer-humanize는 로케이터와 호환되지 않습니다. 즉, 요소 핸들을 직접 가져오려면 $() 또는 $$()를 사용해야 합니다.
페이지에서 두 입력란이 모두 발견되면 실제 사용자와 동일하게 상호작용할 준비를 하세요:
if (usernameInput && passwordInput) {
// 상호작용...
}
훌륭합니다! 이제 실제 사용자처럼 해당 입력란을 채울 차례입니다.
4단계: puppeteer-humanize 입력 기능 구성
먼저, puppeteer-humanize에서 typeInto 함수를 가져옵니다:
import { typeInto } from "@forad/puppeteer-humanize";
그런 다음 아래와 같이 인간과 유사한 양식 입력 상호작용을 구성하는 데 사용하세요:
const typingConfig = {
mistakes: {
chance: 10, // 오타 발생 후 수정될 확률 (10%)
delay: {
min: 100, // 오타 수정 전 최소 지연 시간 (ms)
max: 500, // 오타 수정 전 최대 지연 시간 (ms)
},
},
delays: {
all: {
chance: 100, // 각 키 입력 사이에 지연 추가 확률 100%
min: 100, // 문자 간 최소 지연 시간 (ms)
max: 200, // 문자 간 최대 지연 시간 (ms)
},
},
};
// 입력 필드에 채워 넣을 문자열
const username = "username";
const password = "password";
// 두 입력 필드에 인간 같은 타이핑 로직 적용
await typeInto(usernameInput, username, typingConfig);
await typeInto(passwordInput, password, typingConfig);
위의 타이핑 설정:
- 가끔 오타를 발생시킨 후, 실제 사용자가 하듯이 현실적인 수정을 가합니다.
- 각 키 입력 사이에 무작위 지연을 추가하여 자연스러운 타이핑 속도 변동을 모방합니다.
이러한 동작은 자동화 작업을 훨씬 더 인간처럼 보이게 하여 UBA 기술에 의한 탐지 가능성을 제한합니다.
훌륭합니다! 이제 Puppeteer 스크립트가 실제 사람처럼 훨씬 더 자연스럽게 동작할 것입니다.
5단계: 양식 작성 및 웹 스크래핑 준비
아래 코드를 사용하여 양식을 작성할 수 있습니다:
const submitButton = page.locator("input[type="submit"]");
await submitButton.click();
참고: Quotes to Scrape의 로그인 양식은 테스트 페이지일 뿐입니다. 구체적으로, 사용자명과 비밀번호 자격 증명으로 접근할 수 있습니다. 양식을 제출하면 스크래핑할 데이터가 포함된 페이지로 리디렉션됩니다:

이 시점에서 일반적인 Puppeteer API를 사용하여 실제 스크래핑 로직을 구현할 수 있습니다:
// 페이지 로드 완료 대기
await page.waitForNavigation();
// 스크래핑 로직...
본 문서의 초점은 puppeteer-humanize에 있습니다. 따라서 여기서는 스크래핑 부분은 다루지 않겠습니다.
Quotes to Scrape에서 데이터를 스크래핑하여 CSV로 내보내는 방법에 관심이 있다면, Puppeteer를 활용한 웹 스크래핑에 대한 전체 튜토리얼을 참고하세요.
6단계: 모든 것을 통합하기
이제 script.js 파일에는 다음 내용이 포함되어야 합니다:
import puppeteer from "puppeteer";
import { typeInto } from "@forad/puppeteer-humanize";
(async () => {
// 헤드리스 모드가 아닌 새 브라우저 인스턴스 설정
const browser = await puppeteer.launch({
headless: false, // 사용자 상호작용을 관찰할 수 있도록 false로 설정
defaultViewport: null,
});
const page = await browser.newPage();
// 대상 페이지 방문
await page.goto("https://quotes.toscrape.com/login");
// 로그인 양식 입력란 선택
const usernameInput = await page.$("input[name="username"]");
const passwordInput = await page.$("input[name="password"]");
// 둘 다 null이 아닐 경우 상호작용
if (usernameInput && passwordInput) {
// 입력 동작 구성
const typingConfig = {
mistakes: {
chance: 10, // 오타 발생 후 수정 확률 (10%)
delay: {
min: 100, // 오타 수정 전 최소 지연 시간 (ms)
max: 500, // 오타 수정 전 최대 지연 시간 (ms)
},
},
delays: {
all: {
chance: 100, // 각 키 입력 사이에 지연 추가 확률 100%
min: 100, // 문자 간 최소 지연 시간 (ms)
max: 200, // 문자 간 최대 지연 시간 (ms)
},
},
};
// 입력 필드에 채울 테스트 문자열
const username = "username";
const password = "password";
// 두 입력 필드에 인간 같은 타이핑 로직 적용
await typeInto(usernameInput, username, typingConfig);
await typeInto(passwordInput, password, typingConfig);
// 양식 제출
const submitButton = page.locator("input[type="submit"]");
await submitButton.click();
// 페이지 로드 완료 대기
await page.waitForNavigation();
// 스크래핑 로직...
}
// 브라우저 닫기 및 리소스 해제
await browser.close();
})();
위의 puppeteer-humanize 스크래핑 스크립트를 다음으로 실행하세요:
node script.js
결과는 다음과 같습니다:

보시다시피, 이제 Puppeteer 봇이 실제 인간 사용자와 매우 유사한 방식으로 로그인 양식과 상호작용합니다. 현실적인 속도로 입력하고, 가끔 오타를 내며, 이를 수정합니다. 이것이 바로 puppeteer-humanize의 힘입니다!
이 웹 스크래핑 접근법의 한계점
puppeteer-humanize는 사용자 상호작용 방식을 분석하는 기술에 의해 탐지될 가능성을 줄이는 데 확실히 훌륭한 동맹입니다. 하지만 반스크래핑 및 반봇 기술은 단순한 사용자 행동 분석을 훨씬 뛰어넘습니다!
첫째, Puppeteer는 브라우저를 프로그래밍 방식으로 제어하기 위해 브라우저에 도구를 설치해야 한다는 점을 기억하세요. 이는 브라우저가 자동화되었음을 드러낼 수 있는 미묘한 변화와 신호를 유발합니다. 이러한 정보 유출을 줄이기 위해 Puppeteer Stealth 사용도 고려해야 합니다.
puppeteer-humanize와 Puppeteer Stealth를 모두 적용하더라도 상호작용 중 CAPTCHA를 마주칠 수 있습니다. 이 경우 Playwright를 활용한 CAPTCHA 우회 방법에 관한 저희 글을 참고하세요.
이러한 도구와 가이드가 더 탄탄한 스크래핑 환경 구축에 도움이 되지만, 그 기반이 되는 많은 우회 방법은 영구적이지 않습니다. 고도로 정교한 봇 방지 솔루션을 사용하는 사이트를 상대할 경우 성공 확률은 크게 떨어집니다. 또한 여러 플러그인을 추가하면 메모리 및 디스크 사용량이 증가하고 확장성이 떨어질 수 있습니다.
이 시점에서 문제는 단순히 Puppeteer 자체가 아니라, Puppeteer가 제어하는 브라우저의 한계에 있습니다. 진정한 돌파구는 웹 스크래핑을 위해 특별히 설계된 클라우드 기반 헤드풀 브라우저와 Puppeteer를 통합하는 데서 나옵니다. 이 솔루션은 프록시 로테이션, 고급 CAPTCHA 해결, 현실적인 브라우저 지문 등 다양한 기능을 기본 지원합니다. 바로 이것이 Bright Data의 Browser API가 제공하는 핵심입니다!
결론
이 튜토리얼에서는 기본 Puppeteer가 사용자 행동 분석에 부적합한 이유와 puppeteer-humanize로 이를 해결하는 방법을 배웠습니다. 특히 단계별 튜토리얼을 통해 이 접근법을 웹 스크래핑 워크플로에 통합하는 방법을 확인했습니다.
이 방법은 단순한 안티봇 시스템을 우회하는 데 도움이 될 수 있지만, 높은 성공률을 보장하지는 않습니다. 특히 CAPTCHA, IP 차단 또는 최신 AI 기반 안티봇 기술을 사용하는 사이트를 스크래핑할 때 더욱 그렇습니다. 게다가 이 설정을 확장하는 것은 복잡할 수 있습니다.
스크래핑 스크립트나 AI 에이전트까지 실제 사용자와 유사하게 동작하도록 만드는 것이 목표라면, 해당 용도에 특화된 브라우저인 Bright Data의 Agent Browser 사용을 고려해 보세요.
Bright Data의 무료 계정을 생성하여 AI 지원 스크래핑 인프라 전체를 활용하세요!