땃쥐네

[Spring DB] JDBC 표준 인터페이스의 등장 배경 본문

Spring

[Spring DB] JDBC 표준 인터페이스의 등장 배경

ttasjwi 2022. 8. 21. 16:20

웹 클라이언트 - WAS - DB 의 흐름

 

  • 웹 클라이언트 계층 : 웹 브라우저, 모바일 웹 애플리케이션, PC 웹 애플리케이션, ... 등이 이에 해당
  • 웹 서버 : 외부 클라이언트로부터 요청을 받아, 정적 컨텐츠 리소스(html, css, ...)를 응답하는 계층. 
  • 웹 애플리케이션 서버 : 외부 클라이언트로부터 요청을 받아, 동적 컨텐츠 리소스를 응답하는 계층. 여기서는 java단.
  • 데이터베이스 : 데이터 저장, 관리, 등등을 책임지는 계층. 일반적으로 데이터 조작, 조회를 수행하려면 웹 애플리케이션 서버를 거쳐야한다.

 

웹 클라이언트 계층은 우리 서비스의 웹 애플리케이션 서버(WAS)를 통해 DB의 데이터를 조회, 조작하고, 동적으로 응답을 받을 수 있습니다. 예를 들면, 기차표를 예매할 때 ktx의 코레일톡 애플리케이션을 통해 남아있는 열차 좌석들을 확인하고 예매를 하는 과정은 이에 속합니다. 

 

일차적으로 웹 클라이언트- 웹 애플리케이션 서버 사이에서 수행되는 요청-응답에 관한 로직 부분은 Spring MVC가 다루는 내용인지라 여기서 다루지는 않겠습니다. 또, 웹 정적 컨텐츠 리소스를 응답하는 웹 서버 계층은 고려하지 않도록 하겠습니다.

 

동적 컨텐츠 리소스 요청에 대한 응답을 책임지는 WAS에서 DB에 접근하여 명령을 내리고 결과를 받아오는 부분이 저희가 관심있게 봐야할 부분입니다.


표준화되지 않은 데이터베이스 접근 방법

WAS - DB 간의 요청-응답 로직

WAS 단에서 DB에 데이터를 저장, 조회를 하는 작업을 수행해야하는데 이 과정은 다음 4단계의 과정을 거쳐서 수행됩니다.

 

1. TCP/IP 통신을 통한 커넥션 획득(DB에는 데이터베이스 세션 생성)

2. 연결된 커넥션을 통해 DB에 SQL 전달

3. DB의 SQL 수행

4. 결과를 적절한 객체에 응답받기

 

여기가 DB가 하는 과정을 제외하면 1,2,4에 해당하는 부분을 저희가 자바 코드로 적절하게 작성해야합니다.

 

데이터베이스 변경에 매우 취약

문제는 이 과정들이 각 DB마다 다르다는 것입니다.

 

갑자기 윗선에서 Oracle에서 MySQL로 데이터베이스를 바꿔달라고 요청이 들어온다 칩시다.

이 경우 1,2,4에 해당하는 자바 코드를 변경해야합니다. (커넥션 획득 부분, 각 SQL 제품군에 맞게 SQL을 다르게 작성해야하는 부분, SQL을 전달하는 부분, 결과 응답받는 부분...)

 

개발자는 Oracle에 맞게 작성한 자바 코드를 다 갈아엎고, MySQL에 맞는 자바 코드를 작성하는 방법을 학습하는데 시간을 투자해야합니다. 코드를 많이 뜯어고친다는 것은 새로운 오류를 발생시킬 가능성이 매우 높아서 위험합니다. 그리고 오늘은 MySQL 쓰는데, 내일 갑자기 PostgreSQL로 바꿔달라고 하면 그 때도 또 이런 삽질을 해야합니다. 유지보수에서 매우 취약합니다. 

 

이런 삽질을 개발자가 다 할 수도 없고, 이런 문제를 해결하기 위해 JDBC라는 자바 표준 API가 등장합니다.


JDBC 표준 인터페이스와 JDBC Driver

