PreparedStatement 사용의 장점
PreparedStatement는 SQL 쿼리를 미리 컴파일하고, 동일한 쿼리를 반복해서 실행할 때 효율적으로 사용할 수 있는 인터페이스이다.
이는 성능과 보안 측면에서 많은 장점을 제공한다.
- 성능 향상:
- 쿼리 컴파일: SQL 쿼리를 미리 컴파일하여, 쿼리를 여러 번 실행할 때 컴파일 시간을 절약할 수 있다.
- 쿼리 계획 재사용: 동일한 쿼리를 반복적으로 실행할 때, 쿼리 계획을 재사용하여 실행 시간을 단축할 수 있다.
- 보안 향상:
- SQL 인젝션 방지: 쿼리와 데이터가 분리되어 있어 SQL 인젝션 공격을 방지할 수 있다.
예시 코드
String sql = "INSERT INTO users (name, email) VALUES (?, ?)"; try (Connection connection = DBConnectionManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement(sql)) { preparedStatement.setString(1, "고길동"); preparedStatement.setString(2, "a@example.com"); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }
SQLInjectionExample
package ch01; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.Scanner; public class SQLInjectionExample { public static void main(String[] args) { try (Connection conn = DBConnectionManager.getConnection()){ Scanner scanner = new Scanner(System.in); System.out.print("사용자 입름을 입력하세요 : "); String username = scanner.nextLine(); // 취약한 SQL 쿼리 작성해보기(SQL 인젝션이 가능) String query = " SELECT * FROM user WHERE name = " + username + " "; try (Statement stmt = conn.createStatement()){ ResultSet resultSet = stmt.executeQuery(query); while(resultSet.next()) { System.out.println("사용자 ID : " + resultSet.getInt("id")); System.out.println("사용자 이름 : " + resultSet.getString("name")); System.out.println("사용자 이메일 : " + resultSet.getString("email")); } } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } } // end of main }
SQL 인젝션 확인

SQL 인젝션 예방 코드
package ch01; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.Scanner; public class SQLInjectionExample { public static void main(String[] args) { try (Connection conn = DBConnectionManager.getConnection()){ Scanner scanner = new Scanner(System.in); System.out.print("사용자 입름을 입력하세요 : "); String username = scanner.nextLine(); // 취약한 SQL 쿼리 작성해보기(SQL 인젝션이 가능) String query = " SELECT * FROM user WHERE name = " + username + " "; String query2 = " SELECT * FROM user WHERE name = ? "; try (Statement stmt = conn.createStatement(); // Statement 사용과 인젝션 공격 확인 // ResultSet resultSet = stmt.executeQuery(query); // SQL 인젝션 방지를 위한 PreparedStatement의 사용 PreparedStatement pstmt = conn.prepareStatement(query2)){ pstmt.setString(1, username); ResultSet resultSet = pstmt.executeQuery(); while(resultSet.next()) { System.out.println("사용자 ID : " + resultSet.getInt("id")); System.out.println("사용자 이름 : " + resultSet.getString("name")); System.out.println("사용자 이메일 : " + resultSet.getString("email")); } } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } } // end of main }
연결 풀 (Connection Pool)과 데이터 소스 (Data Source)
데이터베이스 연결의 생애주기
1. 애플리케이션 로직에서 데이터베이스 연결 요청
2. 데이터베이스 드라이버 초기화 및 연결 설정
3. TCP/IP 연결 설정
4. 사용자 인증 및 세션 생성
5. 커넥션 생성 완료
6. 데이터베이스 연결 사용 및 종료
일반적으로 데이터베이스 연결은 비용이 큰 작업이다. 데이터베이스 서버와의 연결을 맺고 끊는 과정은 시간이 많이 소요되며, 데이터베이스 서버의 리소스도 소비된다. 그렇기 때문에 매번 데이터베이스 연결을 필요로 하는 요청이 발생할 때마다 새로운 연결을 생성하는 것은 효율적이지 않다.

성능 최적화의 여러 방법중 하나로 아래와 같은 기술들을 적용할 수 있다.
커넥션 풀(Connection Pool)과 데이터 소스 (Data Source)는 데이터베이스 연결 관리를 효율적으로 하기 위해 사용하는 개념이다.
연결 풀 (Connection Pool)
- 정의: 데이터베이스 연결 풀은 일정 수의 데이터베이스 연결을 미리 생성해두고, 애플리케이션에서 필요할 때마다 이 연결을 재사용하는 기술이다.
- 목적: 데이터베이스 연결을 효율적으로 관리하여 성능을 향상시키고, 데이터베이스 서버의 부하를 줄인다.
- 작동 원리: 애플리케이션이 데이터베이스 연결을 요청하면, 연결 풀에서 사용 가능한 연결을 반환한다. 사용이 끝난 연결은 폐기되지 않고 다시 연결 풀에 반환되어 재사용된다.

💡 핵심 정리
- DB 드라이버가 아닌 커넥션 풀에서 커넥션을 가져온다.
- 커넥션 사용 후 재사용할 수 있도록 커넥션 풀에 살아 있는 상태로 반환 한다
커넥션 생성에 필요한 6가지 단계들이 모두 처리된 상태이므로,
언제든지 즉시 SQL 문을 데이터베이스로 전달할 수 있어서 사용자 응답 속도가 빨라진다.
서버당 최대 커넥션 개수를 제한할 수 있어
DB에 무한정 연결이 생성되는 것을 막아 데이터베이스를 보호하는 효과도 존재한다.


연결 풀과 데이터 소스의 관계
- 통합 관리: 데이터 소스는 연결 풀을 사용하여 데이터베이스 연결을 관리한다. 데이터 소스를 통해 데이터베이스 연결을 요청하면, 내부적으로 연결 풀에서 관리하는 연결이 반환된다.
- 연결 추상화: 데이터 소스는 연결 풀을 포함한 다양한 연결 관리 방식을 추상화하여 제공한다. 이를 통해 애플리케이션 개발자는 데이터 소스를 통해 쉽게 데이터베이스 연결을 사용할 수 있다.
'Java' 카테고리의 다른 글
| 웹 서버와 웹 애플리케이션 서버(WAS) (1) | 2024.07.02 |
|---|---|
| HTTP 사전 기반 기초 지식 (1) | 2024.07.02 |
| JDBC를 활용한 CRUD 와 SOLID 원칙 (1) | 2024.06.27 |
| JDBC 트랜잭션 관리와 배치 처리 (0) | 2024.06.27 |
| JDBC 기본 사용법 (0) | 2024.06.14 |