Could not load JDBC driver class [org.h2.Driver] 발생 원인과 해결 방법
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in ServletContext resource [/WEB-INF/spring/root-context.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'driverClassName' threw exception; nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [org.h2.Driver]
해당 문제는 maven 빌드 툴을 사용하는 spring 프로젝트에서 h2 데이터베이스를 연결하는 과정에서 발생하였으며, 문제의 원인은 pom.xml 파일의 h2 데이터베이스 dependency 중 scope 값으로 인해 발생하였습니다.
(작업 환경은 spring framework 5.2.5 RELEASE + java 11 + h2 2.2.220 입니다.)
h2 데이터베이스 의존성을 사용하기 위해 Maven Repository에서 위 dependency 부분을 그대로 적용하였습니다.
이때 간과한 점이 바로 'scope' 설정인데요.
pom.xml 파일에서 의존성 설정에 사용되는 각 dependency는 scope 설정을 가지고 있으며, scope 설정은 해당 의존성이 사용되는 범위를 지정하기 위해 설정됩니다.
maven에서는 compile, provided, runtime, test, system, import 총 6가지의 scope 범위를 제공하는데요.
maven repository에서 그대로 복사해 온 h2 database 의존성의 scope 값이 '<scope>test</scope>'로 되어 있었으며, test 설정의 경우 테스트 클래스 경로에서만 해당 의존성을 사용할 수 있으며, 런타임이나 컴파일 시점에는 필요하지 않다는 설정이기 때문에 프로젝트 실행 시 위와 같이 'org.h2.Driver' driver class를 로드하지 못하는 문제가 발생했던 것입니다.
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.220</version>
<scope>runtime</scope>
</dependency>
(pom.xml 파일 h2 database 의존성 scope 수정)
문제의 해결 방안은 scope 설정을 '<scope>runtime</scope>'로 바꾸는 것인데요.
runtime 설정의 경우 해당 의존성이 컴파일 시에는 필요하지 않고 런타임 환경에서만 필요한 경우, 특히 JDBC 드라이버 등에 많이 사용되는 설정입니다.
추가로 <scope></scope> 부분을 아예 제거해 버리면 scope 값이 default 설정인 'compile'이 적용되며, runtime과 동일하게 위와 같은 문제가 발생하지 않게 되는데요.
하지만 compile 설정의 경우 해당 의존성이 모든 클래스 경로에 포함되기 때문에 컴파일 시점과 런타임 시점, 테스트 클래스 경로 모두 사용할 수 있지만, 컴파일 단계에서 불필요한 의존성이 포함되는 것이기 때문에 약간이겠지만 성능적 낭비가 생길 수 있습니다.
또한 scope 설정을 runtime으로 지정함으로써 해당 의존성이 런타임 시점에만 필요하다고 명확하게 구분하여 관리할 수 있다는 장점이 있습니다.
추가로 properties 파일 설정으로 인해 발생하는 Cannot load driver class: org.h2.Driver
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception with message: Cannot load driver class: org.h2.Driver
추가로 SpringBoot 환경에서 'Cannot load driver class: org.h2.Driver' 문제가 발생하는 경우 아래와 같이 datasource 설정 값을 관리하는 properties 파일에서 'spring.datasource.driver-class-name' 값에 대해 'org.h2.Driver' 뒤에 공백이 들어간 경우가 원인일 수 있습니다.
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:test
spring.datasource.username=sa
spring.datasource.password=