파이썬 셀레니움 클릭 오류, ElementNotInteractable과 ClickIntercepted 구분하는 법

파이썬 Selenium에서 요소를 찾았는데 클릭이 실패한다면 먼저 예외 이름을 구분해야 합니다. ElementNotInteractableException은 찾은 요소가 현재 상태에서 상호작용할 수 없다는 뜻이고, ElementClickInterceptedException은 클릭 지점이 다른 요소에 가려졌다는 뜻입니다. 따라서 sleep 시간을 무작정 늘리기보다 대기 조건, locator, 가림 요소, iframe 순서로 확인하는 편이 안전합니다.

두 클릭 오류는 무엇이 다른가

Selenium의 클릭은 요소의 중심점을 기준으로 수행됩니다. 대상이 viewport 밖에 있으면 Selenium이 안으로 스크롤하려고 하지만, 표시되지 않거나 pointer-interactable하지 않은 요소라면 ElementNotInteractableException이 발생할 수 있습니다.

반대로 중심점이 navbar, 팝업, modal, 애니메이션 같은 다른 요소에 가려져 클릭이 전달되지 않으면 ElementClickInterceptedException을 의심합니다. 전자는 대상 자체의 상태와 선택 문제에 가깝고, 후자는 화면 위에서 클릭을 막는 요소를 찾는 문제에 가깝습니다.

먼저 locator와 대기 조건을 확인하기

같은 selector가 여러 요소와 일치하면 숨겨진 요소나 아직 상호작용할 수 없는 요소를 고를 수 있습니다. 개발자 도구에서 selector가 실제 클릭 대상 하나를 가리키는지 확인하고, 가능하면 역할이나 고유한 속성을 포함해 더 정확하게 좁힙니다.

presence_of_element_located는 DOM에 존재하는지만 확인합니다. 클릭 직전에는 visible이고 enabled인지 확인하는 element_to_be_clickable을 사용할 수 있습니다. 다만 이 조건이 다른 요소에 가려지지 않았음까지 보장하는 것은 아니므로, 실제 클릭에서 intercepted 예외가 계속되면 화면을 덮는 요소를 따로 확인해야 합니다.

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

wait = WebDriverWait(driver, 10)
button = wait.until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-action='save']"))
)
button.click()

고정된 time.sleep()은 페이지 상태를 직접 확인하지 않습니다. 로딩 시간이 짧을 때는 우연히 통과하고, 네트워크나 애니메이션이 늦어지면 다시 실패할 수 있으므로 조건 기반 대기를 우선 검토합니다.

ClickIntercepted라면 가림을 확인하기

intercepted 예외가 난다면 클릭 대상이 실제로 보이는지, 상단 고정 메뉴나 모달·팝업이 중심점을 덮는지, 닫기 동작 뒤 overlay가 사라졌는지, 대상이 애니메이션 중인지 순서대로 살펴봅니다.

overlay가 사라지는 조건은 Selenium의 invisibility_of_element_located로 기다릴 수 있습니다.

wait.until(
    EC.invisibility_of_element_located((By.CSS_SELECTOR, ".loading-overlay"))
)
button = wait.until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-action='save']"))
)
button.click()

JavaScript로 클릭을 강제하는 방식은 화면에서 실제 사용자가 클릭할 수 있는 상태인지 확인하는 과정을 건너뛸 수 있습니다. 먼저 locator와 overlay, 대기 조건을 바로잡고 실제 상호작용 흐름과 맞는지 판단하는 것이 좋습니다.

iframe 안의 요소인지 확인하기

요소가 iframe 내부에 있다면 WebDriver는 기본적으로 최상위 문서의 요소만 찾습니다. selector가 맞아 보여도 클릭 이전에 올바른 frame으로 전환하지 않으면 요소를 정상적으로 다룰 수 없습니다.

wait.until(
    EC.frame_to_be_available_and_switch_to_it(
        (By.CSS_SELECTOR, "iframe.payment-form")
    )
)

button = wait.until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "button.submit"))
)
button.click()

driver.switch_to.default_content()

iframe 전환 뒤에는 그 문서 안에서 locator를 다시 적용해야 합니다. 작업이 끝나면 default_content()로 최상위 문서로 돌아와 다음 요소를 찾습니다.

운영에서의 판단 순서

저라면 오류 메시지를 기준으로 범위를 줄입니다. ElementNotInteractableException이면 locator가 숨은 요소를 고른 것은 아닌지, visible/enabled 상태인지, iframe 전환이 빠지지 않았는지 확인합니다. ElementClickInterceptedException이면 중심점을 덮은 overlay·modal·navbar가 있는지와 대상이 움직이는 중인지 확인합니다. 두 경우 모두 DOM 존재만 기다리는 조건을 클릭 조건으로 오해하지 않았는지 살펴봅니다.

문제가 해결되지 않으면 우회 코드부터 추가하기보다 클릭하려는 요소의 실제 상태와 페이지의 상호작용 순서를 다시 기록해 보십시오. 그러면 대기를 추가할 문제인지, locator를 고칠 문제인지, overlay를 닫을 문제인지, iframe으로 전환할 문제인지 결정할 수 있습니다.

근거 자료

Leave a Comment