Skip to content

실전 사례 가이드

이 장에서는 실제 프로젝트에 즉시 적용할 수 있는 4가지 비즈니스 스크립트 템플릿을 제공합니다. 가장 일반적인 다계정 자동화 시나리오를 다루고 있습니다.


사례 1: 계정 정보 자동 입력 및 로그인

시나리오: 다양한 플랫폼(이커머스 운영, 소셜 미디어, 광고 계정 등)에 자동으로 로그인합니다.

python
import requests
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

API_URL     = "http://127.0.0.1:8186"
SESSION_ID  = "사용자_환경_ID_입력"
DRIVER_PATH = r"C:\Program Files (x86)\Mbbrowser_v7.10.20.219\chromedriver.exe"


def get_driver_from_mbbrowser(session_id: str) -> webdriver.Chrome | None:
    """유틸리티 함수: Mbbrowser 환경을 열고 Selenium 드라이버를 반환합니다."""
    resp = requests.post(
        f"{API_URL}/api/v1/browser/start",
        json={"Session_ID": session_id},
        timeout=30
    )
    data = resp.json()
    if data.get("code") != 0:
        print(f"❌ 환경 시작 실패: {data.get('message')}")
        return None

    debugger_address = data["data"]["http"]
    chrome_options = Options()
    chrome_options.add_experimental_option("debuggerAddress", debugger_address)
    service = Service(executable_path=DRIVER_PATH)
    driver = webdriver.Chrome(service=service, options=chrome_options)
    return driver


def auto_login():
    driver = get_driver_from_mbbrowser(SESSION_ID)
    if not driver:
        return

    wait = WebDriverWait(driver, 20)

    try:
        # ── 1. 로그인 페이지 열기 ────────────────────────────────────
        driver.get("https://example.com/login")

        # ── 2. 계정 필드를 확인한 후 계정 입력 ──────────────────────────
        username_input = wait.until(
            EC.visibility_of_element_located((By.ID, "username"))
        )
        username_input.clear()
        username_input.send_keys("my_account@email.com")
        time.sleep(0.5)  # 인간의 리듬을 흉내 내기 위한 짧은 대기

        # ── 3. 비밀번호 입력 ────────────────────────────────────────
        password_input = driver.find_element(By.ID, "password")
        password_input.clear()
        password_input.send_keys("my_password_123")
        time.sleep(0.3)

        # ── 4. 로그인 버튼 클릭 ──────────────────────────────────────
        login_btn = wait.until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, "button[type='submit']"))
        )
        login_btn.click()

        # ── 5. 로그인 성공 신호 대기 (URL이 대시보드로 리다이렉트됨)
        wait.until(EC.url_contains("/dashboard"))
        print(f"✅ 로그인 성공! 현재 페이지: {driver.current_url}")

        # ── 6. 로그인 성공 후 Mbbrowser가 쿠키를 자동으로 저장합니다.
        # 다음에 수동으로 또는 스크립트로 열 때도 로그인 상태가 유지됩니다.
        print("🔒 쿠키가 Mbbrowser 환경에 자동으로 저장되었습니다.")

    except Exception as e:
        print(f"❌ 로그인 중 예외 발생: {e}")
        driver.save_screenshot("login_error.png")  # 오류 시 스크린샷 저장
    finally:
        driver.quit()


if __name__ == "__main__":
    auto_login()

사례 2: 즉시 로그인을 위한 쿠키 주입 (단계 생략)

시나리오: 계정의 쿠키 데이터를 이미 가지고 있어 로그인 단계를 직접 생략하고 싶을 때 사용합니다.

python
def inject_cookies_and_enter():
    driver = get_driver_from_mbbrowser(SESSION_ID)
    if not driver:
        return

    # ── 1. 쿠키를 설정하기 위해 먼저 대상 도메인을 열어야 합니다 ──────
    driver.get("https://www.amazon.com")

    # ── 2. 준비된 쿠키 데이터 ────────────────────────────────────
    cookies = [
        {
            "name": "session-id",
            "value": "123-4567890-1234567",
            "domain": ".amazon.com",
            "path": "/",
            "secure": True
        },
        {
            "name": "ubid-main",
            "value": "130-1234567-7654321",
            "domain": ".amazon.com",
            "path": "/"
        }
    ]

    # ── 3. 쿠키를 하나씩 주입 ────────────────────────────────────
    driver.delete_all_cookies()  # 기존 쿠키 삭제(선택 사항)
    for cookie in cookies:
        driver.add_cookie(cookie)
    print(f"✅ {len(cookies)}개의 쿠키 주입 완료")

    # ── 4. 쿠키를 적용하기 위해 페이지 새로고침 ──────────────────────
    driver.refresh()
    time.sleep(2)

    # ── 5. 로그인 성공 여부 확인 ──────────────────────────────────
    if "Hello" in driver.page_source or "Account" in driver.title:
        print("✅ 쿠키 주입을 통한 로그인 성공!")
    else:
        print("⚠️ 쿠키가 만료되었을 수 있습니다. 다시 생성해 주세요.")

    driver.quit()

