크롤러2026-10-01·8분 읽기

파이썬 웹 크롤러를 24시간 무료로 자동 실행하는 방법 (PC 끄고 매일 정기 수집하기)

매일 아침 최저가와 신규 공지를 자동 수집하는 파이썬 크롤러를 내 컴퓨터 없이 24시간 무료로 돌리는 법. Chromium 설치와 텔레그램 알림 연동까지 완벽 정리했어요.

파이썬 웹 크롤러를 24시간 무료로 자동 실행하는 방법 (PC 끄고 매일 정기 수집하기)

원하는 상품의 최저가 할인 알림, 매일 아침 채용 사이트의 신규 공고, 혹은 경쟁사의 가격 변동을 자동으로 긁어오는 파이썬 크롤러를 완성했을 때의 성취감은 정말 짜릿해요.

하지만 막상 일상에서 써보려고 하면 곧바로 현실적인 장벽을 마주하게 됩니다.

"크롤러를 매일 돌리려면 내 노트북을 24시간 켜두어야 하나요?"
"외출할 때 노트북 덮개를 닫으면 절전 모드로 들어가서 수집이 멈춰요."
"Vercel이나 AWS 람다에 올려봤더니 10초 만에 타임아웃 에러가 나면서 꺼져버려요."

크롤러나 스크래퍼는 웹페이지가 완전히 렌더링될 때까지 기다려야 하고, 일정한 주기로 백그라운드에서 계속 살아 숨 쉬어야 해요. 그래서 일반적인 웹사이트 호스팅이나 서버리스 함수로는 제대로 돌릴 수 없습니다.

내 컴퓨터를 완전히 끄고도 파이썬 크롤러가 365일 24시간 자동으로 돌아가며, 원하는 데이터를 텔레그램으로 쏴주도록 무료 클라우드에 배포하는 방법을 차근차근 정리해 드릴게요.


1. 크롤러를 로컬 PC나 서버리스에서 돌리면 실패하는 이유

크롤러 배포를 처음 시도할 때 가장 많이 겪는 세 가지 시행착오를 먼저 짚어볼게요.

① 내 컴퓨터(노트북)에서 돌리기: 절전 모드와 유동 IP

  • 노트북 덮개를 닫거나 일정 시간 키보드를 만지지 않으면 운영체제가 절전 모드로 들어가요. 화면만 꺼지는 게 아니라 백그라운드 네트워크 연결까지 끊어버립니다.
  • 집에서 쓰는 공유기는 주기적으로 공인 IP가 바뀌는데, 이 과정에서 대상 웹사이트나 API 연결 소켓이 먹통이 되기도 해요.

② Vercel / AWS Lambda: 엄격한 실행 시간 한계

  • Vercel이나 람다는 사용자의 웹 요청이 들어올 때 잠깐 켜졌다가 응답이 끝나면 즉시 꺼지는 이벤트 기반 구조예요.
  • 무료 플랜 기준으로 10~15초 타임아웃이 걸려 있어서, 헤드리스 브라우저(Playwright, Selenium)가 뜨는 도중에 타임아웃으로 강제 종료당합니다.
  • 무한 루프(while True: sleep(300))나 10분 간격의 정기 반복 작업을 원천적으로 돌릴 수 없는 구조예요.

③ 일반 클라우드 VM: 복잡한 리눅스 의존성과 한글 깨짐

  • 리눅스 가상 서버에 Chromium 브라우저를 띄우려면 수십 개의 그래픽 라이브러리를 터미널에서 일일이 설치해야 해요.
  • 한국 웹사이트를 긁을 때 한글 폰트가 설치되어 있지 않으면, 캡처 화면과 수집 텍스트가 전부 네모 모양(□□□, 폰트 두부 현상)으로 깨져서 저장되는 문제도 흔합니다.

2. 실전 예제: 24시간 가격 추적 & 텔레그램 알림 크롤러

