파이썬 Selenium Shadow DOM 접근 방법 host shadow_root 활용 가이드
🚀 Selenium으로 Shadow DOM 내부 요소 탐색하는 실전 예제와 꿀팁
웹 자동화 작업을 하다 보면 일반적인 DOM 접근만으로는 원하는 요소를 찾을 수 없는 경우가 있습니다.
특히 최신 웹 애플리케이션에서는 Shadow DOM을 활용해 컴포넌트가 구성되는 경우가 많죠.
이럴 때 Selenium을 그대로 사용하면 요소 탐색이 제대로 되지 않아 난관에 부딪히곤 합니다.
프론트엔드 개발자뿐만 아니라 자동화 테스트를 진행하는 QA 엔지니어, 그리고 데이터 크롤링을 하는 분들에게도 이는 큰 도전 과제가 됩니다.
다행히 Selenium에서는 Shadow Root를 활용하여 내부 요소에 접근할 수 있는 방법을 제공합니다.
즉, 단순히 find_element로는 접근할 수 없지만, host 요소에서 shadow_root 객체를 호출하면 내부 탐색이 가능해집니다.
오늘은 바로 이 host.shadow_root.find_element 방식을 중심으로, Python Selenium을 통해 Shadow DOM 내부에 접근하는 법을 쉽고 명확하게 정리해 드리겠습니다.
📋 목차
🔎 Shadow DOM이란 무엇인가?
웹 개발에서 Shadow DOM은 컴포넌트 기반 UI를 구현하기 위한 핵심 기술입니다.
브라우저가 제공하는 캡슐화 메커니즘으로, 각 컴포넌트가 독립적인 DOM 구조와 스타일을 가질 수 있도록 도와줍니다.
쉽게 말해, 외부의 CSS나 스크립트가 의도치 않게 영향을 미치지 않도록 보호해 주는 일종의 ‘작은 DOM 세계’라고 할 수 있죠.
예를 들어, 크롬 브라우저의 주소창 UI나 기본 제공되는 HTML 요소 일부는 Shadow DOM을 활용해 렌더링됩니다.
이 덕분에 사용자 정의 CSS로 브라우저 핵심 UI를 쉽게 변경할 수 없게 보호되는 셈입니다.
또한 최근 프론트엔드 프레임워크(예: Lit, Stencil, Web Components)에서 제공하는 재사용 가능한 위젯도 Shadow DOM을 적극적으로 활용합니다.
📌 왜 Selenium에서 Shadow DOM이 문제일까?
기본적인 find_element 메서드는 일반 DOM 구조에서만 동작합니다.
하지만 Shadow DOM 내부는 별도의 트리로 관리되기 때문에, Selenium이 이를 직접 인식하지 못합니다.
따라서 단순히 driver.find_element()를 실행하면 Shadow DOM 내부 요소는 “찾을 수 없다”는 오류가 발생하죠.
⚠️ 주의: Shadow DOM 내부 요소에 직접 접근하려 하면 Selenium은 DOM을 탐색할 수 없기 때문에 NoSuchElementException 오류가 발생할 수 있습니다.
📌 Shadow DOM의 장점
- 🔒스타일과 스크립트가 외부에 영향을 받지 않으므로 안정적인 UI 유지 가능
- 📦컴포넌트 단위의 재사용성 극대화
- ⚡대규모 애플리케이션에서도 효율적인 유지보수 가능
즉, 개발자와 사용자 모두에게 유리한 구조이지만, 자동화 테스트나 크롤링 작업에서는 반드시 전용 접근 방식을 사용해야 한다는 점을 기억해야 합니다.
⚙️ Selenium에서 Shadow Root 접근하기
Selenium은 기본적으로 Shadow DOM 내부를 탐색할 수 없습니다.
하지만 Python Selenium 4부터는 shadow_root 속성을 활용하여 호스트 요소 내부에 접근할 수 있는 기능을 지원합니다.
이 기능을 활용하면 일반 DOM처럼 find_element 메서드로 Shadow DOM 안쪽을 탐색할 수 있죠.
접근 절차는 비교적 단순합니다.
먼저 Shadow DOM을 감싸는 호스트 요소를 찾은 뒤, 해당 요소의 shadow_root를 호출합니다.
그러면 별도의 DOM 트리처럼 작동하는 객체가 반환되고, 그 안에서 다시 원하는 요소를 찾을 수 있습니다.
📌 기본 접근 방식
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com")
# Shadow host 찾기
host = driver.find_element(By.CSS_SELECTOR, "shadow-host-selector")
# Shadow root 접근
shadow = host.shadow_root
# 내부 요소 탐색
button = shadow.find_element(By.CSS_SELECTOR, "button.submit")
button.click()
위 코드에서 핵심은 host.shadow_root 부분입니다.
이 과정을 거쳐야만 Shadow DOM 내부 요소를 Selenium이 인식할 수 있습니다.
📌 JavaScript 실행 방식과 비교
Selenium 4 이전에는 Shadow DOM 접근을 위해 execute_script를 사용해야 했습니다.
즉, JavaScript를 직접 실행해 shadowRoot 객체를 반환받는 방식이었죠.
그러나 이제는 shadow_root 속성이 정식으로 지원되기 때문에 코드가 훨씬 간결해졌습니다.
💎 핵심 포인트:
Python Selenium 4부터는 별도의 JavaScript 실행 없이도 shadow_root.find_element()로 Shadow DOM 내부 탐색이 가능합니다.
🛠️ host.shadow_root.find_element 실전 코드 예제
이제 실제 Python 코드로 host.shadow_root.find_element를 어떻게 사용하는지 살펴보겠습니다.
아래 예제는 로그인 버튼이 Shadow DOM 안에 위치한 경우, 해당 버튼을 찾아 클릭하는 과정을 보여줍니다.
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com")
# Shadow host 찾기
host = driver.find_element(By.CSS_SELECTOR, "login-component")
# Shadow root 접근
shadow = host.shadow_root
# 내부 버튼 탐색
login_button = shadow.find_element(By.CSS_SELECTOR, "button#login")
login_button.click()
위 코드를 실행하면 Shadow DOM 내부에 숨겨져 있던 로그인 버튼을 정확히 찾아 동작시킬 수 있습니다.
만약 여러 개의 Shadow DOM이 겹쳐 있는 경우에는, 단계적으로 각 shadow_root를 탐색해야 합니다.
📌 코드 적용 시 유의사항
- ⏳Shadow DOM이 렌더링되기 전에 접근하면 NoSuchElementException 발생
- 🔄반드시 WebDriverWait를 사용해 요소가 로드될 때까지 대기
- 🧩중첩 구조에서는 단계별로 shadow_root를 탐색해야 함
💬 실전에서는 단순 클릭 외에도 입력창 탐색, 속성 값 읽기, 이벤트 트리거 등 다양한 활용이 가능합니다.
🔌 중첩된 Shadow DOM 탐색 방법
실제 웹사이트에서는 Shadow DOM이 한 겹만 있는 경우보다 중첩된 구조를 가진 경우가 많습니다.
이때는 첫 번째 Shadow DOM에 접근한 뒤, 다시 내부에 존재하는 Shadow Host를 찾아 또다시 shadow_root로 들어가야 합니다.
즉, 단계별 탐색이 필수라는 뜻입니다.
📌 중첩 Shadow DOM 예제 코드
# 1차 Shadow host 찾기
outer_host = driver.find_element(By.CSS_SELECTOR, "outer-component")
outer_shadow = outer_host.shadow_root
# 2차 Shadow host 찾기
inner_host = outer_shadow.find_element(By.CSS_SELECTOR, "inner-component")
inner_shadow = inner_host.shadow_root
# 내부 버튼 클릭
inner_button = inner_shadow.find_element(By.CSS_SELECTOR, "button.confirm")
inner_button.click()
위와 같이 단계별로 shadow_root 객체를 탐색해야만 중첩된 Shadow DOM 안쪽 요소를 제대로 찾을 수 있습니다.
📌 중첩 탐색 시 주의사항
💡 TIP: 중첩된 Shadow DOM을 다룰 때는 각 단계마다 WebDriverWait을 사용해 요소가 로드될 때까지 대기하는 습관이 필요합니다.
- 🔍한 번에 깊숙한 요소를 찾으려 하지 말고, 반드시 단계적으로 접근
- ⏱️DOM 로드 타이밍에 따라 실패할 수 있으므로 Explicit Wait 필수
- 🧭내부에 또 다른 컴포넌트가 있는지 구조를 미리 파악
즉, 중첩 Shadow DOM은 단순히 한 번의 접근으로 해결되지 않으며, 여러 단계의 shadow_root 탐색을 통해 원하는 요소를 찾아야 합니다.
💡 자주 발생하는 오류와 해결법
Shadow DOM을 Selenium으로 다루다 보면 예상치 못한 오류가 자주 발생합니다.
특히 DOM 로딩 타이밍이나 셀렉터 지정 문제로 인해 테스트가 실패하는 경우가 많습니다.
아래에서는 실무에서 자주 마주치는 오류와 그 해결 방법을 정리했습니다.
📌 NoSuchElementException
Shadow DOM 내부 요소가 로드되기 전에 접근하려 하면 발생합니다.
이 문제는 WebDriverWait을 사용하여 요소가 나타날 때까지 기다리면 해결됩니다.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
host = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "shadow-host")))
📌 StaleElementReferenceException
DOM이 리렌더링되면서 기존에 참조하던 요소가 사라질 때 발생합니다.
이 경우에는 다시 find_element로 요소를 탐색해야 합니다.
⚠️ 주의: React, Vue 같은 프레임워크 기반 웹사이트에서는 Shadow DOM 내부가 자주 갱신되므로 재탐색 로직을 반드시 준비해야 합니다.
📌 CSS Selector 불일치
Shadow DOM 내부의 구조는 일반 DOM과 다를 수 있으므로 CSS 선택자가 조금만 틀려도 요소를 찾지 못합니다.
따라서 개발자 도구에서 반드시 shadow-root 내부 구조를 확인하고 올바른 셀렉터를 지정해야 합니다.
💎 핵심 포인트:
Selenium에서 Shadow DOM 오류를 해결하려면 대기(WebDriverWait), 재탐색, 정확한 셀렉터 이 세 가지가 핵심입니다.
❓ 자주 묻는 질문 (FAQ)
Selenium에서 Shadow DOM은 꼭 shadow_root를 사용해야 하나요?
중첩된 Shadow DOM도 Selenium으로 탐색 가능한가요?
JavaScript 실행으로도 Shadow DOM에 접근할 수 있나요?
Shadow DOM 내부의 CSS 선택자는 일반 DOM과 동일한가요?
Selenium에서 Shadow DOM 접근 시 가장 흔한 오류는 무엇인가요?
WebDriverWait은 왜 필요한가요?
React나 Vue 같은 프레임워크에서도 동일하게 동작하나요?
Selenium 말고 다른 도구에서도 Shadow DOM 접근이 가능한가요?
📌 Selenium으로 Shadow DOM 내부 탐색 완벽 정리
오늘은 Python Selenium을 활용하여 Shadow DOM 내부 요소 탐색 방법을 단계별로 정리했습니다.
기본적인 개념부터 시작해, host.shadow_root.find_element의 활용법, 중첩된 Shadow DOM 탐색 방식, 그리고 자주 발생하는 오류 해결법까지 살펴봤습니다.
특히 Selenium 4에서 제공하는 shadow_root 속성은 기존의 JavaScript 실행 방식보다 훨씬 직관적이고 간결한 코드 작성이 가능하다는 장점이 있습니다.
정리하자면, 안정적인 Shadow DOM 자동화를 위해서는 단계적 접근, WebDriverWait 활용, 그리고 정확한 CSS 선택자 지정이 필수입니다.
이 세 가지 원칙만 잘 지킨다면, 복잡한 Shadow DOM 구조를 가진 웹사이트에서도 Selenium을 활용한 자동화가 충분히 가능합니다.
🏷️ 관련 태그 : Selenium, Python자동화, ShadowDOM, 웹테스트, hostshadowroot, findelement, 웹크롤링, 자동화스크립트, QA테스트, 웹컴포넌트