[Day 27 | Spring] Spring Boot - JDBC 연결과 DataSource (MariaDB)

y♡ding·2024년 11월 19일

데브코스 TIL - Spring

목록 보기
14/46

SQL Databases :: Spring Boot

1. 프로젝트 설정

1-1. 의존성 추가

Spring Boot 프로젝트의 build.gradle 또는 pom.xml 파일에 필요한 의존성을 추가합니다.

Gradle 예시:

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'  // JDBC API
    implementation 'org.mariadb.jdbc:mariadb-java-client' // MariaDB JDBC 드라이버
}

2. 데이터베이스 설정

2-1. application.properties

MariaDB 데이터베이스 연결 정보를 설정합니다.

# 데이터베이스 URL 및 인증 정보
spring.datasource.url=jdbc:mariadb://localhost:3306/your_database_name
spring.datasource.username=your_username
spring.datasource.password=your_password

# JDBC 기본 설정
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.initialization-mode=always

2-2. application.yml (YAML 형식)

spring:
  datasource:
    url: jdbc:mariadb://localhost:3306/your_database_name
    username: your_username
    password: your_password
    driver-class-name: org.mariadb.jdbc.Driver
    initialization-mode: always

Spring Boot에서 DataSource는 데이터베이스 연결을 설정하고 관리하는 기본 객체입니다. JDBC를 사용할 때 핵심적인 역할을 하며, 애플리케이션에서 데이터베이스 연결 풀(Connection Pool)을 생성, 관리합니다.


DataSource란?

  • DataSource는 JDBC API에서 데이터베이스 연결을 추상화한 인터페이스입니다.
  • 데이터베이스 연결 풀(Connection Pool)을 관리하고, 효율적인 연결 재활용을 제공합니다.
  • Spring Boot는 DataSource를 자동으로 구성하며, 주요 구현체로는 HikariCP, Apache DBCP, Tomcat JDBC Connection Pool 등이 사용됩니다.
  • 기본적으로 Spring Boot는 HikariCP를 사용합니다.


3. DataSource를 직접 확인

Spring Boot에서 구성된 DataSource 객체를 직접 확인하려면 @Bean이나 @Autowired를 사용하여 주입받을 수 있습니다.

확인용 Controller 작성

아래 코드를 작성하면 애플리케이션에서 사용하는 DataSource 정보(클래스 이름, URL 등)를 확인할 수 있습니다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.sql.DataSource;

@RestController
public class DataSourceController {

    @Autowired
    private DataSource dataSource;

    @GetMapping("/datasource-info")
    public String getDataSourceInfo() {
        StringBuilder info = new StringBuilder();
        info.append("DataSource Class: ").append(dataSource.getClass().getName()).append("<br>");
        try {
            info.append("JDBC URL: ").append(dataSource.getConnection().getMetaData().getURL()).append("<br>");
            info.append("DB Username: ").append(dataSource.getConnection().getMetaData().getUserName()).append("<br>");
        } catch (Exception e) {
            info.append("Error retrieving DataSource info: ").append(e.getMessage());
        }
        return info.toString();
    }
}

실행 결과

  • 애플리케이션을 실행한 뒤 브라우저에서 http://localhost:8080/datasource-info로 접속하면 DataSource 정보가 출력됩니다.
  • 예시 출력:
DataSource Class: com.zaxxer.hikari.HikariDataSource
JDBC URL: jdbc:mariadb://localhost:3306/your_database_name
DB Username: your_username

4. DataSource를 Bean으로 명시적 등록하기

Spring Boot의 자동 설정 대신 명시적으로 DataSource를 정의할 수도 있습니다.

명시적 등록 예제

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.zaxxer.hikari.HikariDataSource;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {

    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mariadb://localhost:3306/your_database_name");
        dataSource.setUsername("your_username");
        dataSource.setPassword("your_password");
        dataSource.setMaximumPoolSize(10);  // 최대 커넥션 수
        return dataSource;
    }
}