NOTE

Mbbrowser의 비밀: Mbbrowser는 각 환경마다 쿠키를 자동으로 유지합니다. 한 번 로그인하면 쿠키가 저장되어 다음에 다시 열 때도 로그인 상태가 유지됩니다.


사례 3: 대량 데이터 스크래핑 (상품 목록)

시나리오: 로그인된 상태에서 광고 보고서나 경쟁사 가격 등 보호된 페이지 데이터를 수집합니다.

python
def scrape_product_list():
    driver = get_driver_from_mbbrowser(SESSION_ID)
    if not driver:
        return

    wait = WebDriverWait(driver, 20)
    all_products = []

    try:
        # 상품 목록 페이지 열기
        driver.get("https://example.com/products?page=1")

        # ── 페이지 네이션 스크래핑 로직 ────────────────────────────────
        page_num = 1
        while True:
            print(f"📄 {page_num}페이지 스크래핑 중...")

            # 목록 컨테이너가 로드될 때까지 대기
            wait.until(EC.presence_of_element_located(
                (By.CSS_SELECTOR, ".product-list")
            ))

            # 현재 페이지의 모든 상품 수집
            items = driver.find_elements(By.CSS_SELECTOR, ".product-item")
            for item in items:
                try:
                    name  = item.find_element(By.CSS_SELECTOR, ".name").text.strip()
                    price = item.find_element(By.CSS_SELECTOR, ".price").text.strip()
                    all_products.append({"name": name, "price": price, "page": page_num})
                except Exception:
                    pass  # 개별 실패 건은 건너뜀

            print(f"  현재 페이지 {len(items)}개 상품 수집, 누적 {len(all_products)}개")

            # "다음" 버튼 찾기; 없거나 비활성화된 경우 중단
            next_btns = driver.find_elements(
                By.CSS_SELECTOR, "a.pagination-next:not([aria-disabled='true'])"
            )
            if not next_btns:
                print("✅ 마지막 페이지 도달, 수집 완료!")
                break

            next_btns[0].click()
            page_num += 1
            time.sleep(1.5)  # 페이지 전환 후 짧은 대기

    finally:
        driver.quit()

    # 결과 출력 (CSV 또는 데이터베이스에 저장 가능)
    print(f"\n{len(all_products)}개의 상품을 수집했습니다:")
    for p in all_products[:5]:
        print(f"  {p['name']} - {p['price']}")
    return all_products

사례 4: 다계정 병렬 처리 (동시 실행)

시나리오: 여러 Mbbrowser 환경을 동시에 제어하여 작업 효율을 극대화합니다.

python
import threading
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service

API_URL     = "http://127.0.0.1:8186"
DRIVER_PATH = r"C:\Program Files (x86)\Mbbrowser_v7.10.20.219\chromedriver.exe"

# 병렬 실행할 Session_ID 리스트
SESSION_LIST = [
    "환경_ID_1",
    "환경_ID_2",
    "환경_ID_3",
    "환경_ID_4",
    "환경_ID_5",
]


def operate_one_account(session_id: str, thread_id: int):
    """단일 계정 조작 로직 (스레드당 실행)"""
    print(f"[Thread {thread_id}] {session_id[:8]} 환경 시작 중...")
    try:
        # Mbbrowser 환경 시작
        resp = requests.post(
            f"{API_URL}/api/v1/browser/start",
            json={"Session_ID": session_id},
            timeout=30
        )
        data = resp.json()
        if data.get("code") != 0:
            print(f"[Thread {thread_id}] ❌ 실패: {data.get('message')}")
            return

        debugger_address = data["data"]["http"]
        chrome_options = Options()
        chrome_options.add_experimental_option("debuggerAddress", debugger_address)
        service = Service(executable_path=DRIVER_PATH)
        driver = webdriver.Chrome(service=service, options=chrome_options)

        # ── 여기에 본인의 계정 비즈니스 로직 작성 ──
        driver.get("https://example.com")
        print(f"[Thread {thread_id}] ✅ 작업 완료: {driver.title}")

        driver.quit()
    except Exception as e:
        print(f"[Thread {thread_id}] ❌ 예외 발생: {e}")
    finally:
        # 성공 여부와 관계없이 자원 확보를 위해 환경 종료 권장
        requests.post(
            f"{API_URL}/api/v1/browser/stop",
            json={"Session_ID": session_id},
            timeout=10
        )


def batch_operate():
    """모든 계정을 동시(병렬) 실행"""
    threads = []
    for i, session_id in enumerate(SESSION_LIST):
        t = threading.Thread(
            target=operate_one_account,
            args=(session_id, i + 1)
        )
        threads.append(t)
        t.start()

    # 모든 스레드가 종료될 때까지 대기
    for t in threads:
        t.join()

    print("\n🎉 모든 계정의 작업이 완료되었습니다!")


if __name__ == "__main__":
    batch_operate()

