Docker 환경에서 Selenium WebDriver 설정하기

왔다 정보리·2025년 7월 29일
0
post-thumbnail

Docker 환경에서 Selenium으로 웹 크롤링을 해야 할 일이 있었다. 로컬 환경에서는 따로 chromium을 다운받지 않고도 실행이 잘 되었지만, Docker 환경에서 돌려보니 크롬을 인식하지 못해서 WebDriver가 초기화되지 않는 문제가 발생했다. 그 과정을 어떻게 해결했는지 정리해보려 한다!

참고로 내가 마주한 에러는 다음과 같았다.

Error creating bean with name 'webDriver' defined in class path resource

Chromium 설치


1. Dockerfile를 설정한다

# Chromium 설치
RUN apk add --no-cache \
    gcompat glib nss libxcb libgcc \
    chromium \
    chromium-chromedriver

Dockerfile에서 Chromium을 설치해야 한다. A1pine Linux 환경에서는 apk를 통해 설치할 수 있다.

패키지 옵션

패키지역할중요도
gcompatAlpine Linux와 GNU C 라이브러리 호환성 제공필수
glibChromium 엔진 프로세스/메모리 관리필수
nssHTTPS/SSL 암호화 처리HTTPS 링크 접근에 필수
libxcbX11 클라이언트 라이브러리헤드리스 모드에서 렌더링에 필수
libgccGCC 런타임 라이브러리C++ 예외처리 및 기본 런타임 기능
chromium브라우저필수
chromium-chromedriverSelenium과 Chromium을 연결하는 드라이버필수

여기서 사용한 패키지 외에도 자신이 필요한 패키지를 같이 다운받아서 사용하면 된다.

2. WebDriverConfig를 작성한다

@Configuration
public class SeleniumConfig {
    @Bean
    public WebDriver webDriver() {
        // ChromeDriver 경로 설정 (선택)
        String chromeDriverPath = "/usr/bin/chromedriver";
        System.setProperty("webdriver.chrome.driver", chromeDriverPath);

        // Chromium 바이너리 경로 (필수)
        ChromeOptions options = new ChromeOptions();

        options.setBinary("/usr/bin/chromium-browser");

        // 헤드리스 모드
        options.addArguments("--headless=new");
        options.addArguments("--no-sandbox");
        options.addArguments("--disable-dev-shm-usage");
        options.addArguments("--disable-gpu");

        return new ChromeDriver(options);
    }
}

설치한 Chromium을 Spring Boot 환경에서 사용하기 위해 WebDriverConfig를 작성해준다. 이때 Chromium 브라우저를 찾기 위해 chromium-browser의 위치를 확인해서 setBinary()에 넣어줘야 한다.

설정 옵션

옵션설명중요도
--headless=newGUI 없이 실행하는 헤드리스 모드필수
--no-sandbox샌드박스 보안 기능 비활성화Docker 컨테이너에 필수
--disable-dev-shm-usage/dev/shm 공유 메모리 비활성화메모리 부족 방지
--disable-gpuGPU 하드웨어 가속 비활성화안정성 향상

WebDriver 메모리 최적화


1. Scope를 Prototype으로 지정한다

@Bean
@Scope("prototype")
public WebDriver webDriver() {
    // 로직 구현
}

기본적으로 Bean Scope는 singleton으로 설정이 되어 있다. Scope를 singleton으로 설정하면 애플리케이션 전체에서 하나의 WebDriver 인스턴스를 공유하게 된다.
하지만 Scope를 prototype으로 설정하면 getBean()을 호출할 때마다 새로운 WebDriver 인스턴스를 생성한다. prototype을 설정된 Bean은 Spring이 생성만 담당하고, 소멸은 개발자가 직접 관리해야 한다. 따라서 반드시 수동으로 quit()을 호출해야 한다.

2. WebDriver를 사용할 때마다 생성 및 해제를 진행한다

private final ApplicationContext context;

public void useWebDriver() {
		WebDriver webDriver = context.getBean(WebDriver.class);
		
		try {
		    // 로직 구현
		} finally {
		    webDriver.quit();
		}
}

스케쥴러가 돌 때마다 WebDriver 인스턴스를 생성하고 해제할 수 있도록 한다. 이때 WebDriver는 @Autowired로 직접 주입하면 안 되고, context.getBean(WebDriver.class)로 매번 새로운 인스턴스를 생성해야 한다.
WebDriver 사용이 끝나면 webDriver.quit()을 통해 인스턴스를 해제한다. 이렇게 하면 WebDriver를 사용할 때만 메모리가 사용되고, quit()이 호출되면 사용하던 메모리를 해제하기 때문에 메모리 최적화에 도움이 된다.

참고 자료


크롬 드라이버, 셀레니움, 도커 환경 연동
[Spring] 빈 스코프란? (Singleton, Prototype Scope)

profile
왔다 정보리

0개의 댓글