메뉴 닫기

파이썬 Selenium 실행 JS 사용법 execute_script execute_async_script 반환과 Promise 처리

파이썬 Selenium 실행 JS 사용법 execute_script execute_async_script 반환과 Promise 처리

🚀 Selenium 중급 개발자를 위한 자바스크립트 실행과 비동기 Promise 핸들링 완벽 가이드

웹 자동화를 배우다 보면 단순한 클릭이나 입력을 넘어서, 브라우저 내부에서 직접 자바스크립트를 실행해야 하는 상황이 자주 등장합니다.
특히 Selenium의 execute_scriptexecute_async_script는 이런 경우 반드시 알아야 할 핵심 도구인데요.
이 기능들을 활용하면 DOM 조작부터 API 호출, 비동기 데이터 처리까지 한 단계 높은 자동화 작업이 가능합니다.
다만 반환값 처리나 자바스크립트 Promise를 어떻게 다루는지에 따라 코드 안정성과 실행 결과가 크게 달라지기 때문에, 제대로 이해하는 것이 중요합니다.

이번 글에서는 파이썬 Selenium에서 두 가지 방식의 자바스크립트 실행 차이를 명확히 짚어보고, 반환값 처리와 비동기 Promise 핸들링 방법까지 실전 예제와 함께 정리해 드립니다.
이를 통해 자동화의 유연성을 높이고, 복잡한 웹 애플리케이션 환경에서도 보다 안정적인 스크립트 실행이 가능해질 것입니다.



execute_script 기본 사용법과 반환값

파이썬 Selenium에서 가장 많이 사용되는 기능 중 하나가 바로 execute_script입니다.
이 메서드는 브라우저의 자바스크립트 엔진을 직접 호출하여 원하는 코드를 실행할 수 있게 해주는데요.
예를 들어 DOM 요소를 가져오거나, 스크롤을 내리거나, 특정 값을 반환받는 경우에 활용됩니다.

일반적으로 execute_script는 동기 방식으로 실행되며, 자바스크립트 코드가 반환하는 값은 그대로 파이썬으로 전달됩니다.
숫자, 문자열, 불리언, 배열, 객체 등 대부분의 기본 데이터 타입을 받을 수 있으며, DOM 요소를 반환하면 Selenium이 이를 자동으로 WebElement 객체로 변환합니다.

CODE BLOCK
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://example.com")

# 자바스크립트 실행 - 페이지 제목 반환
title = driver.execute_script("return document.title;")
print(title)

# 스크롤 내리기
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

위 예제에서 첫 번째 스크립트는 페이지의 제목을 가져와 반환합니다.
자바스크립트 return 키워드가 사용된 부분은 곧바로 파이썬 변수에 할당됩니다.
두 번째 스크립트는 반환값이 없기 때문에 단순히 브라우저에서 동작만 수행합니다.

💡 TIP: 반환값을 받아올 때는 반드시 return 키워드를 포함해야 하며, 그렇지 않으면 항상 None이 반환됩니다.

즉, execute_script는 간단한 자바스크립트 실행과 동기적 반환에 최적화되어 있으며, 대부분의 상황에서는 이 방식만으로도 충분히 원하는 작업을 수행할 수 있습니다.
하지만 Ajax 호출이나 타이머처럼 시간이 걸리는 작업에는 다른 접근이 필요합니다.

execute_async_script 비동기 실행 방식

웹 페이지에는 네트워크 요청이나 타이머, 이벤트 리스너처럼 실행이 끝날 때까지 시간이 걸리는 코드가 많습니다.
이럴 때 execute_script를 사용하면 브라우저가 응답을 돌려주지 않아 TimeoutException 같은 오류가 발생할 수 있습니다.
이를 해결하기 위해 Selenium은 execute_async_script라는 메서드를 제공합니다.

이 방식은 비동기 자바스크립트를 실행할 수 있도록, 마지막에 반드시 콜백(callback) 함수를 호출해야 합니다.
Selenium은 해당 콜백이 실행되기 전까지 기다리며, 콜백의 인자로 전달한 값이 곧 파이썬으로 반환됩니다.

CODE BLOCK
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://example.com")

# 비동기 스크립트 실행
result = driver.execute_async_script("""
    var callback = arguments[0];
    setTimeout(function() {
        callback("3  반환된 데이터");
    }, 3000);
""")

print(result)  # "3초 후 반환된 데이터"

위 예제에서 자바스크립트의 setTimeout은 3초 뒤에 콜백을 실행합니다.
그 전까지 Selenium은 대기하고 있다가, 콜백이 실행되면 해당 값이 파이썬으로 반환됩니다.

