들어가며

  • 이번 포스트에서는 Java에서 DB를 연결할 때 사용했던 JDBC(Java Data Base Connectivity)기술에 대한 전반적 배경에 대해 알아본다.

 

 

 

DB를 사용한 데이터의 저장

  • 애플리케이션 개발에서 중요한 데이터들(게시판의 경우 게시글과 그 댓글, 회원 관리의 경우 회원의 정보)을 DB에 저장한다. 그리고 해당 데이터가 필요할 시 DB에서 해당 데이터를 탐색한 뒤 그 데이터를 가져온다.

  • 클라이언트에서 요청이 들어오는 부분은 지금 우리의 관심사는 아니다. 우리의 관심사는 애플리케이션 서버에서 DB로 어떻게 요청과 그 응답이 들어오는가에 대한 것이다.
  • 애플리케이션 서버는 어떻게 DB와 통신을 수행하는걸까?

  • 서버는 먼저 DB로 커넥션을 연결한다. 해당 작업은 서버와 DB가 TCP/IP를 통한 통신 연결이 일어나는 작업이며 웹으로 비유하자면 클라이언트와 서버 간 TCP/IP를 통한 연결을 수행하는것과 동일하다.
  • SQL 전송은 서버에서 DB가 이해할 수 있는 형식의 SQL을 커넥션을 통해 DB에 전송하는 것이다. DB는 해당 SQL을 수신받고 SQL을 수행한다.
  • 마지막으로 수행된 SQL의 결과를 응답으로 애플리케이션 서버에 넘긴다. 이후 커넥션은 종료되며 애플리케이션 서버와 DB간 연결이 종료된다.

 

 

 

DB 연결의 어려움

  • 위의 도식과 과정은 DB와 서버가 연결되고, SQL 요청과 응답을 수신하는 과정을 추상적으로 표시한 것이다. 실제로는 DB의 종류가 MySQL, Oracle, MS-SQL 등 세분화 될 것이다.
  • 문제는 각 DB별로 커넥션을 연결하는 방식과 SQL을 전달하는 방법, 그리고 그 결과를 응답 받는 방식들이 모두 다르다는 것이다. 따라서 다음과 같은 문제점이 발생할 수 있다.
    • 맨 처음 어떤 서비스를 개발할 때 선택한 DB는 MySQL을 선정하였다. 그래서 MySQL에 맞는 DB 커넥션, SQL, 결과 응답 방식을 구현하였다.
    • 그런데 서비스 기간이 길어지면서 Oracle DB로 교체해야 하는 상황이 되었다. 그런데 Oracle DB는 MySQL과 별개의 DB이다. 따라서 커넥션이나, SQL 전송 방식, 응답 방식이 모두 달라진다.
    • 따라서 개발자는 해당 부분을 모두 처음부터 Oracle DB에 맞는 방식으로 다시 구현해야 한다.
  • 이는 비단 한 번만 일어난다는 보장도 없다. 만약 어떠한 사유로 MS-SQL로 넘어가야 한다면 또 다시 밑바닥부터 구현해야 하고, 변경이 매우 크게 일어난다는 것을 의미한다.

 

 

 

JDBC의 등장

  • 사실 이러한 상황을 우리는 프로그래밍 세계에서 본 적이 있다. 위의 과정을 보면 개발자가 MySQL에만 맞춰진 연결, SQL전송, 응답 수신 코드를 구현한 것이다. 즉 구체적인 방식에 의존하고 있다.
  • 이는 객체지향 세계에서 DIP를 위반한것과 동일하다. 따라서 당연히 OCP가 성립하지 않고, OCP가 성립하지 않음으로 인해 DB를 교체하거나, 다른 DB를 붙이는 등의 확장에도 모든 코드들이 변경되어야 할 것이다.
  • 문제점이 명확해졌다. 구체적인 방식에 의존적인 코드를 사용하고 있으니 해결책으로는 추상적인 방식을 의존하도록 하면 될 것이다.

  • 그리고 위의 문제점을 해결한 자바 표준이 바로 JDBC 표준 인터페이스이다. 위의 그림에서는 DB Connection Interface의 역할을 맡는 것이 JDBC 표준 인터페이스라고 할 수 있겠다.
  • 이를 통해서 애플리케이션은 어떤 DB를 사용하고 있는지에 대해 전혀 몰라도, 데이터를 DB에 적재하거나, 반출하거나, 수정하는 등의 연산등을 문제 없이 수행할 수 있다. 즉 DIP가 지켜지게 된다.
  • 이는 이후에 DB가 변경되어도 그에 맞는 구체 커넥션만 꽂으면 되기 때문에 변경점이 매우 적어지게 된다.
  • JDBC 표준 인터페이스는 다음과 같은 기능을 인터페이스로 정의하여 제공한다.
    • java.sql.Connection에 존재하는 커넥션 연결 기능
    • java.sql.Statement에 존재하는 SQL 전송 기능
    • java.sql.ResultSet에 존재하는 SQL 요청에 대한 응답 기능
  • 개발자는 저 3개의 인터페이스를 사용하여 개발을 하면 된다.

 

 

 

