본문 바로가기
CS/DataBase

[DB] Prepared Statement란?

by BK0625 2025. 6. 10.
반응형

Prepared Statement는 데이터베이스 쿼리를 실행 할 때 쿼리를 미리 준비하고 실행할 때 필요한 값만 바인딩하여 사용하는 방식이다. 일반적으로 SQL 쿼리를 실행할 때와 달리, Prepared Statement는 SQL 구문과 데이터 값을 분리하여 처리한다. 이러한 방식은 SQL Injection 공격을 예방하고, 반복적인 쿼리 실행 성능을 향상시키는 등 여러 가지 장점을 제공한다.

 

 

일반 Statement의 동작 방식

일반적으로 SQL을 실행할 때 다음과 같은 단계를 거친다.

  1. SQL 문자열 생성
--예시
SELECT * FROM users WHERE name = 'Alice';

   

    2. 파싱 (Parsing) : SQL 문법을 검사하고, 쿼리 구조를 분석한다.

    3. 컴파일(Complie) : 실행 계획을 수립한다. (어떤 인덱스를 사용할지 등)

    4. 실행(Execute) : 쿼리를 실행하고 결과를 반환한다.

 

이 과정은 쿼리마다 반복된다,

 

prepared statement의 동작 과정

 

prepared statement는 위 과정을 두 단계로 나눈다

  1. 쿼리 준비(Preparation) : 데이터베이스에 실행할 쿼리 템플릿을 미리 전송하고, SQL 구문을 컴파일하여 실행 계획을 저장해둔다. 이 단계에서 SQL 구문과 데이터 값이 분리되며, 쿼리 자체는 미리 컴파일 되어 효율적으로 처리된다
  2. 바인딩(Binding)과 실행(Execution) : 준비된 쿼리에 데이터를 바인딩하고 실행한다. 이 때 바인딩 되는 데이터 값은 쿼리 구문에 직접 포함되지 않으므로, SQL Injection 공격을 방지할 수 있다.

 

이러한 과정을 통해 Prepared Statement는 반복적으로 실행되는 쿼리에 대해 성능을 최적화 하고 보안을 강화할 수 있다.

 

장점

  1. 성능 향상 : Prepared Statement는 한 번 컴파일 된 쿼리를 반복적으로 실행할 수 있기 때문에, 동일한 쿼리를 여러 번 실행하는 경우 성능이 크게 향상됩니다. 예를 들어, 대규모 데이터를 처리하는 배치 작업에서 동일한 쿼리를 여러 번 사용해야 할 때 효과적이다.
    1. 서버 부하 감소 : 동일한 쿼리를 파싱/컴파일하지 않고 재사용하기 때문에 DB 서버의 CPU 부하가 줄어든다. 이는 트래픽이 많은 시스템에서 효율성 향상에 도움이 된다.
    2. 네트워크 트래픽 감소 : 쿼리 전체를 매번 보내지 않고 파라미터만 전송하므로 쿼리 문자열 전송 비용이 줄어든다. 특히 JDBC,ODBC, PostgreSQL, MySQL 등의 클라이언트-서버 통신에서 이 이점이 크다.
  2. 보안 강화 : Prepared Statement는 SQL 구문과 데이터를 분리하여 전송하므로, SQL Injection과 같은 공격을 방어하는데 매우 효과적이다. SQL Injection은 공격자가 SQL 구문 내에 악의적인 코드를 주입하여 데이터베이스를 손상시키거나 정보를 유출할 수 있는 공격 방식이다. Prepared Statement는 바인딩하는 값이 SQL 구문에 직접 포함되지 않기 때문에 이러한 공격을 차단할 수 있다.
  3. 가독성 및 유지보수성 향상 : Prepared Statement를 사용하면, 코드가 보다 간결하고 가독성이 높아진다. 또한, 코드 수정 시 쿼리 구문에 포함된 데이터 값만 조정하면 되므로 유지보수가 용이하다.
  4. 타입 안정성 보장 : 대부분의 DB 드라이버는 prepared statement를 통해 타입 체킹을 자동 수행한다. 이는 버그를 조기에 방지할 수 있게 한다.
  5. 바이너리 프로토콜 활용(DBMS에 따라) : 일부 DBMS는 prepared statement를 사용할 때 바이너리 프로토콜로 파라미터를 전송한다. 문자열보다 효율적이며, 성능 향상에 도움이 된다. (PostgreSQL의 binary format, MySQL의 binary protocol)
  6. 접근 제어 (일부 시스템) : 일부 고급 DBMS는 Prepared statement를 정의한 사용자와 실행하는 사용자의 권한을 분리하거나 관리할 수 있게 한다. 보안 정책이나 감사 로그 측면에서 유용할 수 잇다.

 

Prepared Statement에서 동적 값 바인딩 방법

 

prepared statement에서는 placeholder를 사용하여 값이 들어갈 위치를 미리 지정하고, 실행 시점에 필요한 값을 바인딩한다. 예를 들어, ? 기호 또는 명명된 변수 (:name)를 사용하여 값을 바인딩 할 수 있다.

 

 

보안에 좋은 이유

 

Prepared Statement는 SQL 구문과 값을 분리하여 처리하므로, SQL Injection과 같은 보안 취약점을 효과적으로 막아준다. 예를 들어, 일반적인 SQL 쿼리에서 사용자가 제공하는 값에 SQL 코드를 삽입하면 의도치 않은 쿼리가 실행될 수 있다. 하지만 Prepared Statement에서는 쿼리와 값이 완전히 독립적으로 처리되기 때문에, 값이 악의적인 SQL 구문을 포함하더라도 단순한 값으로 취급되며 코드로 실행되지 않는다.

 

주의할 점

  1. 일회성 쿼리에는 부적할 수도? : Prepared Statement는 반복 실행 시 성능이 향상되는 구조이므로, 단 한 번만 실행되는 쿼리에서는 성능상의 이점이 크지 않다. 오히려 준비 단계에서 오버헤드가 발생할 수 있으므로 단발성 쿼리에서는 일반적인 쿼리 실행 방식이 더 나을 수 있다.
  2. 변수 바인딩 오류 : 바인딩 시 변수의 타입이 잘못 지정되면 오류가 발생할 수 있으므로, 바인딩하는 값의 타입이 쿼리에서 기대하는 타입과 일치하는지 확인해야 한다.
  3. 일부 데이터베이스 제한 : 모든 DBMS가 Prepared Statement를 동일한 방식으로 지원하지 않으므로, 사용하는 DBMS의 지원 여부와 기능 차이를 이해하고 사용하여야 한다. 일부 DB는 prepared statement의 실행 계획을 완전히 재사용하지 않거나, 캐시가 제한될 수 있다.
  4. 동적 쿼리 (컬럼명/조건이 바뀌는 쿼리)에는 부적절할 수 있음

 

 

공부하면서 정리한 내용입니다. 모든 지적 감사히 받겠습니다:)

반응형