BackEnd๐Ÿƒ/Java

[JAVA / JDBC] JDBC๊ฐ€ ๋ฌด์—‡์ผ๊นŒ?

์–ด์ œ์‹œ์ž‘ 2025. 1. 20. 15:37

JDBC(Java Database Connectivity)๋ž€?

JDBC(Java Database Connectivity) API๋Š” Java ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์™€ ํญ๋„“์€ ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ์Šคํ”„๋ ˆ๋“œ์‹œํŠธ๋‚˜ ํ”Œ๋žซ ํŒŒ์ผ์„ ๋น„๋กฏํ•œ ํ…Œ์ด๋ธ” ํ˜•์‹ ๋ฐ์ดํ„ฐ ์†Œ์Šค)๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋…๋ฆฝ์ (database-independent)์œผ๋กœ ์—ฐ๊ฒฐํ•ด ์ฃผ๋Š” ์‚ฐ์—… ํ‘œ์ค€์ž…๋‹ˆ๋‹ค. JDBC API๋Š” SQL ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์•ก์„ธ์Šค๋ฅผ ์œ„ํ•œ ํ˜ธ์ถœ ๋ ˆ๋ฒจ API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. (์ถœ์ฒ˜ : Oracle ๊ณต์‹๋ฌธ์„œ)

→ ์ฆ‰, JDBC(Java Database Connectivity)๋Š” Java ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ์ž๋ฐ” ํ‘œ์ค€ API์ž…๋‹ˆ๋‹ค. JDBC๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Java ํ”„๋กœ๊ทธ๋žจ์—์„œ SQL ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Java ์ฝ”๋“œ์—์„œ DB์„œ๋ฒ„์— ์ ‘์†ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • SQL๋ฌธ์„ ๊ตฌ์„ฑํ•˜๊ณ  DB์„œ๋ฒ„์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋•Œ, SQL๋ฌธ์€ Java ์ฝ”๋“œ ์•ˆ์— ํฌํ•จ๋œ๋‹ค.
  • DB์˜ ์ •๋ณด๋‚˜ DB์„œ๋ฒ„์—์„œ ์ฒ˜๋ฆฌํ•œ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“Œ JDBC๊ฐ€ ์™œ ์ƒ๊ฒจ๋‚ฌ๋‚˜?!

1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ณ„๋กœ ๋‹ค๋ฅธ API๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์Œ

  • ์˜ˆ๋ฅผ ๋“ค์–ด, MySQL, Oracle, PostgreSQL ๋“ฑ ๊ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋งˆ๋‹ค ์„œ๋กœ ๋‹ค๋ฅธ ์—ฐ๊ฒฐ ๋ฐฉ์‹์„ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐœ๋ฐœ์ž๋Š” ๊ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋งˆ๋‹ค ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ๋งˆ๋‹ค ์ฝ”๋“œ ์ „์ฒด๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ–ˆ์Œ → ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›€.

๐Ÿ“Œ ์˜ˆ์‹œ

  • Oracle ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” Oracle OCI API
  • MySQL์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” MySQL API
  • PostgreSQL์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” PostgreSQL ์ „์šฉ API

→ ์™€ ์–ธ์ œ ์ „๋ถ€ ๋‹ค ์ƒˆ๋กœ ์งœ๊ณ  ์žˆ์–ด ใ… ใ…  → ๊ณตํ†ต๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์„๊นŒ?!

2. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋ฐ ์ž์› ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์› ์Œ

  • ๊ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋งž๋Š” ์—ฐ๊ฒฐ(Connection) ๋ฐฉ์‹์ด ๋‹ค ๋‹ฌ๋ž์Œ.
  • ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•ด์•ผ ํ–ˆ๊ณ , ์ž˜๋ชปํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜(Connection Leak) ๊ฐ€ ๋ฐœ์ƒํ•จ.
  • ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•ด์•ผ ํ–ˆ์Œ.

3. SQL Injection(๋ณด์•ˆ ๋ฌธ์ œ)์— ๋Œ€ํ•œ ๊ณ ๋ ค ๋ถ€์กฑ

  • JDBC๊ฐ€ ์—†๋˜ ์‹œ์ ˆ์—๋Š” ๋ฌธ์ž์—ด์„ ์ง์ ‘ ๊ฒฐํ•ฉํ•˜์—ฌ SQL์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์ด ๋งŽ์•˜์Œ.
  • ์ด๋กœ ์ธํ•ด SQL Injection ๊ณต๊ฒฉ์— ์ทจ์•ฝํ–ˆ์Œ.

๐Ÿ“Œ ์˜ˆ์‹œ

String query = "SELECT * FROM users WHERE username = '" + userInput + "'";
stmt.executeQuery(query);
  • ์‚ฌ์šฉ์ž๊ฐ€ admin' OR '1'='1 ๊ฐ™์€ ๋ฌธ์ž์—ด์„ ์ž…๋ ฅํ•˜๋ฉด ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ๋…ธ์ถœ๋  ์œ„ํ—˜์ด ์žˆ์—ˆ์Œ.
  • JDBC์˜ PreparedStatement๊ฐ€ ๋“ฑ์žฅํ•˜๋ฉด์„œ SQL Injection์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋จ.

→ ๋”ฐ๋ผ์„œ ํ•ด๋‹น ์–ด๋ ค์›€๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ƒ๊ฒจ๋‚ฌ๋‹ค!


๐Ÿ“Œ JDBC ๊ฐœ๋… ๋ฐ ๋™์ž‘ ๊ณผ์ •