💎 핵심 포인트:
비동기 실행 시 반환은 return 키워드가 아닌 callback() 함수로 해야 하며, 콜백이 호출되지 않으면 Selenium은 무한 대기에 빠질 수 있습니다.

따라서 API 요청, Ajax 처리, 지연 실행 같은 상황에서는 반드시 execute_async_script를 사용해야 안정적인 결과를 얻을 수 있습니다.
이 기능을 적절히 활용하면 페이지 내부의 비동기 로직까지 제어할 수 있어 자동화의 범위를 크게 확장할 수 있습니다.



🔄 Promise 반환값 처리와 주의점

최근의 웹 애플리케이션은 Promise 기반의 비동기 코드를 광범위하게 사용합니다.
하지만 Selenium에서 단순히 execute_script로 Promise를 실행하면 아직 완료되지 않은 상태가 반환되므로, 원하는 데이터를 바로 얻지 못하는 문제가 생깁니다.

이 경우 가장 안전한 방법은 execute_async_script를 활용해 Promise의 then() 또는 catch() 안에서 콜백을 호출하는 방식입니다.
즉, Promise가 완료될 때까지 기다렸다가 Selenium에 최종 결과를 전달하는 구조로 작성해야 합니다.

CODE BLOCK
# 자바스크립트 Promise를 Selenium에서 처리하기
result = driver.execute_async_script("""
    var callback = arguments[0];
    fetch("https://jsonplaceholder.typicode.com/posts/1")
        .then(response => response.json())
        .then(data => callback(data))
        .catch(error => callback("Error: " + error));
""")

print(result)

위 예제에서는 fetch() API가 반환하는 Promise를 받아 JSON 데이터가 준비된 시점에 콜백으로 전달합니다.
이렇게 하면 네트워크 요청이 완료될 때까지 기다렸다가 Selenium이 최종 결과를 정상적으로 받을 수 있습니다.

⚠️ 주의: Promise를 단순히 return으로 반환하면 [object Promise] 문자열만 받게 됩니다.
반드시 execute_async_script와 콜백을 함께 사용해야 합니다.

즉, Selenium에서 Promise를 다룰 때는 비동기 처리라는 특성을 고려해야 하며, 적절히 콜백 구조를 작성하지 않으면 데이터 로드 실패나 무한 대기 같은 문제가 발생할 수 있습니다.

🛠️ 실전 예제 코드와 활용 시나리오

이제 실제로 Selenium에서 execute_scriptexecute_async_script를 어떻게 활용할 수 있는지 살펴보겠습니다.
단순한 DOM 조작부터, 네트워크 API 호출, 스크롤 처리까지 다양한 활용 시나리오가 존재합니다.

📌 동기 실행 활용 예제

페이지의 특정 요소를 조작하거나 화면을 이동시키는 경우에는 execute_script를 사용하는 것이 간단하고 빠릅니다.

CODE BLOCK
# 특정 요소의 텍스트 가져오기
element_text = driver.execute_script(
    "return document.querySelector('h1').innerText;"
)
print(element_text)

# 무한 스크롤 페이지 로딩
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

📌 비동기 실행 활용 예제

API 요청이나 Ajax 데이터 로딩처럼 시간이 걸리는 작업에서는 execute_async_script가 필수입니다.

CODE BLOCK
# Ajax 요청  데이터 가져오기
result = driver.execute_async_script("""
    var callback = arguments[0];
    fetch("https://jsonplaceholder.typicode.com/users/1")
        .then(resp => resp.json())
        .then(data => callback(data))
        .catch(err => callback("Error: " + err));
""")

print(result)

  • DOM 조작 → 텍스트, 속성, 스타일 변경
  • 🌐API 요청 → Ajax, Fetch로 서버 데이터 받기
  • 🔄무한 스크롤 처리 → 동적 페이지 컨텐츠 로딩

이처럼 Selenium의 자바스크립트 실행 기능은 단순 제어를 넘어, 실제 사용자 브라우저 환경을 그대로 시뮬레이션하는 데 유용합니다.
특히 데이터 크롤링이나 자동화 테스트 환경에서 활용도가 높습니다.



⚠️ 오류와 예외 처리 전략

Selenium에서 자바스크립트를 실행하다 보면 다양한 오류와 예외 상황을 맞이하게 됩니다.
스크립트 실행 자체가 실패하는 경우도 있고, 비동기 작업이 끝나지 않아 무한 대기 상태에 빠지기도 합니다.
따라서 안정적인 자동화를 위해서는 반드시 예외 처리를 고려해야 합니다.

