
1편에서 웹 크롤링의 개념과 구조,
2편에서 Requests + BeautifulSoup로 정적 페이지 크롤링 실습까지 다뤘습니다.
하지만 실제 서비스에 들어가 보면 이런 경험이 한 번쯤은 있습니다.
- HTML을 받아서 BeautifulSoup으로 파싱했는데,
브라우저에서 보이던 목록이 통째로 안 나옴 - “더 보기”, “스크롤 내리면 자동 로딩” 같은 부분은
Requests로는 도저히 가져오기 힘듦
이유는 간단합니다. 해당 사이트가 “동적 페이지”,
즉 자바스크립트로 화면을 그리는 방식이기 때문입니다.
이때 등장하는 게 바로 Selenium입니다.
- 실제 브라우저(Chrome, Edge 등)를 띄워서
- 사람처럼 클릭하고, 스크롤하고, 입력하고, 기다린 뒤
- 그 결과 화면의 HTML을 가져와 파싱하게 해 주는 도구입니다.
이번 글에서는
- 정적/동적 페이지 차이
- Selenium의 기본 구조
- 간단한 로그인·리스트 수집 예제
- Requests/BS4 vs Selenium, 언제 무엇을 쓸지
- 다음 편(구글 시트/노션 연동)에서 이어갈 포인트
까지, 입문자가 부담 없이 이해할 수 있는 수준으로 정리해 보겠습니다.
1. 정적 페이지 vs 동적 페이지 – 왜 Selenium이 필요할까?
1) 정적 페이지(Static Page)
- 서버가 HTML을 한 번에 만들어서 보내주는 형태
- 브라우저는 거의 “보기만” 하면 끝
- 뷰어 입장에서 단순해서
requests.get(url) 한 번이면 필요한 정보가 대부분 HTML 안에 포함
예:
- 단순 문서·공지 페이지
- 오래된 홈페이지 구조
- 블로그 글 상세 페이지 등
2) 동적 페이지(Dynamic Page)
- 처음에는 빈 틀만 있는 HTML이 오고
- 브라우저 안에서 자바스크립트가 실행되면서
API를 호출해 데이터(목록, 댓글, 차트 등)를 가져와 그리는 구조
특징:
- HTML 소스(view-source)만 보면,
실제 화면에 보이던 데이터가 비어 있거나 일부만 존재 - 스크롤 할 때마다 추가 로딩, 더 보기 버튼, 탭 전환 등
사용자 행동에 따라 내용이 달라짐
이런 경우 Requests + BeautifulSoup만으로는
- 필요한 API 엔드포인트를 역으로 찾거나
- 복잡한 파라미터/토큰까지 분석해야 해서
입문자에게는 거의 “리버스 엔지니어링” 수준이 됩니다.
그래서 가장 현실적인 선택이:
“사람처럼 브라우저를 조작해서 화면을 완성하게 만들고,
그 상태의 HTML을 가져온다”
이고, 그것을 도와주는 도구가 Selenium입니다.

