중복 파일 삭제 스크립트를 돌렸다가 식은땀 흘린 날
이 블로그의 웹 데이터 자동 수집 편에서는 requests와 BeautifulSoup을 사용했고, 웹사이트 자동 로그인 편에서는 Selenium을 사용했습니다. "둘 다 웹에서 데이터를 가져오는데 왜 다른 도구를 썼을까" 궁금하셨던 분들을 위해, 이번엔 같은 작업을 두 가지 방식으로 각각 구현해보면서 차이를 직접 비교해보겠습니다.
requests+BeautifulSoup → 서버가 처음 보내주는 "날것의 HTML"만 읽음 Selenium → 실제 브라우저를 띄워서 자바스크립트가 실행된 "최종 화면"을 읽음
이 한 줄이 모든 차이의 근원입니다. 요즘 많은 웹사이트는 페이지가 처음 열릴 때는 빈 뼈대만 오고, 자바스크립트가 실행되면서 실제 내용(상품 목록, 가격 등)이 채워지는 방식으로 만들어집니다. requests는 이 자바스크립트를 실행하지 못하기 때문에, 이런 사이트에서는 빈 껍데기만 가져오게 됩니다.
정적인 뉴스 목록 페이지(자바스크립트 없이 서버가 완성된 HTML을 바로 보내주는 경우)를 크롤링하는 상황을 가정합니다.
requests + BeautifulSoup
import requests
from bs4 import BeautifulSoup
import time
start = time.time()
res = requests.get("https://example-news.com/list")
soup = BeautifulSoup(res.text, "html.parser")
titles = [t.get_text(strip=True) for t in soup.select(".news-title")]
print(f"수집 완료: {len(titles)}건 / 소요시간: {time.time()-start:.2f}초")
Selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
start = time.time()
driver = webdriver.Chrome() # 실제 브라우저 창이 뜸
driver.get("https://example-news.com/list")
time.sleep(2) # 페이지 로딩 대기
elements = driver.find_elements(By.CLASS_NAME, "news-title")
titles = [e.text for e in elements]
driver.quit()
print(f"수집 완료: {len(titles)}건 / 소요시간: {time.time()-start:.2f}초")
💡 체감 속도 차이: 정적인 페이지 기준으로requests는 보통 0.5초 내외,Selenium은 브라우저를 띄우고 로딩을 기다려야 하므로 3~5초 이상 걸립니다. 같은 작업을 정적 페이지에서 한다면requests쪽이 5~10배 이상 빠릅니다.
이번엔 페이지를 아래로 스크롤해야 상품이 추가로 로딩되는(무한 스크롤) 쇼핑몰 페이지를 가정합니다.
requests + BeautifulSoup (한계에 부딪힘)
import requests
from bs4 import BeautifulSoup
res = requests.get("https://example-shop.com/products")
soup = BeautifulSoup(res.text, "html.parser")
products = soup.select(".product-item")
print(f"수집된 상품: {len(products)}개")
# ⚠ 결과: 스크롤 전 처음 로딩된 20개만 수집됨
# 나머지 상품은 자바스크립트로 추가 로딩되기 때문에 requests로는 접근 불가
Selenium (스크롤 동작까지 재현 가능)
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get("https://example-shop.com/products")
# 스크롤을 여러 번 내려서 추가 상품이 로딩되게 함
for _ in range(5):
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(1.5)
products = driver.find_elements(By.CLASS_NAME, "product-item")
print(f"수집된 상품: {len(products)}개")
# ✔ 결과: 스크롤한 만큼 추가 로딩된 상품까지 모두 수집됨
driver.quit()
💡 여기서 알 수 있는 것: 무한 스크롤, 버튼 클릭 후 나타나는 콘텐츠, 로그인 후에만 보이는 페이지는 requests로는 근본적으로 접근할 수 없습니다. 이 블로그의 웹사이트 자동 로그인 편에서 Selenium을 쓴 이유가 바로 "로그인 버튼 클릭"이라는 상호작용이 필요했기 때문입니다.
requests+BeautifulSoup Selenium 메모리 사용량 매우 적음 (수십 MB) 많음 (수백 MB, 브라우저 구동) 동시 실행 수백 개 요청도 가벼움 브라우저 인스턴스라 5~10개도 부담 서버 차단 위험 User-Agent 위조로 우회 가능 실제 브라우저라 차단 확률 낮음 설치 요구사항 pip install만 하면 끝 크롬 드라이버까지 추가 설치 필요 자바스크립트 실행 ✗ 불가능 ✓ 완벽 지원 디버깅 텍스트 로그만 확인 브라우저 화면을 눈으로 직접 확인 가능
requests + BeautifulSoup을 선택하세요, 만약:
페이지 소스보기(Ctrl+U)로 열었을 때 원하는 데이터가 이미 HTML 안에 텍스트로 보인다면, 별다른 고민 없이 이 조합을 사용하세요. 빠르고 가볍고, 여러 페이지를 대량으로 수집할 때도 서버 부담이 적습니다. 웹 데이터 자동 수집 편, 주식·환율 자동 수집 편이 이 조합으로 충분했던 이유입니다.
Selenium을 선택하세요, 만약:
로그인, 클릭, 스크롤처럼 사람이 직접 조작해야 나타나는 데이터가 필요하거나, 페이지 소스보기에는 없는데 화면에는 보이는 데이터(자바스크립트로 나중에 채워지는 콘텐츠)라면 Selenium이 유일한 선택지입니다. 느리고 무겁지만, 사람이 브라우저로 보는 것과 똑같은 결과를 얻을 수 있습니다.
판단이 어렵다면 이렇게 확인하세요:
크롤링하려는 페이지에서 마우스 오른쪽 클릭 → "페이지 소스 보기"를 열어보세요. 원하는 텍스트가 그 소스 안에 그대로 보인다면 requests로 충분합니다. 소스에는 안 보이는데 실제 화면에는 보인다면 자바스크립트로 렌더링되는 것이므로 Selenium이 필요합니다.