4,563,181 th visitor since 2017.2.1 ( Today : 75 )
Programming
No. 410
Name. swindler
Subject. PreparedStatement를 사용해야 하는 이유
Main Cate. Java
Sub Cate.
Date. 2007-12-12 13:53
Hit. 7184 (211.36.27.8)
File.
Statement vs PreparedStatement



I. PreparedStatement를 반드시 사용해야 하는 경우



1. 사용자 입력값으로 쿼리를 생성하는 경우

사용자에의해 입력되는 값을 가지고 SQL 작업을 할 경우 statement를 사용한다면 다음과 같이 될 것이다.

String content = request.getParameter("content");
stmt= conn.createStatement();
stmt.executeUpdate("INSERT INTO TEST_TABLE (CONTENT) VALUES('"+content+"');

사용자가 제대로 입력 하였다면 상관 없지만 content값에 "AA'AA"를 입력하였다면?
stmt.executeUpdate("INSERT INTO TEST_TABLE (CONTENT) VALUES('"+content+"'); 에서

에러가 발생할 것이다.

즉 SQL문은 다음과 같이 되는 것이다. INSERT INTO TEST_TABLE (CONTENT) VALUES('AA'AA');
요렇게 에러가 나면 그나마 다행..

만약 이쿼리가 대용량 쿼리 문장이었다면..
SELECT * FROM TEST_TABLE WHERE CONTENT = :content
그리고 사용자가 고의적으로 content값을 "' AND content like '%1%" 같이 입력하였다면 큰일이다.

즉 TEST_TABLE을 풀스캔 하여 엄청난 로드가 걸릴 수 있다는 것이다.
이와같이 사용자가 컬럼명을 유추하여 얼마든지 쿼리를 만들 수 있으며 비정상적

대용량 쿼리로 인해 DB서버에 큰 지장을 줄 수도 있다는 말이다.



물론 사용자 입력값을 체크하여 적당한 값으로 치환해주는 작업을 해도 무방하지만 귀찮은 일이다.

이를 다음과 같이 수정한다면 위와같은 에러나 장애를 원천적으로 봉쇄할 수 있다
pstmt = conn.preapreStatement("SELECT * FROM TEST_TABLE WHERE CONTENT = ?");
pstmt.setString(1, content);
pstmt.executeUpdate();
이는 content값이 "'"가 들어왔다 하더라도 알아서 파싱 해주기 때문이다.

고로 사용자 입력 값으로 쿼리를 바인딩 할 경우에는 필히 pstmt를 사용하도록 하자!



2. 쿼리 반복수행 작업일 경우


일반적으로 반복 수행 작업을 할 경우 아래와 같이 코딩 하게 된다.

1) Statement 사용
for (int i = 0; i < 100000; i++) {
stmt.executeUpdate("INSERT INTO TEST_TABLE VALUES('"+content+"');
}

2) PreparedStatement 사용
pstmt = conn.preapreStatement("INSERT INTO TEST_TABLE VALUES(?)"); <--- ⓐ
for (int i = 0; i < 10000; i++) {
pstmt.setString(1, content+i);
pstmt.executeUpdate();
}


-. DB의 종류에 따라 상황이 달라진다.

일반적으로 위와같은 코딩을 할 경우 2)경우가 1)보다 더 낳은 성능을 보인다고 알려져 있다.
즉 자바의 PreparedStatement의 사용은 오라클 DB에서 bind변수를 사용하도록 함으로 해서
DB서버에 미리 준비된 SQL을 사용하게 되고 파싱과정을 생략하기 때문에 결국
DB리소스를 효율적으로 사용하도록 하는 방법이 된다.
하지만 이것이 DB서버에 따라 다르다. MySql같은 경우는 1)과2)의 성능차이가 거의 나지 않는다.

-. 적당한 PreparedStatement의 사용
위와같은 이유로 PreparedStatement가 좋다! 모든 쿼리를 PreparedStatement로 하자!
만약 이와 같이 된다면 또다른 문제가 생긴다.
각 DB마다 SQL캐싱할 수 있는 한계가 있기 때문에 정작 성능상 캐싱되어야 할 쿼리가
그렇지 않은 쿼리 때문에 캐싱이 안 될 수 있기때문에 꼭 필요한 문장만

PreparedStatement를 쓰는것을 권고한다.





II. Statement를 받드시 사용해야 하는 경우




1. Dynamic SQL을 사용할 경우


Dynamic SQL을 사용한다면 매번 조건절이 틀려지게 됨으로 statement가 낫겠지요
즉 캐싱의 장점을 잃어버립니다.
또한 Dynamic SQL일 경우 코딩도 Statement가 훨신 편하니다.



2. 디버깅이 좋다.


PreparedStatement보다 Statement가 디버깅이 훨씬 편한것은 사실입니다.

preparedstatement를 디버깅 하려면 따로 래퍼 클래스를 만들거나
jakarta commons의 dbutil을 사용하면 어느정도 디버깅은 할 수 있습니다.






[바로가기 링크] : http://coolx.net/cboard/develop/410



swindler 이거보다 잘 정리된 문서를 본적이 있었는데 못 찾겠다. 2007-12-12
Name
Password
Comment
Copyright © 1999-2017, swindler. All rights reserved. 367,611 visitor ( 1999.1.8-2004.5.26 ), 2,405,771 ( -2017.01.31)

  2HLAB   2HLAB_Blog   RedToolBox   Omil   Omil_Blog