JDBC 표준 인터페이스

"DBMS 종류에 관계 없이 Java에서 표준화된 사용방법으로 DBMS에 접속할 수 있도록 하는 Java API"
  • java.sql.Connection : DBMS 연결
  • java.sql.Statement : SQL을 담은 내용(여기서 Statement를 그대로 사용하면 SQL Injection에 취약해서 보통은 하위 인터페이스인 PreparedStatement를 사용합니다.)
  • java.sql.ResultSet : SQL 요청 응답 결과

java는 개발자들이 편리하게 데이터베이스에 접근할 수 있도록 아래의 표준 인터페이스(API)들을 정의했습니다.

개발자들은 위의 인터페이스들을 의존하여 사용하면 됩니다.

각 데이터베이스 제품에서 구현한 JDBC 드라이버

각각의 DB 벤더측에서 각각 JDBC 인터페이스 사양에 맞게 구현한 구현체 모음입니다. 개발자는 JDBC 인터페이스를 의존하고, 실질적으로 데이터베이스에 접근하는 역할을 수행하는 것은 드라이버의 API들입니다.


JDBC 도입을 통해 얻어낸 것

표준화된 인터페이스에 의존

애플리케이션 로직은 이제 JDBC 표준 인터페이스에만 의존합니다. 사용하던 DB를 변경하려거든, 변경하고자 하는 DB 벤더측에서 구현한 Jdbc Driver로 드라이버를 변경하고 설정정보를 적절하게 변경해주면 됩니다. 다른 종류의 데이터베이스로 변경해도 애플리케이션 서버의 사용 코드를 거의 그대로 유지할 수 있습니다.

 

개발자의 학습량 경감

이제 JDBC 인터페이스를 의존하게 된 덕분에, 개발자는 JDBC 표준 인터페이스 사용법만 학습하고(한번 배워두면 수십개의 데이터베이스에 모두 동일하게 적용할 수 있습니다.), 이를 이용한 코드를 작성만 해주면 됩니다. 각 DB마다 커넥션 연결, SQL 전달, 결과 응답 방법 등을 새로 학습할 필요가 없게됩니다. DB를 변경할 때 신경써야할 부분이 거의 사라지니 그 시간에 다른 코드에 좀 더 집중할 수 있게 됩니다.


순수 JDBC 기술의 한계

아까, "다른 종류의 데이터베이스로 변경해도 애플리케이션 서버의 사용 코드를 거의 그대로 유지할 수 있다"라고 했는데요. '거의'라는 말은 모든 것을 그대로 유지할 수 있다는게 아니라는 뜻입니다.

 

어느 DB든 Jdbc 인터페이스를 의존하지만, SQL은 개발자가 직접 DB에 맞게 작성해줘야하고, 실제 DB 내부적으로도 데이터 타입 등 여러가지가 다르기 때문이거든요. ANSI에서 정한 SQL 표준이 있지만, 거의 일부만 공통화되어 있게 DB마다 다른 SQL 들이 매우 많습니다. 대표적으로 페이징에 사용하는 limit같은 SQL문은 MySQL, PostgreSQL에서는 사용할 수 있어도 Oracle에서는 쓰지 못 합니다. Oracle에서는 이를 매우 복잡한 서브쿼리를 사용해서 작성해야합니다.

 

결국 데이터베이스를 변경하면 JDBC 코드는 변경하지 않아도 되는데, SQL은 해당 데이터베이스에 맞도록 변경해야합니다.

 

(cf) 자바의 표준 ORM 기술인 JPA(Java Persistence API)를 사용하면 이렇게 각각의 데이터베이스마다 다른 SQL을 작성해야 하는 문제도 많은 부분 해결할 수 있습니다. JPA에서는 개발자가 jpql을 통해 객체 쿼리를 작성하면 이를 각 데이터베이스 방언에 맞게 SQL로 변형시켜서 DB에 날려주기 때문입니다! JPA를 씁시다 여러분...!


참고 : 김영한님의 Spring DB 1편

Comments