상세 컨텐츠

본문 제목

JDBC

백엔드/Java

by Ryuzy 2025. 5. 29. 01:19

본문

728x90
반응형

1. JDBC

JDBC(Java Database Connectivity)는 자바에서 데이터베이스에 접근하고 SQL을 실행할 수 있도록 지원하는 표준 API(인터페이스)입니다. 이를 통해 자바 애플리케이션은 MySQL, Oracle, PostgreSQL 등 다양한 관계형 데이터베이스에 연결하여 데이터를 조회하거나 추가, 수정, 삭제할 수 있습니다. JDBC는 데이터베이스별로 제공되는 드라이버를 통해 실제 연결을 처리하며, 주요 구성 요소로는 데이터베이스와의 연결을 관리하는 Connection, SQL을 실행하는 Statement 또는 PreparedStatement, 결과를 처리하는 ResultSet 등이 있습니다. JDBC는 자바와 DB 간의 중간 다리 역할을 하며, 자바 애플리케이션에서 데이터베이스를 활용한 기능을 개발하는 데 필수적인 기술입니다.

 

 

2. MySQL과의 연동

1. MySQL 설치

  • MySQL 서버 설치 (Windows/Mac/Linux 중 선택)
  • DB 사용자 계정 및 비밀번호 확인
  • 예: user: root, password: 1234

 

2. JDBC 드라이버 설치

  • MySQL Connector/J를 다운로드하거나,
  • Maven/Gradle을 사용할 경우 자동으로 라이브러리를 추가 가능
  • JDBC 드라이버 의존성 추가 (Maven 기준)
<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
</dependencies>

 

Maven

Maven은 자바 프로젝트의 빌드(build), 의존성 관리(dependency management), 프로젝트 구조화 등을 자동으로 처리해주는 빌드 도구(Build Tool)입니다. 개발자가 필요한 외부 라이브러리를 일일이 다운로드하지 않고, pom.xml 파일에 필요한 라이브러리를 선언만 하면 Maven이 자동으로 인터넷에서 해당 JAR 파일을 받아 프로젝트에 추가해줍니다. 또한 프로젝트 컴파일, 테스트, 패키징(JAR/war 파일 생성)까지 일괄적으로 실행할 수 있어 일관된 개발 환경을 유지하고 협업을 쉽게 만들어주는 강력한 도구입니다. Maven은 특히 대규모 프로젝트나 팀 개발에서 널리 사용되며, 대부분의 현대 자바 개발 환경에서는 표준처럼 사용됩니다.

 

Gradle

Gradle은 자바를 포함한 다양한 언어의 프로젝트에서 빌드, 의존성 관리, 배포 등을 자동화해주는 현대적인 빌드 도구(Build Tool)입니다. 기존의 Maven보다 더 빠르고 유연하며, Groovy 또는 Kotlin DSL을 사용해 스크립트 형식으로 빌드 과정을 직접 제어할 수 있는 것이 특징입니다. build.gradle 파일에 필요한 라이브러리와 작업을 선언하면, Gradle이 자동으로 필요한 라이브러리를 다운로드하고 컴파일, 테스트, 패키징 등을 수행합니다. 특히 속도와 커스터마이징 유연성이 뛰어나서, Android 개발이나 복잡한 빌드 환경에서 널리 사용됩니다. Maven과 달리 코드처럼 작성할 수 있어 자동화와 확장이 쉬운 빌드 도구로 인식되고 있습니다.

 

 

3. Statement

Statement는 JDBC API에서 제공하는 인터페이스로, SQL 문장을 데이터베이스에 전달하고 실행 결과를 받아오는 데 사용됩니다. Statement는 사용자 입력값이 직접 SQL 문자열에 들어가기 때문에 보안에 취약하며,  가독성이 떨어지고 반복되는 코드는 유지보수가 어렵다는 단점이 있습니다.