2. Selenium의 기본 구조 이해하기
Selenium의 핵심은 딱 세 가지입니다.
- 브라우저 열기 – Chrome/Edge 등을 자동으로 실행
- 브라우저 조작 – URL 이동, 클릭, 스크롤, 입력 등
- 결과 가져오기 – page_source로 최종 HTML 받아서 파싱
Selenium 4 기준, 가장 기본적인 코드 흐름은 아래와 같습니다.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import time
# 1. 브라우저 옵션 설정 (예: 창을 띄우지 않는 headless 모드)
options = Options()
options.add_argument("--headless=new") # 새 헤드리스 모드
# 2. 드라이버 생성
driver = webdriver.Chrome(options=options)
try:
# 3. 페이지 열기
driver.get("https://example.com")
time.sleep(2) # JS 로딩 대기 (실전에서는 WebDriverWait 사용 권장)
# 4. 요소 찾기
titles = driver.find_elements(By.CSS_SELECTOR, ".post-title")
for t in titles:
print(t.text)
finally:
# 5. 브라우저 종료
driver.quit()
실무에서는 WebDriverWait과 EC(조건)을 함께 써서
“특정 요소가 나타날 때까지 기다렸다가 진행”하는 패턴을 많이 사용합니다.
하지만 첫 입문 단계에서는 위 흐름만 이해해도 충분합니다.
3. Selenium 설치와 기본 설정 (간단 버전)
3-1. 설치
터미널/명령 프롬프트에서:
pip install selenium
Chrome 브라우저 기준으로는
- 예전에는 따로 ChromeDriver를 설치해야 했지만
- 최근 Selenium 버전은 대부분 자동으로 드라이버를 관리해 줍니다.
(단, 환경에 따라 수동 설정이 필요할 수는 있습니다.)
3-2. 기본 템플릿 기억하기
Selenium을 쓸 때는 항상 아래 5단계만 기억하면 됩니다.
- 옵션 설정 (필요 시 headless, 언어 등)
- webdriver.Chrome(...)으로 드라이버 생성
- driver.get(url)로 페이지 열기
- find_element(s)로 요소 찾고, .text, .get_attribute() 등으로 데이터 추출
- driver.quit()으로 브라우저 종료
앞으로 크롤링할 때도 이 템플릿을 복붙해 놓고,
URL·선택자(CSS/XPath) 부분만 바꾸면 대부분 해결됩니다.

4. 실전 1 – 로그인 필요한 페이지 처리 (개념 예시)
주의:
아래 내용은 본인이 계정 권한을 가진 서비스에서
허용된 범위 내 자동화에만 사용해야 합니다.
서비스 이용약관·로봇 정책을 반드시 확인하세요.
예를 들어 “내가 운영하는 관리자 페이지”에 접속해
일별 방문자 숫자를 가져온다고 가정해 봅시다.
4-1. 흐름 설계
- 로그인 페이지 열기
- 아이디/비밀번호 입력
- 로그인 버튼 클릭
- 특정 통계 페이지로 이동
- 통계 숫자 요소를 찾아 텍스트로 추출
4-2. 코드 개념(축약)
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Chrome()
driver.get("https://example.com/login")
# 1) 로그인 정보 입력
id_input = driver.find_element(By.ID, "user_id")
pw_input = driver.find_element(By.ID, "user_pw")
id_input.send_keys("my_id")
pw_input.send_keys("my_password")
# 2) 로그인 버튼 클릭
login_btn = driver.find_element(By.CSS_SELECTOR, "button.login")
login_btn.click()
time.sleep(3) # 로그인 처리 대기
# 3) 통계 페이지 이동
driver.get("https://example.com/admin/stats")
time.sleep(2)
# 4) 원하는 숫자 요소 읽기
today_views = driver.find_element(By.CSS_SELECTOR, ".today-views").text
print("오늘 방문자:", today_views)
driver.quit()
실제 사이트 구조에 따라 By.ID, By.NAME, By.CSS_SELECTOR 등
선택자만 바꾸면 같은 패턴으로 적용 가능합니다.
5. 실전 2 – 무한 스크롤 페이지에서 리스트 수집
쇼핑몰, 뉴스 리스트, SNS 타임라인처럼
- 스크롤을 내릴 때마다 추가로 로딩되는 구조
는 Requests만으로 처리하기 까다롭습니다.
Selenium에서는 “스크롤을 몇 번까지 내려라”라고 명령하면 됩니다.
5-1. 스크롤 기본 패턴
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com/list")
time.sleep(2)
# 스크롤을 n번 반복
for _ in range(5):
# 페이지 맨 아래로 스크롤
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2) # 새 데이터 로딩 대기
# 스크롤이 끝난 뒤, 리스트 요소 가져오기
items = driver.find_elements(By.CSS_SELECTOR, ".item-title")
for i in items:
print(i.text)
driver.quit()
5-2. BeautifulSoup와 함께 쓰기
Selenium으로 화면을 완전히 로딩한 뒤,
결과 HTML을 BeautifulSoup에게 넘겨줄 수도 있습니다.
from bs4 import BeautifulSoup
html = driver.page_source
soup = BeautifulSoup(html, "html.parser")
titles = [tag.get_text(strip=True) for tag in soup.select(".item-title")]
즉,
동적 로딩 → Selenium
파싱(정제, 텍스트 추출) → BeautifulSoup
이라는 역할 분담이 가능합니다.

