초장거리 마라톤 애호가로서 나는 종종 마주하는 공통된 도전 과제가 있습니다: 아직 시도해 보지 않은 더 긴 레이스의 완주 시간을 어떻게 예측할 수 있을까요? 나의 코치와 이에 대해 논의할 때, 그는 실용적인 방법을 제안했습니다 – 내가 완주한 레이스와 나의 목표로 하는 레이스 둘 다를 완주한 러너들을 살펴보는 것입니다. 이 상관 관계는 잠재적인 완주 시간에 대한 소중한 통찰을 제공할 수 있습니다. 그러나 레이스 결과를 수동으로 검색하는 것은 매우 시간이 많이 소요될 것입니다.
이러한 이유로 나는 Race Time Insights를 개발하게 되었습니다. 이 도구는 두 이벤트를 모두 완주한 선수들을 찾아 레이스 결과를 자동으로 비교합니다. 이 애플리케이션은 UltraSignup 및 Pacific Multisports와 같은 플랫폼에서 레이스 결과를 스크랩하며, 러너들이 두 레이스 URL을 입력하고 다른 선수들이 두 이벤트에서 어떻게 성과를 냈는지 확인할 수 있습니다.
이 도구를 만들면서 얼마나 강력한 DigitalOcean의 App Platform인지 알 수 있었습니다. Puppeteer와 헤드리스 Chrome을 Docker 컨테이너에서 사용함으로써, 러너들을 위한 문제 해결에 집중할 수 있었고 App Platform이 모든 인프라 복잡성을 처리해주었습니다. 결과적으로, 우리는 단단하고 확장 가능한 솔루션을 만들어 러닝 커뮤니티가 레이스 목표에 대한 데이터 기반 결정을 내릴 수 있게 도와주었습니다.
Race Time Insights를 개발한 후, 나는 다른 개발자들이 Puppeteer, Docker 컨테이너 및 DigitalOcean App Platform을 활용하는 방법에 대한 안내서를 작성하고자 했습니다. 물론, 외부 데이터를 처리할 때는 요청 속도 제한 및 서비스 약관과 같은 사항을 주의 깊게 고려해야 합니다.
프로젝트 구텐베르크에 들어가 보세요. 방대한 공공 도메인 도서 컬렉션과 명확한 서비스 약관을 갖춘 이곳은 이러한 기술을 시연하기에 이상적인 후보입니다. 이 게시물에서는 Puppeteer를 사용하여 Docker 컨테이너에서 책 검색 애플리케이션을 구축하는 방법을 탐구하고, 외부 데이터 접근에 대한 모범 사례를 따르겠습니다.
프로젝트 구텐베르크 도서 검색
저는 프로젝트 구텐베르크에서 책 정보를 책임감 있게 스크랩하는 웹 애플리케이션을 구축하고 공유했습니다. 이 애플리케이션은 GitHub 저장소에서 찾을 수 있으며, 사용자가 수천 권의 공공 도메인 도서를 검색하고 각 도서에 대한 자세한 정보를 조회하며 다양한 다운로드 형식에 접근할 수 있도록 합니다. 특히 흥미로운 점은 사용자가 진정한 가치를 제공하면서 책임감 있는 웹 스크래핑 관행을 시연한다는 것입니다.
좋은 디지털 시민이 되기
웹 스크래퍼를 구축할 때는 좋은 관행을 따르고 기술적 및 법적 경계를 존중하는 것이 중요합니다. 프로젝트 구텐베르크는 이러한 원칙을 배우기에 훌륭한 예시입니다. 그 이유는:
- 명확한 서비스 약관을 가지고 있기 때문입니다.
- 로봇.txt 가이드라인을 제공합니다
- 그 내용은 명시적으로 공개 도메인에 있습니다
- 자원에 대한 접근성이 증가할 수 있습니다
우리의 구현은 여러 가지 모범 사례를 포함합니다:
속도 제한
시연 목적으로, 적어도 요청 사이에 1초가 보장되는 간단한 속도 제한기를 구현합니다:
이 구현은 예제를 위해 일부러 간소화되었습니다. 단일 애플리케이션 인스턴스를 가정하고 메모리에 상태를 저장하므로 실제 용도로는 적합하지 않습니다. 더 견고한 솔루션은 분산 속도 제한을 위해 Redis를 사용하거나 확장 가능성을 높이기 위해 대기열 기반 시스템을 구현할 수 있습니다.
이 속도 제한기는 Project Gutenberg에 대한 모든 요청 전에 사용됩니다:
봇 식별 정보 지우기
사용자 지정 User-Agent는 웹 사이트 관리자가 누가 사이트에 접속하고 왜 그렇게 하는지 이해할 수 있게 돕습니다. 이 투명성을 통해 그들은 다음을 할 수 있습니다:
- 문제가 발생할 경우 연락
- 봇 트래픽과 인간 사용자를 별도로 모니터링하고 분석
- 합법적인 스크레이퍼에 대해 더 나은 액세스 또는 지원 제공 가능성
효율적인 자원 관리
Chrome은 여러 인스턴스를 실행할 때 특히 메모리를 많이 사용합니다. 사용 후 브라우저 페이지를 올바르게 닫음으로써 메모리 누수를 방지하고 응용 프로그램이 효율적으로 실행되도록 보장합니다. 많은 요청을 처리할 때에도 효율적으로 작동합니다:
이러한 관행을 따르면 접근하는 자원을 효과적으로 활용하면서도 존중하는 스크레이퍼를 만들 수 있습니다. 이는 Project Gutenberg와 같은 소중한 공공 자원과 작업할 때 특히 중요합니다.
클라우드에서의 웹 스크레이핑
이 응용 프로그램은 DigitalOcean의 App Platform을 통해 현대적인 클라우드 아키텍처와 컨테이너화를 활용합니다. 이 접근 방식은 개발의 간편함과 운영 신뢰성 사이의 완벽한 균형을 제공합니다.
App Platform의 강점
App Platform은 다음을 처리함으로써 배포 프로세스를 간소화합니다:
- 웹 서버 구성
- SSL 인증서 관리
- 보안 업데이트
- 부하 분산
- 리소스 모니터링
이를 통해 App Platform이 인프라를 관리하면서 우리는 응용 프로그램 코드에 집중할 수 있습니다.
컨테이너 내 Headless Chrome
저희 스크래핑 기능의 핵심은 Puppeteer를 사용하는데 있습니다. 이는 Chrome을 프로그래밍 방식으로 제어하기 위한 고수준 API를 제공합니다. 우리의 애플리케이션에서 Puppeteer를 설정하고 사용하는 방법은 다음과 같습니다:
이 설정을 통해 우리는 다음을 할 수 있습니다:
- 헤드리스 모드에서 Chrome 실행(그래픽 사용 불필요)
- 웹 페이지 컨텍스트에서 JavaScript 실행
- 브라우저 리소스 안전하게 관리
- 컨테이너화된 환경에서 안정적으로 작업
이 설정은 컨테이너화된 환경에서 실행하기 위한 여러 중요한 구성을 포함합니다:
- 적절한 Chrome 인수: 컨테이너에서 실행하기 위한
--no-sandbox
및--disable-dev-shm-usage
와 같은 필수 플래그 - 환경 인식 경로: 환경 변수에서 올바른 Chrome 실행 파일 경로 사용
- 리소스 관리: 뷰포트 크기 설정 및 불필요한 기능 비활성화
- 전문적인 봇 식별: 스크래퍼를 식별하는 명확한 사용자 에이전트 및 HTTP 헤더 설정
- 오류 처리: 메모리 누수를 방지하기 위한 브라우저 페이지의 적절한 정리
Puppeteer는 Chrome을 프로그래밍 방식으로 쉽게 제어할 수 있게 해줍니다. 그러나 컨테이너에서 실행하려면 적절한 시스템 종속성과 구성이 필요합니다. 이제 우리의 도커 환경에서 이를 어떻게 설정하는지 살펴보겠습니다.
도커: 일관된 환경 보장
웹 스크레이퍼를 배포하는 가장 큰 어려움 중 하나는 개발 환경과 프로덕션 환경에서 동일하게 작동함을 보장하는 것입니다. 로컬 컴퓨터에서 스크레이퍼가 완벽히 작동할 수 있지만 클라우드에서는 종속성이 누락되거나 시스템 구성이 다르기 때문에 실패할 수 있습니다. 도커는 Node.js부터 Chrome 자체에 이르기까지 응용 프로그램이 필요로 하는 모든 것을 패키징하여 어디에서나 동일하게 실행되는 단일 컨테이너로 이 문제를 해결합니다.
우리의 Dockerfile은 이 일관된 환경을 설정합니다:
FROM node:18-alpine
# Chromium 및 종속성 설치
RUN apk add --no-cache \
chromium \
nss \
freetype \
harfbuzz \
ca-certificates \
ttf-freefont \
dumb-init
# 환경 변수 설정
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser \
PUPPETEER_DISABLE_DEV_SHM_USAGE=true
알파인 기반 이미지는 모든 필요한 종속성을 포함하면서도 컨테이너를 가볍게 유지합니다. 이 컨테이너를 실행할 때, 노트북에서든 DigitalOcean의 앱 플랫폼에서든, 헤드리스 Chrome을 실행하는 데 필요한 모든 올바른 버전과 구성이 있는 정확히 동일한 환경을 얻게 됩니다.
개발에서 배포까지
이 프로젝트를 설정하고 실행하는 과정을 살펴보겠습니다:
1. 로컬 개발
먼저, 예제 저장소를 GitHub 계정으로 포크하세요. 이렇게 하면 작업하고 배포할 수 있는 자신의 복사본이 생깁니다. 그런 다음 포크를 로컬로 클론하세요:
# 포크 클론하기
git clone https://github.com/YOUR-USERNAME/doappplat-puppeteer-sample.git
cd doappplat-puppeteer-sample
# Docker로 빌드 및 실행하기
docker build -t gutenberg-scraper .
docker run -p 8080:8080 gutenberg-scraper
2. 코드 이해하기
애플리케이션은 세 가지 주요 구성 요소를 중심으로 구조화되어 있습니다:
-
도서 서비스: 웹 스크래핑 및 데이터 추출을 처리합니다
-
익스프레스 서버: 라우트를 관리하고 템플릿을 렌더링합니다
-
프론트엔드 뷰: 부트스트랩을 사용한 깔끔하고 반응형 UI
<div class="card book-card h-100"> <div class="card-body"> <span class="badge bg-secondary downloads-badge"> <%= book.downloads.toLocaleString() %> 다운로드 </span> <h5 class="card-title"><%= book.title %></h5> <!-- ... 더 많은 UI 요소 ... --> </div> </div>
3. 디지털오션에 배포하기
저장소의 포크가 준비되었으니, 디지털오션 앱 플랫폼에 배포하는 것은 간단합니다:
- 새로운 앱 플랫폼 애플리케이션 만들기
- 포크한 저장소에 연결하기
- 리소스에서 두 번째 리소스(도커파일이 아닌)를 삭제하세요; 이는 앱 플랫폼에 의해 자동 생성된 것으로 필요하지 않습니다
- 리소스 생성 클릭하여 배포하기
애플리케이션은 자동으로 빌드되고 배포되며, 앱 플랫폼이 모든 인프라 세부 사항을 처리합니다.
결론
이 Project Gutenberg 스크레이퍼는 현대적인 클라우드 기술을 활용하여 실용적인 웹 응용 프로그램을 구축하는 방법을 보여줍니다. 웹 스크래핑을 위해 Puppeteer, 컨테이너화를 위해 Docker, 그리고 배포를 위해 DigitalOcean의 앱 플랫폼을 결합하여 견고하고 유지 보수가 쉬운 솔루션을 만들었습니다.
이 프로젝트는 당신의 웹 스크래핑 응용 프로그램을 위한 템플릿으로 작용하며, 브라우저 자동화를 처리하는 방법, 자원을 효율적으로 관리하는 방법, 그리고 클라우드로 배포하는 방법을 보여줍니다. 데이터 수집 도구를 구축하거나 컨테이너화된 응용 프로그램을 학습하고 있다면, 이 예는 튼튼한 기반을 제공하여 발전시킬 수 있습니다.
자세한 내용 및 자신의 인스턴스를 배포하는 방법은 GitHub의 프로젝트를 확인하세요!