IMPORTANT

병렬 실행 권장 사항: 각 환경은 메모리를 소모합니다 (약 300~600MB). 본인 컴퓨터의 사양에 맞게 병렬 개수를 조절하십시오.

  • 16GB RAM → 동시에 10-15개 환경
  • 32GB RAM → 동시에 20-30개 환경

과도한 병렬 실행은 메모리 부족으로 인한 브라우저 반응 저하 또는 스크립트 오류를 유발할 수 있습니다.


사례 5: 완성형 운영급 스크립트 프레임워크

오류 처리, 재시도 및 로깅이 포함된 실제 운영 환경에 더 가까운 프레임워크입니다.

python
import requests
import time
import logging
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.common.exceptions import TimeoutException, WebDriverException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# 로깅 설정
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    datefmt="%H:%M:%S"
)
logger = logging.getLogger(__name__)

API_URL     = "http://127.0.0.1:8186"
DRIVER_PATH = r"C:\Program Files (x86)\Mbbrowser_v7.10.20.219\chromedriver.exe"


class MBBrowserSession:
    """Mbbrowser Selenium 세션 관리자 (재시도 및 컨텍스트 매니저 지원)"""

    def __init__(self, session_id: str, retry: int = 3):
        self.session_id = session_id
        self.retry = retry
        self.driver = None

    def start(self) -> webdriver.Chrome:
        """환경을 시작하고 드라이버 반환 (실패 시 자동 재시도)"""
        for attempt in range(1, self.retry + 1):
            try:
                logger.info(f"[{self.session_id[:8]}] 시작 시도 (차수 {attempt})...")
                resp = requests.post(
                    f"{API_URL}/api/v1/browser/start",
                    json={"Session_ID": self.session_id},
                    timeout=30
                )
                data = resp.json()
                if data.get("code") == 0:
                    debugger_address = data["data"]["http"]
                    chrome_options = Options()
                    chrome_options.add_experimental_option("debuggerAddress", debugger_address)
                    service = Service(executable_path=DRIVER_PATH)
                    self.driver = webdriver.Chrome(service=service, options=chrome_options)
                    logger.info(f"[{self.session_id[:8]}] 시작 완료 ✅")
                    return self.driver
                else:
                    logger.warning(f"[{self.session_id[:8]}] 실패: {data.get('message')}")
            except Exception as e:
                logger.error(f"[{self.session_id[:8]}] 예외: {e}")
            time.sleep(2 ** attempt)  # 지수 백오프(Exponential Backoff)

        raise RuntimeError(f"세션 {self.session_id} 시작 실패 ({self.retry}회 시도)")

    def stop(self):
        """Mbbrowser 환경 종료"""
        if self.driver:
            try:
                self.driver.quit()
            except Exception:
                pass
        requests.post(
            f"{API_URL}/api/v1/browser/stop",
            json={"Session_ID": self.session_id},
            timeout=10
        )
        logger.info(f"[{self.session_id[:8]}] 환경 종료됨")

    def __enter__(self):
        return self.start()

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.stop()
        return False  # 예외를 숨기지 않음


# ── 사용 예시 ──────────────────────────────────────────────────
SESSION_ID = "사용자_환경_ID_입력"

with MBBrowserSession(SESSION_ID) as driver:
    wait = WebDriverWait(driver, 15)
    try:
        driver.get("https://www.mbbrowser.com")
        logger.info(f"페이지 타이틀: {driver.title}")
        driver.save_screenshot("result.png")
    except TimeoutException:
        logger.error("페이지 로드 시간 초과; 네트워크나 프록시 확인 필요.")
    except WebDriverException as e:
        logger.error(f"WebDriver 오류: {e}")

베스트 프랙티스 요약

실무 조언설명
항상 명시적 대기 사용안정성을 위해 time.sleep() 대신 WebDriverWait를 사용하십시오.
오류 발생 시 스크린샷디버깅을 위해 except 블록에서 driver.save_screenshot()을 호출하십시오.
컨텍스트 매니저(with) 사용브라우저가 정상적으로 종료되도록 보장합니다.
속도 조절 (Pacing)주요 동작 사이에 time.sleep(0.3~1.0)을 추가하여 인간의 속도를 흉내 내십시오.
ID가 식별된 로그 기록병렬 처리 시 로그에 항상 Session_ID를 포함시켜 추적 가능하게 하십시오.
루프 내의 과도한 sleep 금지효율성을 크게 떨어뜨립니다; 대신 대기 조건을 사용하십시오.
드라이버 공유 금지각 스레드/계정은 자신만의 Session_ID와 드라이버 인스턴스가 필요합니다.

TIP

🎉 축하합니다! Mbbrowser + Selenium을 활용한 풀 자동화 스택을 모두 익히셨습니다.

문제가 발생하면 핵심 API 레퍼런스를 다시 확인하거나, 클라이언트 내에서 Python 스크립트를 관리하기 위한 자동화 스크립트 관리자를 참조하십시오.