JDBC 드라이버

  • 물론 인터페이스만 존재한다고 해서 기능이 수행되는 것은 당연히 아니다. 인터페이스가 존재한다면 해당 인터페이스를 구현한 구현체들(implements)이 존재해야 할 것이다.
  • Oracle, MySql, MS-SQL 등의 각 데이터베이스 벤더들은 JDBC 표준 인터페이스를 자신들의 데이터베이스 명세에 맞도록 구현한 구현체들을 제공하는데 이 구현체들을 JDBC 드라이버라고 한다.
    • MySQL에서 JDBC 표준 인터페이스를 구현한 구현체는 MySQL JDBC 드라이버라고 부른다.
    • Oracle에서 JDBC 표준 인터페이스를 구현한 구현체는 Oracle JDBC 드라이버라고 부른다.
  • 이 드라이버를 사용하여 DB와 통신하는 전체적인 과정은 다음과 같다.

  • 서비스에서 DB와 통신이 필요하다면 JDBC 인터페이스에 DB와 연결 및 SQL을 전송해야 한다는 메시지를 보낸다.
  • JDBC 인터페이스의 구현체 중 MySQL의 명세와 맞는 구현체가 해당 메시지를 수신받고 현재 사용 중인 MySQL DB에 커넥션과 SQL전송을 수행한다.
  • MySQL DB는 SQL에 대한 연산을 수행하여 결과를 응답으로 MySQL 드라이버에 전송한다. 이후 응답이 서비스로 전달된다.
  • 만약 DB가 다른 DB로 교체된다고 하더라도 구현체만 바꾸면 되기 때문에 어플리케이션 서비스에 변경이 일어나지 않는다. 그저 구현체만 다른 것으로 갈아 끼우면 되기 때문이다.

 

 

 

JDBC의 의의와 한계

  • JDBC가 등장함으로서 개발자는 JDBC 인터페이스의 사용 방법만 알면 그 구현체가 무엇인지에 상관 없이 DB와의 통신을 수행할 수 있게 되었다.
  • DB가 변경되어도 변경한 DB에 맞는 JDBC Driver를 갈아끼우면 되기 때문에 DB가 어떻게 커넥션을 연결하는지, SQL 전송 방법이나 응답을 받는 방법에 대한 구체적 스펙을 배우지 않아도 된다.
  • 하지만 JDBC도 한계점이 존재한다.
    • SQL이 달라지는 경우에는 어떻게 해야할까? MySQL과 Oracle, MS-SQL은 모두 각각의 고유한 SQL 문법을 가지고 있다.
    • 이 경우에는 어쩔 수 없이 각각의 SQL 문법을 사용하여 DB와 통신해야 한다. JDBC는 DB와의 통신만을 추상화하여 제공하지 SQL까지 추상화시켜 해당 DB에 맞도록 변경시킬 수 없기 떄문이다.
    • 결국 DB를 변경하게 된다면 어쩔 수 없이 SQL 구문을 해당 DB에 맞게 수정해야 하는 문제점이 생긴다.
  • 위의 SQL의 한계점은 JPA, Hibernate로 대표되는 ORM 기법이 나오기 시작하면서 어느 정도 해결되었다.
복사했습니다!