본문 바로가기
업무 자동화(RPA)/Python | 웹 크롤링(Web Crawling)

[Python] Chrome '페이지를 열기 위한 메모리가 충분하지 않음' 오류 해결

by 디지털 전산일지 2024. 2. 19.

문제 상황

크롤링을 하다가 중간에 '페이지를 열기 위한 메모리가 충분하지 않음' 오류와 함께 오류 코드 : Out of Memory 오류가 발생하였다. 

 

크롤링을 하다가 중간에 다음과 같이 Chrome 창이 열리지 않고 오류가 생겼다.

 

문제 원인

Chrome은 메모리를 많이 요구한다. 탭을 10개 이상 띄워놓게 된다면 메모리가 8GB 이상인 PC 환경에서 해야 할 정도이다.

메모리를 어마어마하게 잡아먹는다.

 

"왜 Chrome은 다른 브라우저보다 메모리 사용량이 많은가?"

 

1. Chrome은 각 탭이 독립되어있는 응용프로그램처럼 작동하기 때문에 메모리 사용량이 많이 늘어나게 된다.

예를 들어 Chrome에서는 한 탭에서 오류가 나더라도 다른 탭에서 오류가 나지 않는다면 다른 탭에서는 잘 작동하지만 Internet Explorer는 도중에 오류가 나게 되면 전부 다 다시 실행시켜야 한다.

 

2. Chrome은 프리렌더링(사용자가 이전에 방문한 페이지를 메모리에 저장해 두었다가 다시 그 페이지로 들어가게되면 메모리에서 웹 페이지를 불러오는 기술)을 지원하기 때문이다.

특정 웹 페이지를 다시 방문하게 되면 웹 페이지가 뜨는 속도가 빨라지는 경험을 할 수 있는데 이런 프리렌더링 기술을 활용하기 때문이다.

즉, 메모리를 손해보고 속도 측면에서 이득을 본 것이다.

 

문제 해결 과정(시행 착오)

1) 처음에는 새로운 쿠키를 생성해서 각 쿠키에 분산해서 담으면 되지 않을까? 라고 생각하여 쿠키를 랜덤으로 만들어주는 코드를 넣었다.

결과는 똑같은 오류가 발생하였다.

 

2) 구글링을 해본 결과 disk-cache-size을 조정하면 해결이 된다고 하여 이를 조정하고 보안 기능 비활성화, 시크릿 모드 활성화 등 캐시와 쿠키를 비활성화하기 위해 아래와 같은 코드를 추가하였다.

 

결과는 똑같은 오류가 발생하였다.ㅠㅠ

#chromeOptions에 disk-cache-size를 0으로 지정한다. (크롤링 하다 중간에 메모리 문제로 끊기는 것을 방지)
chrome_options.add_argument("--disk-cache-size=0") 
#chrome_options.add_argument("--incognito") # 시크릿 모드 (캐시, 쿠키 기능 비활성화)
# chrome_options.add_argument('headless')
chrome_options.add_argument('--no-sandbox') # 보안 기능 비활성화 (샌드박스라는 공간을 비활성화 시킨다는 뜻)
chrome_options.add_argument('--disable-dev-shm-usage') # /dev/shm(공유메모리) 디렉토리를 사용하지 않는다는 뜻
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument("window-size=1400,600")

 

3) 크롤링 하는 중간마다 구글에서 인터넷 사용 기록을 삭제하는 코드를 추가한다.

하지만 인터넷 사용 기록 삭제를 하려고 CSS 선택자를 확인해보니 실제로 선택이 되지 않도록 막아두었다.

인터넷 사용 기록 삭제 버튼을 css 선택자로 선택할 수 없도록 막았다ㅠㅠ.

방법이 없을까? 고민하다가 단축키를 이용하였다. 이 방법은 막히지 않은 것 같다. (코드는 아래 '문제 해결' 란에 있습니다.)

 

문제 해결

 크롤링 하는 중간마다 구글에서 인터넷 사용 기록을 삭제하는 코드를 추가하여 주기적으로 delete_cash 함수를 호출해주었다.

주의사항 : 각 탭에 대해서 인터넷 사용 기록을 삭제해야한다. (탭이 3개라면 주기적으로 3개 탭에 대해서 모두 인터넷 사용 기록을 삭제하는 로직을 수행해주는 것이 안전하다.)

service = Service() # chrome-for-testing 버전에 맞춰 적용되는 코드
driver = webdriver.Chrome(service=service, options=chrome_options)

def delete_cash(driver):
    driver.get("chrome://settings/clearBrowserData")
    driver.implicitly_wait(10)
    time.sleep(3)
    element = driver.find_element(By.XPATH, "//settings-ui")

    element.send_keys(mouse_button.MouseButton.LEFT)
    element.send_keys(Keys.ENTER)

    time.sleep(1)
    
 delete_cash(driver)


이제 크롤링을 하다가 메모리가 뻗지 않고 잘 실행되었다.