본문 바로가기

Development Note

[MYSQL] 모르고 지나쳤던 MySQL Connector/J : Statement

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.


Java 가 아니어도 많은 언어에 대한 Connector 를 제공 하고 있다.



자바 프로그래밍을 여러해 동안 하면서 각종 RDBMS 에 연결할 수 있도록 도와주는 Connector 들은 그저 스쳐 지나가는 jar 파일에 불과했다. 그래서 그런지 MyBatis, Hibernate, JPA 와 같은 ORM 에 대해서만 관심이 많았지 Connector 에 대해서는 사실 별로 관심이 없었다. 물론 앞에 언급한 프레임워크에서 모두 다루고 있을지도 모르겠지만 Low Level 에서의 동작에 대한 관심이 별로 없었던 지난 날을 반성해본다. 역시 기술의 기초는 몇번을 강조해도 지나침이 없는거 같다.. (be overemphasized of..)


책에서는 Java 와 연동하는 JDBC 와 C API 로 연동하는 방법들에 대해서 다뤘지만 다른 언어라고 크게 차이는 없을것 같다. 내용도 Application 레벨에서의 기능들에 대해서도 다루기도 하지만 주로 Connector 와 MySQL 간의 통신과 관련된 내용에 대해서 언급을 많이 하고 있다. 내용은 대체로 처음 아는 내용들이 많아서 신선 했다.


신입사원 입사 필기 시험때 이야기를 잠깐 떠올려야 했다. 2008년 겨울 입사 시험으로 나온 문제가 이 JDBC 연동하는 방법을 종이 위에다가 손코딩 하는 것이었다. 가장 먼저 했던 일은 딱 3가지 클래스 이름을 적어 내렸다. 당시는 이런 기초적인 것들이 머릿속에 가득 차 있던 때였으니까... (지금은 다른 것들이 더 많이 차 있다)


Connection connection;
PrepareStatement prepareStatement;
ResultSet resultSet;


이 처럼 위의 세가지 클래스들이 필요하지만 어떤 용도로 사용하고 있는지에 대한 개괄적인 내용들만 알고 있었지 실제로 어떻게 데이터들을 가져오고 만들어 내는지에 대한 내용들에 대해서는 왜 궁금해 하지 않았는지 싶다. 내용들을 살펴보면 크게 어려운 내용들도 아니지만 이제라도 알아보게 되어서 다행이다. 각종 예제들을 살펴보면 각각 저마다의 역할은 명확하다.


  1. Connection : DB 에 연결을 하기 위해 필요한 Object
  2. Statement : DB에 SQL 을 통해서 명령을 전달하기 위한 Object (PrepareStatement 가 대표적인 것이 아니라 Statement 라고 배웠다)
  3. ResultSet  : 처리된 결과를 받아오기 위한 Object


보통은 여기까지 알게 되는데 이번 챕터 내용들을 보면서 더 알게된 내용이 많다. 대용량의 데이터들을 처리하고 Replication 을 이용하는 경우에 따라서 설정해줘야 할 것들을 살펴보면 단순히 DB 로부터 어떤 방법으로 명령어를 처리하느냐 뿐만 아니라 얼마나 똑똑하게 수행할 것인가에 초점을 두었다는 점이 내가 바라본 초점과는 많이 달랐다.


PrepareStatement 와 Statement  와의 차이점


 Statement 대신 PrepareStatement 를 사용하면 쿼리 분석이나 최적화의 일부 작업을 한 번만 수행해서 저장, 다음부터 요청 되는 쿼리는 저장된 결과를 토대로 재사용할 수 있다, 다이나믹 쿼리와 PrepareStatement 를 활용하면 MySQL 에서 분석해야 하는 쿼리 정보가 줄어들어서 메모리 사용량을 줄일 수 있다는 장점이 있다. 또한 JDBC 와 MySQL 서버 간의 프로토콜이 PrepareStatement 는 바이너리, Statement 는 문자열로서 타입 변경이 일어나지 않는 점으로 성능상의 장점이 있다. 거기에 SQL Injection 과 같은 보안상의 취약점에 대한 이점도 있다. 이는 이스케이프 문자 처리를 대신 해준다고 한다.


PrepareStatement 의 종류 

  • Client PrepareStatement : Connector 자체적으로 다이나믹 쿼리의 바인딩 변수에 값을 매핑하여 MySQL 서버에 전달하는 방법
  • Server PrepareStatement : 앞서 이야기한 PrepareStatement 의 분석 쿼리 정보에 대한 메모리 사용량을 줄이는 방법


이렇게 여러가지 성능면에서 이득을 볼 수 있는 PrepareStatement 를 사용할 수 있는 방법은 특별한 구현이 필요한 것이 아니라 특별히 모르고 지나쳤던 MySQL Connection URL 정보에 있었다.


String url = "jdbc:mysql://localhost:3306/mydb";

String url = "jdbc:mysql://localhost:3306/mydb?useServerPrepstmts=true";


차이점이라면 useServerPrepstmts=true 라고 선언이 되어있는 점이다. 저렇게 설정을 해두고 사용하면 Client PrepareStatement 가 아닌 Server PrepareStatement 로 동작을 하게 되어 여러가지 잇점을 볼 수 있다. 이외에도 많은 내용들이 있지만 책을 찾아서 꼭 보길 권하고 싶다. 두꺼워서 잘 갈라지는 무자비한 스케일의 책이지만 (거기에 비싸고..) 정말 내용이 알찬 듯 하다.