아래는 실제 프로덕션 환경에서 곧바로 사용할 수 있는 완성형 파이썬 크롤러 코드예요. 특정 쇼핑몰 상품 페이지를 주기적으로 확인하다가 가격 변동이나 할인이 감지되면 내 텔레그램으로 즉시 알림을 보내줍니다.

# scraper.py
import os
import time
import logging
import asyncio
import httpx
from playwright.async_api import async_playwright
 
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
 
# 환경변수 설정
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID")
TARGET_URL = os.getenv("TARGET_URL", "https://example.com/product/12345")
CHECK_INTERVAL_SECONDS = int(os.getenv("CHECK_INTERVAL", "600"))  # 기본 10분 주기
 
async def send_telegram_alert(message: str):
    """텔레그램 봇으로 알림 메시지 발송"""
    if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
        logger.warning("텔레그램 토큰 또는 Chat ID가 없어 콘솔에만 출력합니다: %s", message)
        return
    url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
    payload = {"chat_id": TELEGRAM_CHAT_ID, "text": message, "parse_mode": "HTML"}
    async with httpx.AsyncClient(timeout=10.0) as client:
        try:
            await client.post(url, json=payload)
        except Exception as e:
            logger.error("텔레그램 발송 실패: %s", e)
 
async def scrape_product():
    """헤드리스 브라우저로 대상 페이지 방문 및 가격 수집"""
    logger.info("크롤링 시작: %s", TARGET_URL)
    
    async with async_playwright() as p:
        # DashCloud에 내장된 Chromium을 헤드리스 모드로 실행
        browser = await p.chromium.launch(
            headless=True,
            args=["--no-sandbox", "--disable-dev-shm-usage"]
        )
        context = await browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
            viewport={"width": 1280, "height": 800}
        )
        
        # 불필요한 이미지와 폰트 요청을 가로채 차단하여 메모리와 대역폭 절약
        await context.route(
            "**/*",
            lambda route: route.abort()
            if route.request.resource_type in ["image", "media", "font"]
            else route.continue_()
        )
 
        page = await context.new_page()
        try:
            await page.goto(TARGET_URL, wait_until="domcontentloaded", timeout=30000)
            
            # 페이지 내 제목 추출
            title = await page.title()
            logger.info("성공적으로 웹페이지를 수집했습니다: %s", title[:30])
            
            # 알림 메시지 구성 및 발송
            alert_msg = f"🔔 <b>[가격 모니터링 알림]</b>\n\n상품: {title}\n확인 시각: {time.strftime('%Y-%m-%d %H:%M:%S')}\n링크: {TARGET_URL}"
            await send_telegram_alert(alert_msg)
 
        except Exception as e:
            logger.error("수집 중 에러 발생: %s", e)
        finally:
            await context.close()
            await browser.close()
 
async def main_loop():
    logger.info("24/7 파이썬 크롤러 데몬이 시작되었습니다.")
    await send_telegram_alert("🚀 <b>[시스템]</b> 크롤러가 클라우드에서 가동을 시작했습니다.")
 
    while True:
        try:
            await scrape_product()
        except Exception as e:
            logger.error("예상치 못한 메인 루프 예외: %s", e)
 
        logger.info("%d초 대기 후 다음 수집을 진행합니다...", CHECK_INTERVAL_SECONDS)
        await asyncio.sleep(CHECK_INTERVAL_SECONDS)
 
if __name__ == "__main__":
    asyncio.run(main_loop())

그리고 필요한 의존성 파일인 requirements.txt를 작성해 주세요.

# requirements.txt
playwright>=1.42.0
httpx>=0.27.0

3. 10초 만에 크롤러 무료 배포하기

리눅스 터미널에서 Playwright 의존 패키지를 수동으로 설치할 필요 없이, DashCloud를 이용하면 웹 브라우저에서 바로 배포할 수 있어요.

1단계: 코드 폴더 준비

내 컴퓨터에 scraper.py와 requirements.txt 두 개 파일을 한 폴더에 담아둡니다.