📌 자주 발생하는 오류 유형

오류 유형 원인 및 해결 방법
TimeoutException 비동기 스크립트에서 callback()이 호출되지 않아 발생 → 콜백 보장 코드 작성 필요
JavascriptException 자바스크립트 구문 오류 → 브라우저 콘솔에서 테스트 후 실행
StaleElementReferenceException DOM이 갱신되어 기존 WebElement가 유효하지 않음 → 요소 재탐색 필요

📌 안전한 코드 작성 전략

  • try-except 문으로 예외 상황을 포착하고 로그 남기기
  • WebDriverWait과 같은 명시적 대기 조건을 함께 사용하기
  • Promise 기반 로직은 반드시 callback() 또는 resolve 시점에서 반환 처리

💡 TIP: 비동기 요청 시 Selenium의 기본 스크립트 실행 대기 시간은 제한적이므로, set_script_timeout()을 조정해 두면 안전합니다.

이처럼 발생 가능한 오류를 사전에 인지하고, 적절한 예외 처리와 대기 전략을 세워두면 예측 불가능한 상황에서도 안정적인 자동화가 가능합니다.

자주 묻는 질문 (FAQ)

execute_script와 execute_async_script의 차이는 무엇인가요?
execute_script는 동기 방식으로 즉시 결과를 반환하고, execute_async_script는 콜백이 호출될 때까지 기다린 뒤 결과를 반환합니다.
비동기 스크립트 실행 시 콜백을 호출하지 않으면 어떻게 되나요?
Selenium은 콜백이 실행될 때까지 무기한 대기하며, 결국 TimeoutException이 발생합니다.
Promise를 execute_script로 처리할 수 있나요?
Promise는 비동기 객체이므로 execute_script에서는 [object Promise] 형태로만 반환됩니다. 반드시 execute_async_script로 처리해야 합니다.
Ajax 요청 데이터를 가져올 때 가장 좋은 방법은 무엇인가요?
execute_async_script 내부에서 fetch 또는 XMLHttpRequest를 사용하고, 완료 시 콜백을 호출하여 데이터를 반환하는 방식이 가장 안정적입니다.
WebElement를 반환하면 어떤 형태로 전달되나요?
자바스크립트에서 DOM 요소를 반환하면 Selenium이 자동으로 해당 요소를 WebElement 객체로 변환하여 제공합니다.
스크립트 실행 시간이 너무 길면 어떻게 해야 하나요?
driver.set_script_timeout() 메서드를 사용하여 비동기 스크립트 최대 대기 시간을 조정할 수 있습니다.
비동기 스크립트에서 오류가 발생하면 어떻게 처리하나요?
Promise의 catch 블록에서 callback()을 호출하여 오류 메시지를 반환하면, 파이썬 측에서 예외를 로깅하거나 재처리할 수 있습니다.
실전에서 가장 많이 쓰이는 활용 예시는 무엇인가요?
무한 스크롤 처리, Ajax 데이터 수집, 페이지 렌더링 완료 여부 확인 등에서 자주 사용됩니다.

📝 Selenium 자바스크립트 실행 핵심 정리

이번 글에서는 파이썬 Selenium을 활용해 브라우저 내부에서 자바스크립트를 실행하는 방법을 심도 있게 다뤄보았습니다.
execute_script는 동기적으로 빠른 제어가 가능하고, execute_async_script는 Promise나 Ajax와 같은 비동기 로직 처리에 최적화되어 있습니다.
특히 콜백을 통해 데이터를 반환하는 방식은 안정적인 자동화 작업을 가능하게 해주며, 잘못된 사용은 TimeoutException이나 무한 대기 문제로 이어질 수 있습니다.

실전 예제에서 확인했듯이 DOM 조작, 무한 스크롤, 서버 API 호출까지 다양한 시나리오에서 활용할 수 있으며, 올바른 오류 처리 전략과 함께 사용하면 복잡한 웹 애플리케이션 자동화도 문제없이 수행할 수 있습니다.
결국 Selenium에서 자바스크립트 실행을 제대로 이해하는 것은 단순 자동화를 넘어, 웹 테스트와 데이터 수집에서 한 단계 높은 수준의 제어를 가능하게 해줍니다.


🏷️ 관련 태그 : Selenium, 파이썬자동화, 자바스크립트실행, execute_script, execute_async_script, Promise처리, 웹크롤링, 자동화테스트, 비동기처리, 파이썬프로그래밍