오늘 제이슨의 수업에서 mysql을 docker container에 올려 실행하는 방법과 간단한 jdbc api 사용법, sql 문법에 대해 배웠습니다. 수업 진행 중 제이슨이 "Statement 와 PreparedStatement가 있는데 차이는 누가 블로그에 올리겠죠." 라고 했고 저는 이 블로그 각을 놓칠 수 없었습니다.
옛날에 JDBC를 공부하던 때의 기억을 되살려 한 번 Statement vs PreparedStatement
를 비교하여 포스팅을 해보고자 합니다.
원문은 baeldung 에서 확인할 수 있고 이 포스팅은 원문을 조금 이해하기 쉽게 설명하고자 합니다..
Statement vs PreparedStatement
JDBC API에는 두가지 인터페이스가 존재합니다. (인터페이스의 구현체는 아마도 각 rdbms 벤더사 class에 있을 가능성이 높아요 .. 아닐지도 ㅋ)
- Statement
- PreparedStatement
위 두 인터페이스는 SQL query를 실행하는 데 사용하지만 전혀 다른 기능을 갖고 있습니다.
차이점은 doc에 나와있는 설명에서부터 확인할 수 있는데요. 두 Interface를 생성하는 Connection docs 로 이동해봅시다.
위 두 사진의 내용을 간단히 해석해보면 SQL query를 db에 보내기 위한 객체를 생성한다고 말하지만 PreparedStatement
는 조금 다릅니다."매개변수가 있는" 이라는 단어가 존재하죠.
그렇다면 사용법에서 어떤 차이를 보이는지 살펴보면서 장단점을 알아보겠습니다..
Statement
public class MemberDao {
public void insert(final Member member) {
Connection connection = JdbcTemplate.getConnection();
String sql = "insert into member (id,name) values (\'" + member.getId() + "\', \'" + member.getName() + "\');";
try {
Statement statement = connection.createStatement();
statement.executeUpdate(sql);
connection.commit();
} catch (SQLException e) {
System.out.println(e);
}
}
}
위 코드에서 볼 수 있듯, String 문자열에 직접 원하는 데이터를 넣어야 합니다.
이는 코드의 가독성
을 떨어트림과 동시에 유지보수, 코드 작성
에도 치명적인 단점을 보입니다.
이런 Statement
의 쿼리 생성 방법으로 인해 SQLInjection에도 취약하다고 하는데요.
만약 코드를 실행하는 시점에 아래와 같은 argument가 입력됐다고 가정하겠습니다.
memberDao.insert(new Member("1", "jaehun' --"));
statement 객체는 sql query를 생성할 때 ' 를 탈출하지 못하고 게다가 --로 인해 이후 모든 sql 명령어가 주석으로 처리됩니다.
하지만 CREATE, ALTER 등 DDL을 사용할 때는 Statement 인터페이스를 사용하는 것도 효과적이라고 합니다.
PreparedStatement
public class MemberDao {
public void insert(final Member member) {
Connection connection = JdbcTemplate.getConnection();
String sql = "insert into member (id,name) values (?, ?);";
try {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, member.getId());
preparedStatement.setString(2, member.getName());
preparedStatement.executeUpdate();
connection.commit();
} catch (SQLException e) {
System.out.println(e);
}
}
}
Statement를 상속받은 PreparedStatement는 벌써부터 보기 편합니다.
가독성이 좋고 당연히 유지보수 및 이해에도 좋습니다.
게다가 Statement에서 발생한 SQL Injection 문제에도 안전합니다.
PreparedStatement는 쿼리를 생성할 때 setString 하는 시점에 엥간한 기호는 escape해준다고 보면 됩니다.
그래서 무엇을 쓸꼬?
상황에 따라 다릅니다. DDL 문법은 간단하게 Statement 인터페이스를 쓸 수 있습니다.
하지만 일반적인 DML 쿼리를 작성할 때는 PreparedStatement 인터페이스의 사용을 추천합니다.
게다가 PreparedStatement 인터페이스는 바이너리 프로토콜을 이용하여 패킷의 데이터를 줄임으로써 JVM과 db간의 통신 속도를 개선해줍니다.
마무리
더 많은 차이점이 있지만 요정도만 알아도 충분히 둘을 사용하는 상황을 구분하여 쓸 수 있을 것 같습니다.
즐거운 JDBC 사용을 해보아요~!
'우아한테크코스 4기 > 레벨1' 카테고리의 다른 글
[Java] @BeforeEach와 독립적인 단위 테스트 (0) | 2022.04.06 |
---|---|
[Java] db 테스트 (0) | 2022.04.02 |
[Java] Singleton LazyHolder는 왜 Thread safe 한가? (0) | 2022.03.16 |
[Java] 전략패턴 (0) | 2022.03.15 |
[Java] 의존성 역전 원칙 (0) | 2022.03.07 |