database

Statement보다 PreparedStatement를 사용해야하는이유

MIN우 2024. 6. 6. 15:23
728x90

목차

· 개요

· Statement, PreparedState 동작방식

· Statement,PreparedState 차이점

· 결론

 

 

 

개요

 

· Statement 종류에는 Statement,PreparedStatemennt,CallableStatement 3가지가 존재한다.

· CallableStatement는 PL/SQL문을 호출할 때 사용한다고 했지만 성능상 이슈로 인해 거의 사용하지 않는다.

· 실무에서는 Statement를 사용하지않고 PreparedStatement를 사용한다고하는데 왜 그런지 이유를 알아보자.

 

Statement, PreparedState 동작방식

동작방식

1. 구문 분석(Parsing) 및 정규화(Normalization)

- Query 문법 확인 및 데이터베이스, 테이블 존재여부 확인

2. 컴파일(Compliation)

- Query 컴파일

3. Query 최적화(Query Optimization Phase)

- Query 실행 방법의 최적 계획 선택

4. 캐시(Cache)

- Query 최적화 단계에서 선택된 계획이 캐시에 저장되어 동일한 Query 실행 시 . 1~3 단계를 실행하지 않고 캐시를 

통해 찾는다.

5. 실행(Execution Phase)

- Quer가 실행된 값이 담긴 객체(ResultSet)를 사용자에게 반환

 

Statement vs PreparedStatement 차이점

 

캐시 사용 유무(재사용성)

- Statement는 매번 Query 실행 시 마다, 1번에서 5번까지의 과정을 반복하며 , Prepared Statment 는 최초

Query 실행 시 ,1~5번까지의 과정을 하지만 두번 째 Query 실행 부터는 1번부터 3번까지의 과정을 생략하고 4번부터 시작한다.

 

SQL Injection 방지(보안성)

- Prepared Statment 방식을 사용하면 SQL Injection 공격 또한 방지할 수 있다.

 

[기존 Statement 방식]
Connection conn = DriverManager.getConnection(url, id, pwd);
Statement stmt = conn.createStatement();
stmt.executeQuery("Select * from Member Where id = " + id + " and pwd = " + pwd);

→ 로그인 시, 사용자에게서 입력받은 값을 Where 조건절에 넣어주어 조회하는 Query이지만 만약, 다음과 같이 공격자가 파라미터 값을 악의적으로 조작해서 보낼 수도 있다.

[사용자에게서 입력받은 값]
id = test123
pwd = 1234’ or 1=1

Query = Select * from Member Where id = ‘test123’ and pwd = ‘1234’ OR ‘1’ = ‘1’;

→ 이처럼 공격자가 악의적으로 파라미터 값을 조작하여 “OR 1=1” 조건을 추가하는 방법으로 사용자 정보를 탈취할 수 있다.

[PreparedStatment 방식]
Connection conn = DriverManager.getConnection(url, id, pwd);
String sql = "Select * from Member Where id = ? and pwd = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
pstmt.setString(2, pwd);
pstmt.executeQuery();

→ PreparedStatment 방식은 사용자에게서 받은 파라미터 값이 악의적으로 조작되었다 하더라도 파라미터 바인딩을 통해 SQL Injection을 방지할 수 있다.

→ 정확히는 pstmt.setString() 메소드 내부에서 사용되는 javaEncode() 메소드가 SQL Injection을 방지해주는데 내부 구현이 어떻게 되어있는지 살펴보자! 

[javaEncode() 메소드]
public static void javaEncode(String s, StringBuilder buff, boolean forSQL) {
    int length = s.length();

    for (int i = 0, i < length; i++) {
        char c = s.charAt(i);

        switch (c) { 
            case ‘\t’:
                buff.append(“\\t”);
                break;
            case ‘\n’:
                buff.append(“\\n”);
                break;
            case ‘\f’:
                buff.append(“\\f”);
                break;
            case ‘“’;
                buff.append(‘\’’);
                break;
                ...
        }
    }
}

→ 이처럼 공격자가 악의적으로 조작한 파라미터 값에 “\”를 붙여줌으로써 SQL Injection을 방지할 수 있는 것이다.
출처: https://shuu.tistory.com/129#(3) Statement vs PreparedStatement 차이점-1 [All about IT:티스토리]

 

728x90