JDBC๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์ด์—์„œ ๋ธŒ๋ฆฌ์ง€(Bridge) ์—ญํ• ์„ ํ•˜๋ฉฐ, JDBC ๋“œ๋ผ์ด๋ฒ„๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค.

JDBC ๋™์ž‘ ๊ณผ์ •

  1. JDBC ๋“œ๋ผ์ด๋ฒ„ ๋กœ๋“œ
    • Class.forName("com.mysql.cj.jdbc.Driver");
    • ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋งž๋Š” JDBC ๋“œ๋ผ์ด๋ฒ„๋ฅผ ๋กœ๋“œํ•ด์•ผ ํ•จ
  2. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ (Connection ๊ฐ์ฒด ์ƒ์„ฑ)
    • Connection conn = DriverManager.getConnection(url, user, password);
    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐํ•˜๋Š” ๊ณผ์ •
  3. SQL ์‹คํ–‰ (Statement, PreparedStatement ์‚ฌ์šฉ)
    • Statement stmt = conn.createStatement();
    • PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE id =?");
    • SQL ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒ, ์‚ฝ์ž…, ์ˆ˜์ •, ์‚ญ์ œ ๊ฐ€๋Šฅ
  4. ๊ฒฐ๊ณผ(ResultSet) ์ฒ˜๋ฆฌ
    • ResultSet rs = stmt.executeQuery("SELECT * FROM users");
    • ๊ฒฐ๊ณผ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์Œ
  5. ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ (Connection ๋‹ซ๊ธฐ)
    • conn.close();
    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ํ•ด์ œํ•˜์—ฌ ๋ฆฌ์†Œ์Šค ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€
// from Chat-GPT
import java.sql.*;

public class JdbcExample {
    public static void main(String[] args) {
        // 1๏ธโƒฃ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์ •๋ณด ์„ค์ •
        String url = "jdbc:mysql://{Your-URL}"; // MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค URL
        String user = "{USERNAME}";   // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์šฉ์ž๋ช…
        String password = "{PASSWORD}"; // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋น„๋ฐ€๋ฒˆํ˜ธ

        // 2๏ธโƒฃ try-with-resources๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ž๋™ ๋ฆฌ์†Œ์Šค ํ•ด์ œ
        try (
            // 3๏ธโƒฃ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ (JDBC 4.0 ์ด์ƒ์—์„œ๋Š” DriverManager๊ฐ€ ์ž๋™์œผ๋กœ ๋“œ๋ผ์ด๋ฒ„ ๋กœ๋“œ)
            Connection conn = DriverManager.getConnection(url, user, password);
            
            // 4๏ธโƒฃ SQL ์‹คํ–‰ (Statement ์‚ฌ์šฉ)
            Statement stmt = conn.createStatement();
            
            // 5๏ธโƒฃ SQL ์‹คํ–‰ (PreparedStatement ์‚ฌ์šฉ, SQL Injection ๋ฐฉ์ง€)
            PreparedStatement pstmt = conn.prepareStatement("SELECT id, name FROM users WHERE id = ?");
        ) {
            System.out.println("โœ… ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์„ฑ๊ณต!");

            // 6๏ธโƒฃ ๋ฐ์ดํ„ฐ ์กฐํšŒ (Statement ํ™œ์šฉ)
            String sql = "SELECT id, name FROM users";
            try (ResultSet rs = stmt.executeQuery(sql)) {
                System.out.println("โœ… ๋ฐ์ดํ„ฐ ์กฐํšŒ ๊ฒฐ๊ณผ:");
                while (rs.next()) { // ๊ฒฐ๊ณผ ์ˆœํšŒ
                    int id = rs.getInt("id");
                    String name = rs.getString("name");
                    System.out.println("ID: " + id + ", Name: " + name);
                }
            }

            // 7๏ธโƒฃ PreparedStatement๋ฅผ ์‚ฌ์šฉํ•œ ์•ˆ์ „ํ•œ SQL ์‹คํ–‰ (SQL Injection ๋ฐฉ์ง€)
            pstmt.setInt(1, 1); // ID ๊ฐ’ ์„ค์ • (์˜ˆ: ID๊ฐ€ 1์ธ ์‚ฌ์šฉ์ž ์กฐํšŒ)
            try (ResultSet rs = pstmt.executeQuery()) {
                System.out.println("โœ… PreparedStatement ์‚ฌ์šฉํ•œ ๋ฐ์ดํ„ฐ ์กฐํšŒ:");
                while (rs.next()) {
                    int id = rs.getInt("id");
                    String name = rs.getString("name");
                    System.out.println("ID: " + id + ", Name: " + name);
                }
            }

            // 8๏ธโƒฃ PreparedStatement๋ฅผ ์‚ฌ์šฉํ•œ ์•ˆ์ „ํ•œ ๋ฐ์ดํ„ฐ ์‚ฝ์ž…
            String insertSQL = "INSERT INTO users (id, name) VALUES (?, ?)";
            try (PreparedStatement insertStmt = conn.prepareStatement(insertSQL)) {
                insertStmt.setInt(1, 3); // ID ๊ฐ’ ์„ค์ •
                insertStmt.setString(2, "New User"); // Name ๊ฐ’ ์„ค์ •
                int rowsInserted = insertStmt.executeUpdate(); // SQL ์‹คํ–‰
                if (rowsInserted > 0) {
                    System.out.println("โœ… ๋ฐ์ดํ„ฐ ์‚ฝ์ž… ์„ฑ๊ณต!");
                }
            }

        } catch (SQLException e) {
            System.out.println("โŒ SQL ์‹คํ–‰ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ!");
            e.printStackTrace();
        }
    }
}