DBCP

일반적으로 데이터베이스의 Connection을 만드는 과정은 복잡하기 떄문에 비용이 비싸다. 그렇기 때문에 DBCP를 이용하여 때문에 커넥션을 미리 만들어놓고 필요할때마다 가져다 쓰는 방식으로 커넥션을 관리한다.

DBCP는 애플리케이션 성능에 핵심적인 역할을 하며 DBCP에 버그가 존재할 경우 디버깅하기 힘든 심각한 상황이 될 수 있다.

스프링부트 DBCP

  1. HikariCP
  2. Tomcat CP
  3. Commons DBCP2

스프링부트는 HikariCP를 기본으로 선택했다. 여기서는 HikariCP만 살펴보자. HikariCP Github에서 HikariCP가 제공하는 다양한 다양한 옵션을 설명한다. 성능 최적화를 위해서는 이러한 옵션들을 상황에 맞게 조절해야한다.

  • autoCommit
    • 기본값이 true. true인 경우 commit을 명시하지 않아도 자동으로 SQL 실행 후 commit이 수행된다.
  • connectionTimeout
    • 커넥션 객체를 애플리케이션한테 얼마동안 전달하지 못하면 예외를 던질 것인가에 대한 설정이다.
    • 짧으면 짧을수록 에러가 날 확률이 높기 때문에 적당한 값을 주는 것이 좋다.
    • 기본값은 30이다. 애플리케이션에 커넥션 객체를 30초동안 전달하지 지나서야 예외를 받는다.
  • maximumPoolSize
    • 커넥션 객체를 몇개를 유지할 것인지 결정한다.
    • 커넥션 객체가 많다고해서 전부 실행할 수 있지는 않다.
    • 동시 실행할 수 있는 커넥션 개수는 CPU 코어 개수와 같다. 코어 개수가 넘어간 커넥션(쓰레드)들은 대기 상태에 있게된다.

스프링부트 설정

spring.datasource.hikari.maxmimum-pool-size=4 # PC의 local 코어가 2개라 pool-size를 4개로 설정했다

HikariCP에 관련된 프로퍼티즈는 HikariDataSource가 상속하고 있는 HikariConfig에서 제공한다. 해당 클래스를 살펴보는 것도 좋지만 문서를 참조하는 것이 가장 좋다.

MySQL 실습

간단한 실습으로 스프링부트에 MySQL을 연동해보자.

도커: MySQL 설치 & 실행

docker run -p 3306:3306 –name mysql_boot -e MYSQL_ROOT_PASSWORD=1 -e MYSQL_DATABASE=springboot -e MYSQL_USER=keesun -e MYSQL_PASSWORD=pass -d mysql

docker exec -i -t mysql_boot bash

mysql -u root -p

먼저 MySQL 커넥터(JDBC가 아니다) 에 대한 의존성이 필요하다.

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

JDBC URL과 연결정보를 설정한다.

spring.datasource.url=jdbc:mysql://192.168.99.100:3306/springboot
spring.datasource.username=jch
spring.datasource.password=pass

인메모리 데이터베이스 에서 작성한 러너에서 테스트로 연결정보를 출력하고 쿼리를 전송해보자.

@Component
public class MySQLRunner implements ApplicationRunner {

    @Autowired
    DataSource dataSource;

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        try (Connection connection = dataSource.getConnection()) {
            System.out.println("===============");
            System.out.println(dataSource.getClass());
            System.out.println(connection.getMetaData().getURL());
            System.out.println(connection.getMetaData().getUserName());

            Statement statement = connection.createStatement();
            String sql = "CREATE TABLE USER(ID INTEGER NOT NULL, name VARCHAR(255), PRIMARY KEY (id))";
            statement.executeUpdate(sql);
        }

        jdbcTemplate.execute("INSERT INTO USER VALUES (1, 'jch')");
    }
}

앱이 실행되면 run 메소드가 호출되면서 테이블과 데이터가 생성된 것을 확인할 수 있다.

MySQL 접속시 에러(SSL 관련 경고)

MySQL 5.* 버전

문제 Sat Jul 21 11:17:59 PDT 2018 WARN: Establishing SSL connection without server’s identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn’t set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to ‘false’. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
해결 jdbc:mysql:/localhost:3306/springboot?**useSSL=false ** 같이 SSL 접속을 false로 설정한다.

MySQL 8.* 이후 버전

문제 com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Public Key Retrieval is not allowed
해결 jdbc:mysql:/localhost:3306/springboot?useSSL=false&allowPublicKeyRetrieval=true

allowPublicKeyRetrieval를 true로 설정하는 해결법은 MySQL 라이센스 (GPL)를 주의해야한다. MySQL은 상용 애플리케이션의 경우 엔터프라이즈 라이센스를 갱신하면서 사용해야 한다. 또한, GPL 라이센스를 사용하기 때문에 소스 코드 공개 의무가 있다. 라이센스 비용이 문제가 되는 경우 MySQL 대신 MariaDB 사용할 수 있다.

해당 포스팅은 스프링 부트 개념과 활용 강의 내용을 토대로 작성하였습니다.