6. 커넥션 풀 기본 개념

Spring Boot의 기본 데이터베이스 연결 풀인 HikariCP의 특징:

  1. 빠르고 경량화된 커넥션 풀.
  2. 최소/최대 커넥션 풀 크기를 조정 가능.
  3. spring.datasource.hikari를 통해 세부 설정 가능.

주요 설정 옵션:

설정 키설명기본값
spring.datasource.hikari.maximum-pool-size최대 커넥션 풀 크기10
spring.datasource.hikari.minimum-idle최소 유휴 커넥션 수10
spring.datasource.hikari.connection-timeout연결 대기 시간(ms)30000
spring.datasource.hikari.idle-timeout유휴 커넥션 제거 시간(ms)600000

실습 코드

DB 연결(JDBC)

데이터베이스에서 현재 시간 가져오기

@SpringBootApplication
public class Jdbc01Application implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(Jdbc01Application.class, args);
    }

    @Override
    public void run(String... args) {
        String url = "jdbc:mariadb://localhost:3306/mysql";
        String user = "root";
        String password = "exxyeon";

        // 데이터베이스에서 현재 시간을 얻어 오는 프로그램
        Connection conn = null;
        PreparedStatement psmt = null;
        ResultSet rs = null;

        try {
            Class.forName("org.mariadb.jdbc.Driver");
            conn = DriverManager.getConnection(url, user, password);

            String sql = "select now() as now";
            psmt = conn.prepareStatement(sql);
            rs = psmt.executeQuery();

            if (rs.next()) {
                System.out.println("현재 시간: " + rs.getString("now"));
            }
        } catch (ClassNotFoundException e) {
            System.out.println("[에러] " + e.getMessage());
        } catch (SQLException e) {
            System.out.println("[에러] " + e.getMessage());
            throw new RuntimeException(e);
        } finally {
            if (rs != null) { try { rs.close(); } catch (SQLException e) {}}
            if (psmt != null) { try { psmt.close(); } catch (SQLException e) {}}
            if (conn != null) { try { conn.close(); } catch (SQLException e) {}}
        }
    }
}

Database Pooling

 # Mariadb 접속에 대한 설정
 spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
 spring.datasource.url=jdbc:mariadb://localhost:3306/mysql
 spring.datasource.username=root
 spring.datasource.password=exxyeon
   @SpringBootApplication
   public class Jdbc02Application implements CommandLineRunner {
   
       @Autowired
       private DataSource dataSource;
       
       public static void main(String[] args) {
           SpringApplication.run(Jdbc02Application.class, args);
       }
   
       @Override
       public void run(String... args) throws Exception {
           // Hikari Database Pooling Library
           System.out.println("dataSource: " + dataSource); //HikariDataSource (null)
           System.out.println("Connection: " + dataSource.getConnection()); 
       }
   }

간접적인 DB 연결

  @Override
     public void run(String... args) throws Exception {
         // Hikari Database Pooling Library
         System.out.println("dataSource: " + dataSource); //HikariDataSource (null)
         System.out.println("Connection: " + dataSource.getConnection());
 
         Connection conn = null;
         PreparedStatement psmt = null;
         ResultSet rs = null;
 
         try {
             **conn = dataSource.getConnection();**
 
             String sql = "select now() as now";
             psmt = conn.prepareStatement(sql);
             rs = psmt.executeQuery();
 
             if (rs.next()) {
                 System.out.println("현재 시간: " + rs.getString("now"));
             }
             **// ClassNotFoundException X**
         } catch (SQLException e) {
             System.out.println("[에러] " + e.getMessage());
             throw new RuntimeException(e);
         } finally {
             if (rs != null) { try { rs.close(); } catch (SQLException e) {}}
             if (psmt != null) { try { psmt.close(); } catch (SQLException e) {}}
             if (conn != null) { try { conn.close(); } catch (SQLException e) {}}
         }

0개의 댓글