executeQuery(String sql) SELECT 문 실행 – 결과는 ResultSet 객체로 반환
executeUpdate(String sql) INSERT, UPDATE, DELETE – 영향을 받은 행 수(int) 반환
execute(String sql) 모든 SQL 문 실행 가능 – 실행 결과에 따라 ResultSet 또는 boolean 반환

 

MySQL에서 테이블 생성

create table words (
	eng varchar(50) primary key,
    kor varchar(50) not null,
    lev int default 1,
    regdate datetime default now()
);

 

import java.sql.*;

public class JdbcEx {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/aiproject?serverTimezone=Asia/Seoul";
        String user = "root";
        String password = "1234";

        try {
            // 1. 드라이버 로드
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. DB 연결
            Connection conn = DriverManager.getConnection(url, user, password);
            System.out.println("MySQL 연결 성공!");

            // 3. 쿼리 실행
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM words");

            while (rs.next()) {
                String eng = rs.getString("eng");
                String kor = rs.getString("kor");
                int lev = rs.getInt("lev");
                System.out.println(eng + ": " + kor + "(레벨: " + lev + ")");
            }

            // 4. 자원 정리
            rs.close();
            stmt.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

 

4. PreparedStatement

PreparedStatement는 JDBC에서 SQL 문장을 미리 준비하고 실행할 수 있도록 해주는 객체로, Statement보다 보안과 성능 측면에서 훨씬 우수합니다.

SELECT * FROM users WHERE name = ?
  • ? 부분은 바인딩 파라미터
  • 실행 시 자바 코드에서 값을 넣음 (pstmt.setString(1, "김사과");)
setString(int index, String value) 문자열 설정
setInt(int index, int value) 정수 설정
setDate(int index, java.sql.Date) 날짜 설정
executeQuery() SELECT 실행
executeUpdate() INSERT/UPDATE/DELETE 실행
close() 자원 정리

 

import java.sql.*;

public class JdbcEx {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/nodejs?serverTimezone=Asia/Seoul";
        String user = "root";
        String password = "1234";

        try {
            // 1. 드라이버 로드
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. DB 연결
            Connection conn = DriverManager.getConnection(url, user, password);
            System.out.println("MySQL 연결 성공!");

            // 3. PreparedStatement 생성
            String sql = "SELECT * FROM words WHERE lev >= ?";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, 2);  // 예: 레벨 2 이상인 단어만 조회

            // 4. 쿼리 실행
            ResultSet rs = pstmt.executeQuery();

            while (rs.next()) {
                String eng = rs.getString("eng");
                String kor = rs.getString("kor");
                int lev = rs.getInt("lev");
                System.out.println(eng + ": " + kor + " (레벨: " + lev + ")");
            }

            // 5. 자원 정리
            rs.close();
            pstmt.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

import java.sql.*;

public class InsertEx {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/nodejs?serverTimezone=Asia/Seoul";
        String user = "root";
        String password = "1234";

        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            // 1. 드라이버 로드
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. DB 연결
            conn = DriverManager.getConnection(url, user, password);
            System.out.println("MySQL 연결 성공!");

            // 3. INSERT 쿼리 준비
            String sql = "INSERT INTO words(eng, kor, lev) VALUES(?, ?, ?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, "apple");     // 영단어
            pstmt.setString(2, "사과");       // 한글뜻
            pstmt.setInt   (3, 2);           // 레벨

            // 4. 쿼리 실행
            int count = pstmt.executeUpdate();
            System.out.println(count + "개 행이 삽입되었습니다.");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 5. 자원 정리
            try { if (pstmt != null) pstmt.close(); } catch (SQLException e) { e.printStackTrace(); }
            try { if (conn  != null) conn.close();  } catch (SQLException e) { e.printStackTrace(); }
        }
    }
}

 

import java.sql.*;

public class UpdateEx {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/nodejs?serverTimezone=Asia/Seoul";
        String user = "root";
        String password = "1234";

        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            // 1. 드라이버 로드
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. DB 연결
            conn = DriverManager.getConnection(url, user, password);
            System.out.println("MySQL 연결 성공!");

