[JAVA / JDBC] JDBC๊ฐ ๋ฌด์์ผ๊น?
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 ๋์ ๊ณผ์
- JDBC ๋๋ผ์ด๋ฒ ๋ก๋
- Class.forName("com.mysql.cj.jdbc.Driver");
- ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ง๋ JDBC ๋๋ผ์ด๋ฒ๋ฅผ ๋ก๋ํด์ผ ํจ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ (Connection ๊ฐ์ฒด ์์ฑ)
- Connection conn = DriverManager.getConnection(url, user, password);
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ๋ ๊ณผ์
- SQL ์คํ (Statement, PreparedStatement ์ฌ์ฉ)
- Statement stmt = conn.createStatement();
- PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE id =?");
- SQL ์ฟผ๋ฆฌ๋ฅผ ์คํํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์กฐํ, ์ฝ์ , ์์ , ์ญ์ ๊ฐ๋ฅ
- ๊ฒฐ๊ณผ(ResultSet) ์ฒ๋ฆฌ
- ResultSet rs = stmt.executeQuery("SELECT * FROM users");
- ๊ฒฐ๊ณผ๋ฅผ ์ํํ๋ฉฐ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ์ ์์
- ๋ฆฌ์์ค ์ ๋ฆฌ (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();
}
}
}