728x90
반응형
🎯 개요
Java 애플리케이션에서 SQLite 데이터베이스를 사용하기 위한 JDBC 연결 설정부터 실제 사용까지의 전체 과정을 다룹니다. Maven 프로젝트 기준으로 설명하며, 실무에서 바로 활용할 수 있는 코드 예제를 포함합니다.
📋 목차
- JDBC란 무엇인가?
- Maven 의존성 설정
- SQLite JDBC 드라이버 설정
- 데이터베이스 연결 구현
- 연결 테스트
- 실무 팁과 Best Practices
- 문제 해결
🔍 JDBC란 무엇인가?
**JDBC (Java Database Connectivity)**는 Java 애플리케이션이 데이터베이스와 상호작용할 수 있게 해주는 API입니다.
JDBC의 핵심 구성요소
- DriverManager: 데이터베이스 드라이버 관리
- Connection: 데이터베이스 연결 인터페이스
- Statement/PreparedStatement: SQL 실행
- ResultSet: 쿼리 결과 처리
SQLite를 선택하는 이유
- ✅ 경량: 별도 서버 설치 불필요
- ✅ 파일 기반: 단일 파일로 데이터베이스 관리
- ✅ 크로스 플랫폼: 다양한 운영체제 지원
- ✅ 개발 친화적: 빠른 프로토타이핑과 테스트에 적합
🛠️ Maven 의존성 설정
1단계: pom.xml 기본 설정
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>jdbc-sqlite-example</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
2단계: SQLite JDBC 의존성 추가
xml
<dependencies>
<!-- SQLite JDBC Driver -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.42.0.1</version>
</dependency>
<!-- 테스트를 위한 JUnit (선택사항) -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
3단계: Maven 플러그인 설정
xml
<build>
<plugins>
<!-- Java 컴파일러 플러그인 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<!-- 실행 가능한 JAR 생성 플러그인 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
🔗 SQLite JDBC 드라이버 설정
JDBC URL 형식 이해하기
java
// 기본 형식
jdbc:sqlite:경로/파일명.db
// 예시들
jdbc:sqlite:mydata.db // 현재 디렉터리
jdbc:sqlite:/absolute/path/to/mydata.db // 절대 경로
jdbc:sqlite:./relative/path/mydata.db // 상대 경로
jdbc:sqlite::memory: // 메모리 DB (테스트용)
프로젝트 구조에 맞는 DB 경로 설정
project-root/
├── src/
│ ├── main/
│ │ ├── java/
│ │ └── resources/
│ │ └── database/
│ │ └── mydata.db ← SQLite 파일 위치
│ └── test/
├── target/
└── pom.xml
권장 JDBC URL:
java
private static final String DB_URL = "jdbc:sqlite:src/main/resources/database/mydata.db";
💻 데이터베이스 연결 구현
1단계: 연결 유틸리티 클래스 생성
java
package com.example.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 데이터베이스 연결 관리 유틸리티 클래스
* SQLite 데이터베이스와의 연결, 초기화, 종료를 담당
*/
public class DatabaseUtil {
// 데이터베이스 연결 URL
private static final String DB_URL = "jdbc:sqlite:src/main/resources/database/mydata.db";
/**
* 데이터베이스 연결을 반환합니다.
* @return Connection 객체
* @throws SQLException 연결 실패시 예외 발생
*/
public static Connection getConnection() throws SQLException {
try {
// SQLite JDBC 드라이버가 자동으로 로드됩니다 (JDBC 4.0+)
return DriverManager.getConnection(DB_URL);
} catch (SQLException e) {
System.err.println("데이터베이스 연결 실패: " + e.getMessage());
throw e;
}
}
/**
* 데이터베이스와 테이블을 초기화합니다.
* 애플리케이션 시작시 한 번 호출됩니다.
*/
public static void initializeDatabase() {
// 테이블 생성 SQL (존재하지 않을 경우에만)
String createTableSQL = """
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)
""";
try (Connection conn = getConnection();
Statement stmt = conn.createStatement()) {
// 테이블 생성
stmt.execute(createTableSQL);
System.out.println("✅ 데이터베이스 초기화 완료");
} catch (SQLException e) {
System.err.println("❌ 데이터베이스 초기화 실패: " + e.getMessage());
}
}
/**
* 데이터베이스 연결을 안전하게 종료합니다.
* @param conn 종료할 Connection 객체
*/
public static void closeConnection(Connection conn) {
if (conn != null) {
try {
conn.close();
System.out.println("🔒 데이터베이스 연결 종료");
} catch (SQLException e) {
System.err.println("연결 종료 중 오류 발생: " + e.getMessage());
}
}
}
/**
* 데이터베이스 연결 상태를 확인합니다.
* @return 연결 성공시 true, 실패시 false
*/
public static boolean testConnection() {
try (Connection conn = getConnection()) {
if (conn != null && !conn.isClosed()) {
System.out.println("✅ 데이터베이스 연결 테스트 성공");
return true;
}
} catch (SQLException e) {
System.err.println("❌ 연결 테스트 실패: " + e.getMessage());
}
return false;
}
}
2단계: 연결 테스트 클래스
java
package com.example.test;
import com.example.util.DatabaseUtil;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
/**
* JDBC 연결 테스트를 위한 클래스
* 데이터베이스 연결 상태와 드라이버 정보를 확인합니다.
*/
public class ConnectionTest {
public static void main(String[] args) {
System.out.println("🚀 JDBC 연결 테스트 시작");
System.out.println("=" .repeat(50));
testBasicConnection();
testDatabaseInfo();
testDatabaseOperations();
System.out.println("=" .repeat(50));
System.out.println("✅ 모든 테스트 완료");
}
/**
* 기본 연결 테스트
*/
private static void testBasicConnection() {
System.out.println("1️⃣ 기본 연결 테스트");
try (Connection conn = DatabaseUtil.getConnection()) {
if (conn != null) {
System.out.println(" ✅ SQLite 연결 성공!");
System.out.println(" 📍 연결 상태: " + !conn.isClosed());
}
} catch (SQLException e) {
System.err.println(" ❌ 연결 실패: " + e.getMessage());
}
System.out.println();
}
/**
* 데이터베이스 정보 조회 테스트
*/
private static void testDatabaseInfo() {
System.out.println("2️⃣ 데이터베이스 정보 조회");
try (Connection conn = DatabaseUtil.getConnection()) {
DatabaseMetaData metaData = conn.getMetaData();
System.out.println(" 📊 데이터베이스 제품: " + metaData.getDatabaseProductName());
System.out.println(" 🔢 제품 버전: " + metaData.getDatabaseProductVersion());
System.out.println(" 🚗 드라이버 이름: " + metaData.getDriverName());
System.out.println(" 📝 드라이버 버전: " + metaData.getDriverVersion());
System.out.println(" 🔗 JDBC URL: " + metaData.getURL());
} catch (SQLException e) {
System.err.println(" ❌ 정보 조회 실패: " + e.getMessage());
}
System.out.println();
}
/**
* 데이터베이스 기본 작업 테스트
*/
private static void testDatabaseOperations() {
System.out.println("3️⃣ 데이터베이스 작업 테스트");
// 데이터베이스 초기화
DatabaseUtil.initializeDatabase();
// 간단한 쿼리 실행 테스트
try (Connection conn = DatabaseUtil.getConnection()) {
// SQLite 버전 확인 쿼리
var stmt = conn.createStatement();
var rs = stmt.executeQuery("SELECT sqlite_version()");
if (rs.next()) {
System.out.println(" ✅ SQLite 버전: " + rs.getString(1));
}
} catch (SQLException e) {
System.err.println(" ❌ 작업 테스트 실패: " + e.getMessage());
}
System.out.println();
}
}
3단계: 실제 사용 예제
java
package com.example.dao;
import com.example.util.DatabaseUtil;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* User 데이터 접근 객체 (DAO)
* CRUD 작업을 담당합니다.
*/
public class UserDao {
/**
* 사용자 추가
*/
public void insertUser(String name, String email) throws SQLException {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, name);
pstmt.setString(2, email);
int rowsAffected = pstmt.executeUpdate();
System.out.println("✅ " + rowsAffected + "명의 사용자가 추가되었습니다.");
} catch (SQLException e) {
System.err.println("❌ 사용자 추가 실패: " + e.getMessage());
throw e;
}
}
/**
* 모든 사용자 조회
*/
public List<User> selectAllUsers() throws SQLException {
String sql = "SELECT id, name, email, created_at FROM users ORDER BY created_at DESC";
List<User> users = new ArrayList<>();
try (Connection conn = DatabaseUtil.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
user.setCreatedAt(rs.getString("created_at"));
users.add(user);
}
} catch (SQLException e) {
System.err.println("❌ 사용자 조회 실패: " + e.getMessage());
throw e;
}
return users;
}
}
🧪 연결 테스트
Maven으로 테스트 실행
bash
# 의존성 확인
mvn dependency:tree
# 컴파일
mvn clean compile
# 연결 테스트 실행
mvn exec:java -Dexec.mainClass="com.example.test.ConnectionTest"
성공적인 테스트 결과 예시
🚀 JDBC 연결 테스트 시작
==================================================
1️⃣ 기본 연결 테스트
✅ SQLite 연결 성공!
📍 연결 상태: true
2️⃣ 데이터베이스 정보 조회
📊 데이터베이스 제품: SQLite
🔢 제품 버전: 3.42.0
🚗 드라이버 이름: SQLite JDBC
📝 드라이버 버전: 3.42.0.1
🔗 JDBC URL: jdbc:sqlite:src/main/resources/database/mydata.db
3️⃣ 데이터베이스 작업 테스트
✅ 데이터베이스 초기화 완료
✅ SQLite 버전: 3.42.0
==================================================
✅ 모든 테스트 완료
💡 실무 팁과 Best Practices
1. 연결 관리 Best Practices
java
// ✅ 좋은 예: try-with-resources 사용
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 작업 수행
} catch (SQLException e) {
// 예외 처리
}
// ❌ 나쁜 예: 수동 연결 관리
Connection conn = null;
try {
conn = DatabaseUtil.getConnection();
// 작업 수행
} finally {
if (conn != null) conn.close(); // 누락 가능성
}
2. SQL Injection 방지
java
// ✅ 안전: PreparedStatement 사용
String sql = "SELECT * FROM users WHERE name = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userName);
// ❌ 위험: 문자열 연결
String sql = "SELECT * FROM users WHERE name = '" + userName + "'";
3. 트랜잭션 관리
java
public void transferData() throws SQLException {
Connection conn = DatabaseUtil.getConnection();
try {
conn.setAutoCommit(false); // 트랜잭션 시작
// 여러 DB 작업 수행
insertUser(conn, "user1", "user1@example.com");
updateUserStatus(conn, 1, "active");
conn.commit(); // 트랜잭션 커밋
System.out.println("✅ 트랜잭션 성공");
} catch (SQLException e) {
conn.rollback(); // 트랜잭션 롤백
System.err.println("❌ 트랜잭션 실패, 롤백됨");
throw e;
} finally {
conn.setAutoCommit(true); // 자동 커밋 복원
conn.close();
}
}
4. 연결 풀링 (고급)
xml
<!-- HikariCP 연결 풀 의존성 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
java
public class ConnectionPool {
private static HikariDataSource dataSource;
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:sqlite:src/main/resources/database/mydata.db");
config.setMaximumPoolSize(10);
config.setMinimumIdle(2);
dataSource = new HikariDataSource(config);
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
🚨 문제 해결
자주 발생하는 오류와 해결책
1. ClassNotFoundException: org.sqlite.JDBC
원인: SQLite JDBC 드라이버를 찾을 수 없음
해결책:
bash
# Maven 의존성 재다운로드
mvn clean install -U
# 의존성 확인
mvn dependency:tree | grep sqlite
2. SQLException: Database is locked
원인: 다른 프로세스가 데이터베이스 파일을 사용 중
해결책:
java
// 연결 URL에 타임아웃 설정 추가
private static final String DB_URL =
"jdbc:sqlite:mydata.db?busy_timeout=30000";
3. Text blocks are not supported in -source 8
원인: Java 8에서 Text Blocks 사용
해결책:
java
// Java 8 호환 코드로 변경
String sql = "CREATE TABLE IF NOT EXISTS users (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"name TEXT NOT NULL" +
")";
4. 한글 깨짐 현상
해결책:
java
// 연결 URL에 인코딩 설정
private static final String DB_URL =
"jdbc:sqlite:mydata.db?encoding=UTF-8";
디버깅 팁
java
// 연결 상태 로깅
public static void logConnectionInfo(Connection conn) throws SQLException {
DatabaseMetaData meta = conn.getMetaData();
System.out.println("🔍 디버깅 정보:");
System.out.println(" - 연결 상태: " + !conn.isClosed());
System.out.println(" - 자동 커밋: " + conn.getAutoCommit());
System.out.println(" - 트랜잭션 격리: " + conn.getTransactionIsolation());
System.out.println(" - 카탈로그: " + conn.getCatalog());
}
📚 참고 자료
- SQLite JDBC 공식 문서
- Oracle JDBC 튜토리얼
- SQLite 공식 문서
- Maven 의존성 관리
🎯 마무리
이 가이드를 통해 Java와 SQLite JDBC 연결을 성공적으로 구현했습니다. 핵심 포인트를 요약하면:
- Maven 의존성: sqlite-jdbc 라이브러리 추가
- 연결 관리: try-with-resources로 안전한 연결 관리
- 보안: PreparedStatement로 SQL Injection 방지
- 예외 처리: 적절한 SQLException 처리
- 테스트: 연결 상태 및 기능 검증
실제 프로덕션 환경에서는 연결 풀링, 트랜잭션 관리, 로깅 등을 추가로 고려해야 합니다. 이 기초를 바탕으로 더 복잡한 데이터베이스 애플리케이션을 구축할 수 있을 것입니다.
728x90
반응형
'유용한 컴공 테크닉' 카테고리의 다른 글
Spring Boot로 CRUD REST API 만들기: 제로부터 배포까지 (3) | 2025.07.10 |
---|---|
Postman 완벽 가이드: REST API 테스트부터 협업까지 (1) | 2025.07.10 |
로그인 필요없이 몇 초만에 무료 이미지 얻는 사이트 2탄 - unsplash (0) | 2021.02.05 |
React , React Native 에 관한 배경 및 지식 for 잘난 척 (0) | 2021.02.05 |
무료 이미지 얻는 사이트, pixabay (0) | 2021.01.14 |