            // 3. UPDATE 쿼리 준비
            String sql = "UPDATE words SET kor = ?, lev = ? WHERE eng = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, "애플");     // 새로운 한글뜻
            pstmt.setInt   (2, 3);         // 새로운 레벨
            pstmt.setString(3, "apple");   // 조건: eng 컬럼

            // 4. 쿼리 실행
            int count = pstmt.executeUpdate();
            System.out.println(count + "개 행이 수정되었습니다.");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 5. 자원 정리
            try { if (pstmt != null) pstmt.close(); } catch (SQLException e) { e.printStackTrace(); }
            try { if (conn  != null) conn.close();  } catch (SQLException e) { e.printStackTrace(); }
        }
    }
}

 

import java.sql.*;

public class DeleteEx {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/nodejs?serverTimezone=Asia/Seoul";
        String user = "root";
        String password = "1234";

        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            // 1. 드라이버 로드
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. DB 연결
            conn = DriverManager.getConnection(url, user, password);
            System.out.println("MySQL 연결 성공!");

            // 3. DELETE 쿼리 준비
            String sql = "DELETE FROM words WHERE eng = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, "apple");   // 삭제할 영단어

            // 4. 쿼리 실행
            int count = pstmt.executeUpdate();
            System.out.println(count + "개 행이 삭제되었습니다.");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 5. 자원 정리
            try { if (pstmt != null) pstmt.close(); } catch (SQLException e) { e.printStackTrace(); }
            try { if (conn  != null) conn.close();  } catch (SQLException e) { e.printStackTrace(); }
        }
    }
}

 

 

5. try-with-resources

Java 7부터 도입된 자원 자동 해제 기능으로, try 구문 안에서 선언한 AutoCloseable(또는 Closeable) 타입의 자원을 블록이 끝날 때 자동으로 close() 해 줍니다. 수동으로 finally 블록을 작성할 필요 없이 깔끔하고 안전하게 자원을 관리할 수 있습니다.

try (리소스 선언 및 초기화) {
    // 자원을 사용하는 코드
} catch (예외타입 e) {
    // 예외 처리
}
  • try 괄호 안에 여러 개의 자원을 세미콜론(;)으로 구분해 나열할 수 있습니다.
  • 블록을 벗어날 때, 선언된 자원들의 close()가 역순으로 자동 호출됩니다.
  • 자원이 null이 아닌 경우에만 close()를 호출합니다.

 

import java.sql.*;

public class SelectWithResources {
    public static void main(String[] args) {
        String url      = "jdbc:mysql://localhost:3306/nodejs?serverTimezone=Asia/Seoul";
        String user     = "root";
        String password = "1234";

        String sql = "SELECT * FROM words WHERE lev >= ?";

        // try(...) 안에서 선언된 자원은 자동으로 close()
        try (
            Connection        conn  = DriverManager.getConnection(url, user, password);
            PreparedStatement pstmt = conn.prepareStatement(sql)
        ) {
            Class.forName("com.mysql.cj.jdbc.Driver");
            pstmt.setInt(1, 2);

            // ResultSet 또한 try-with-resources에 포함 가능
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    String eng = rs.getString("eng");
                    String kor = rs.getString("kor");
                    int lev    = rs.getInt("lev");
                    System.out.println(eng + ": " + kor + " (레벨: " + lev + ")");
                }
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
            // 필요시 e.getSuppressed()로 억제된 예외 확인 가능
        }
    }
}
  • Connection, PreparedStatement, ResultSet 모두 AutoCloseable을 구현하므로 try(...)에 나열할 수 있습니다.
  • 리소스 해제 코드가 전혀 없기 때문에 가독성이 월등히 좋아집니다.
728x90
반응형

'백엔드 > Java' 카테고리의 다른 글

소켓  (1) 2025.05.28
스레드  (1) 2025.05.28
스트림  (0) 2025.05.25
람다식  (1) 2025.05.25
DTO와 VO  (0) 2025.05.23

관련글 더보기