[Java] JDBC의 Statement와 PreparedStatement

2026. 1. 22. 11:30·Back end/Java
반응형

데이터베이스와 통신하는 Java 애플리케이션을 개발할 때, JDBC를 통해 SQL을 실행하게 됩니다. 이때 Statement와 PreparedStatement 중 어떤 것을 사용하느냐에 따라 애플리케이션의 성능과 보안이 크게 달라집니다.


Statement: 유연하지만 위험한 방식

Statement는 가장 기본적인 SQL 실행 방식입니다. 쿼리를 작성할 때 문자열 연결(String concatenation)을 통해 동적으로 SQL을 구성합니다.

String userId = "user123";
String sql = "SELECT * FROM users WHERE id = '" + userId + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);

간단해 보이지만, 이 방식은 사용자 입력이 직접 쿼리 문자열에 포함되기 때문에 SQL 인젝션 공격에 매우 취약합니다.

만약 userId 변수에 ' OR '1'='1 같은 악의적인 입력이 들어온다면, 쿼리의 의도가 완전히 변조될 수 있습니다.

PreparedStatement: 안전하고 효율적인 방식

PreparedStatement는 이러한 문제를 해결하기 위해 설계된 방식입니다. 쿼리의 구조를 먼저 고정시키고, 나중에 실제 값들을 바인딩합니다.

String userId = "user123";
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, userId);
ResultSet rs = pstmt.executeQuery();

물음표(?)는 플레이스홀더(placeholder) 역할을 하며, setString() 같은 메서드로 실제 값을 나중에 바인딩합니다.


두 가지 핵심 차이점

1. SQL 인젝션 방지

PreparedStatement는 쿼리 구조가 이미 확정된 상태이기 때문에, 바인딩되는 데이터는 오직 파라미터로만 취급됩니다. 아무리 악의적인 입력이 들어와도 쿼리의 논리 구조를 변경할 수 없습니다. 반면 Statement는 문자열 연결 방식이므로 사용자 입력이 쿼리 구조 자체를 변경할 여지가 있습니다.

2. 데이터베이스 캐싱을 통한 성능 향상

데이터베이스는 SQL을 실행하기 전에 파싱과 실행 계획 수립이라는 비용이 큰 과정을 거칩니다.

이러한 작업의 결과는 캐시(cache)에 저장되어 재활용됩니다.

 

Statement를 사용하면 파라미터값이 달라질 때마다 전체 쿼리 문자열이 다르게 구성되므로, 매번 파싱과 계획 수립을 새로 진행해야 합니다.

SELECT name FROM tbl WHERE id = 1  -- 서로 다른 SQL로 인식될 가능성
SELECT name FROM tbl WHERE id = 2

반면 PreparedStatement는 SQL 구조가 고정되어 있기 때문에,
데이터베이스나 JDBC 드라이버, 커넥션 풀 설정에 따라
이러한 파싱 결과나 실행 계획을 재활용할 수 있는 여지가 생깁니다.

SELECT name FROM tbl WHERE id = ?  -- 파싱 후 캐싱
SELECT name FROM tbl WHERE id = ?  -- 동일한 SQL 구조로 재사용 가능

특히 같은 쿼리를 여러 번 실행하는 경우, PreparedStatement는 훨씬 빠른 응답 속도를 제공합니다.


연결 풀(Connection Pool)과의 관계

Connection Pool 환경에서는 커넥션이 반복 재사용되므로, PreparedStatement 캐싱을 지원하는 커넥션 풀(HikariCP 등)을 사용할 경우 동일한 SQL에 대한 PreparedStatement를 재사용할 수 있어 성능 이점을 더욱 극대화할 수 있습니다.


결론

PreparedStatement가 표준인 이유

현대의 자바 개발에서는 거의 항상 PreparedStatement를 사용해야 합니다. 보안과 성능 양쪽 측면에서 Statement보다 우수하기 때문입니다. 특히 반복적인 쿼리 실행이 이루어지는 환경에서는 그 차이가 더욱 두드러집니다.

Statement는 단순한 학습 목적이나 특수한 상황을 제외하고는 실제 프로덕션 코드에서 사용하지 않는 것이 좋습니다.

스프링 환경에서의 활용

참고로 스프링 환경에서는 JdbcTemplate, MyBatis, JPA 같은 추상화 계층을 사용하기 때문에, 개발자가 Statement나 PreparedStatement를 직접 다룰 일은 거의 없습니다.

그러나 이들 내부 구현은 대부분 PreparedStatement를 기반으로 동작합니다. 따라서 두 방식의 차이를 이해하는 것은 성능 튜닝이나 문제 분석에 큰 도움이 됩니다.

반응형

'Back end > Java' 카테고리의 다른 글

AtomicInteger는 어떻게 동시성을 보장할까? - CAS 알고리즘 깊이 파헤치기  (0) 2026.01.14
[Java] static import 활용법  (0) 2025.07.07
[Java] 자바 데이터 타입 (기본형, 참조형)  (0) 2025.05.27
[Java] 상수(Constant)  (0) 2025.05.26
[Java] 변수(variable)  (0) 2025.05.26
'Back end/Java' 카테고리의 다른 글
  • AtomicInteger는 어떻게 동시성을 보장할까? - CAS 알고리즘 깊이 파헤치기
  • [Java] static import 활용법
  • [Java] 자바 데이터 타입 (기본형, 참조형)
  • [Java] 상수(Constant)
Kim-SooHyeon
Kim-SooHyeon
개발일기 및 알고리즘, 블로그 운영에 대한 글을 포스팅합니다. :) 목표: 뿌리 깊은 개발자 되기
    반응형
  • Kim-SooHyeon
    soo_vely의 개발로그
    Kim-SooHyeon
  • 전체
    오늘
    어제
    • 분류 전체보기 (258)
      • 알고리즘 (108)
        • 자료구조 (3)
        • Java (104)
        • Python (1)
      • Back end (73)
        • Spring Project (28)
        • Java (23)
        • API (1)
        • Python (0)
        • Django (3)
        • Linux (1)
        • 서버 (2)
        • 에러로그 (11)
        • 부스트 코스 (1)
      • Front end (9)
        • HTML, CSS (4)
        • JavaScript (4)
        • JQuery (0)
      • 기타 프로그래밍 (4)
        • Android Studio (1)
        • Arduino (2)
        • Azure Fundamental(AZ-900) (1)
      • 개발도구 (24)
        • IntelliJ (2)
        • Git (12)
        • SVN (0)
        • Eclipse (2)
        • 기타 Tool (8)
      • Database (17)
        • Oracle (11)
        • MySQL (0)
        • H2 Database (3)
        • ORM & JPA (1)
      • 자격증 (10)
        • 컴활 1급 (7)
        • 컴활 2급 (2)
        • SQLD (1)
      • 기타 (13)
        • 블로그 운영 (6)
        • 문서 (1)
        • 기타 (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    백준
    for문
    java
    solved.ac
    spring
    알고리즘
    단계별풀기
    Git
    1차원 배열
    백준 자바
    오라클
    Oracle
    문자열
    구현
    BOJ
    github
    배열
    jpa
    springboot
    백준알고리즘
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Kim-SooHyeon
[Java] JDBC의 Statement와 PreparedStatement
상단으로

티스토리툴바