6. Requests/BeautifulSoup vs Selenium – 언제 무엇을 쓸까?
정리해 보면 다음과 같습니다.
Requests + BeautifulSoup가 더 나은 경우
- 단순 HTML 페이지(블로그 글, 공지, 문서 등)
- 로그인, 스크롤, 버튼 클릭 없이도
한 번 요청으로 데이터가 다 내려오는 경우 - 속도·리소스가 중요한 대량 크롤링
장점:
- 빠르고 가볍다
- 서버 부하를 상대적으로 덜 준다
- 코드가 단순하고 유지보수가 쉽다
Selenium이 필요한 경우
- 로그인, 팝업 닫기, 버튼 클릭 등
사용자 인터랙션이 필수인 페이지 - 스크롤할 때마다, 탭을 클릭할 때마다
데이터가 로딩되는 동적 페이지 - 자바스크립트로 렌더링된 그래프·차트 등
단순 HTML 응답에 없는 데이터
단점:
- 브라우저를 실제로 띄우기 때문에 속도가 느리고 무거움
- 서버 요청 수도 많아질 수 있음
- 운영 환경(서버·클라우드)에서 세팅이 더 까다로울 수 있음
그래서 실제 프로젝트에서는 보통:
“되면 Requests/BS4로 하고,
안 되면 Selenium을 고려한다”
는 순서로 접근하는 것이 일반적입니다.
7. 크롤링 시 꼭 기억해야 할 법·윤리 가이드
어떤 도구를 쓰든, 아래 원칙은 공통입니다.
- 서비스 이용약관·robots.txt 준수
- 서버에 과도한 요청(짧은 간격 대량 요청) 자제
- 로그인 정보(ID, 비밀번호, 토큰)를 안전하게 관리
- 개인 정보, 민감한 정보 수집 금지
- 상업적 이용 시에는 법적 이슈와 저작권을 반드시 확인
특히 Selenium은 실제 사용자를 흉내내기 때문에
“무엇이든 할 수 있을 것 같은 느낌”이 들지만,
허용된 범위 내에서만 사용하는 것이 중요합니다.
8. 다음 편 예고 – “크롤링 결과를 구글 시트/노션과 연동하기”
이번 글에서 우리는
- 동적 페이지의 개념
- Selenium 기본 구조와 코드 템플릿
- 로그인·무한 스크롤 처리 아이디어
- Requests/BS4와의 역할 분담
까지 살펴봤습니다.
다음 글인
「크롤링 결과를 구글 시트/노션 등과 연동하는 방법」에서는
- 오늘까지 배운 크롤링 코드로 모은 데이터를
- 구글 시트·노션 DB에 자동으로 쌓는 방법
- 나중에 GPT 자동화와 연결하는 아이디어
까지 이어서 정리해 보겠습니다.
'코딩과 AI와 자동화 > 크롤링' 카테고리의 다른 글
| 뉴스·여행·생활 데이터를 자동으로 모으는 크롤링 입문 가이드 (1) | 2026.01.16 |
|---|---|
| 4편. 크롤링 결과를 구글 시트·노션에 “자동으로 쌓는” 방법 (0) | 2026.01.08 |
| 2편. 파이썬 Requests + BeautifulSoup로 크롤링 실습 (0) | 2025.12.10 |
| 1편. 웹 크롤링의 개념과 기본 구조 정리 (0) | 2025.12.06 |