2단계: DashCloud 대시보드에 업로드

  1. DashCloud 콘솔에서 GitHub 또는 Discord로 로그인하고 휴대폰 인증을 1회 완료해요. (신용카드 입력 불필요)
  2. [새 프로젝트 만들기] 버튼을 클릭합니다.
  3. 준비한 폴더를 화면에 드래그 앤 드롭해요.
  4. 시스템이 playwright 패키지를 확인하고 헤드리스 Chromium 브라우저와 Noto Sans 한글 폰트가 내장된 런타임을 자동으로 구성해 줍니다.

3단계: 환경변수 설정 & 가동

대시보드 환경변수 메뉴에서 알림에 필요한 값들을 넣어줍니다:

  • TELEGRAM_BOT_TOKEN: 봇 토큰
  • TELEGRAM_CHAT_ID: 알림을 받을 내 채팅방 ID
  • TARGET_URL: 수집할 목표 웹페이지 주소
  • CHECK_INTERVAL: 수집 주기 (초 단위, 예: 600)

[배포하기] 버튼을 누르면 10초 만에 클라우드 컨테이너가 켜지고, 실시간 웹 콘솔 창에서 크롤링 로그가 출력돼요:

[DashCloud] Chromium & Noto Sans CJK 한글 폰트 감지 완료
[DashCloud] requirements.txt 패키지 설치 완료
[DashCloud] 실행: python scraper.py
2026-10-01 16:00:00 - INFO - 24/7 파이썬 크롤러 데몬이 시작되었습니다.
2026-10-01 16:00:02 - INFO - 크롤링 시작: https://example.com/product/12345
2026-10-01 16:00:05 - INFO - 성공적으로 웹페이지를 수집했습니다

이제 내 컴퓨터를 완전히 끄고 편안히 잠자리에 들어도, 클라우드 위의 크롤러가 10분마다 목표 사이트를 방문해 가격 변동이 생기면 스마트폰으로 텔레그램 알림을 쏴줍니다.


4. 크롤러 장기 운영 시 꼭 지켜야 할 안전 수칙

① 이미지와 미디어 리소스 차단하기

크롤러의 주 목적은 텍스트 데이터 추출이에요. 코드 예시처럼 context.route로 용량이 큰 이미지(.png, .jpg), 미디어, 웹 폰트 요청을 가로채 차단하면 수집 속도가 3배 이상 빨라지고 메모리 사용량을 대폭 아낄 수 있어요.

② 수집 이력은 /app 영구 볼륨에 저장하기

이전에 수집했던 최저가 기록이나 마지막 상품 ID를 로컬에 저장해두어야 매번 똑같은 알림이 중복 발송되는 '알림 폭주'를 막을 수 있습니다. DashCloud에서는 /app/data.db나 /app/history.json처럼 /app 하위에 저장하면 컨테이너가 재시작되어도 데이터가 온전히 보존돼요.

③ 안티봇 탐지 방지 딜레이 적용하기

매번 정확히 0.00초 정각 간격으로 요청을 보내면 웹 방화벽(WAF)에 봇으로 탐지되어 차단당하기 쉬워요. 수집 간격에 random.uniform(5, 15) 같은 랜덤 지터 딜레이를 살짝 주어 사람처럼 불규칙한 브라우징 패턴을 유지해 보세요.


요약: 나만의 자동화 비서를 띄워보세요

정기 스크래핑 스크립트 하나 돌리자고 집 컴퓨터를 하루 종일 켜둘 필요가 없어요. 클라우드에 크롤러를 얹어두고, 매일 자동으로 정제된 데이터를 내 손안에서 편안하게 받아보세요!


관련 문서 & 추천 가이드

  • 12시간 넘게 돌려도 메모리 안 터지는 크롤러 설계법 (실측 비교)
  • 크롤링하기 전에 꼭 알아야 할 법적 기준과 안전 가이드
  • Selenium vs Playwright 리소스 및 속도 벤치마크
  • 크롤링 대신 쓸 수 있는 정부·공공데이터 포털 API 가이드