Mariadb-Java-Client

이영섭·2024년 11월 13일

강사님이 내주신 과제로 미니프로젝트를 하다 정리할 만한 내용이 생겨서 글을 썼다.

java.sql 패키지

Provides the API for accessing and processing data stored in a data source (usually a relational database) using the Java programming language. This API includes a framework whereby different drivers can be installed dynamically to access different data sources. Although the JDBC API is mainly geared to passing SQL statements to a database, it provides for reading and writing data from any data source with a tabular format. The reader/writer facility, available through the javax.sql.RowSet group of interfaces, can be customized to use and update data from a spread sheet, flat file, or any other tabular data source.

간추려보자면, 해당 패키지는 보통 RDB에 저장된 데이터를 접근하거나 프로세싱하기 위해 제공한다.
또, 다양한 드라이버를 동적으로 설치(수업시간에 사용하는 mariadb-java-client-3.5.0.jar)하여 서로 다른 데이터 소스에 접근할 수 있는 프레임워크를 포함하고 있다.
주로 데이터베이스에 SQL 문을 전달하는 데 중점을 두고 있지만, 표 형식의 모든 데이터 소스에서 데이터를 읽고 쓸 수 있는 기능을 제공한다.

위 설명을 기억해두고 파일들을 구경해보면 Class 파일보다 Interface 파일이 3배정도 더 많다. 그 이유는 위에서 설명했듯이 각자의 데이터베이스 맞게 구현 되어있는 즉, 구체 클래스가 들어있는 라이브러리를 추가해서 사용한다.

많이 사용하는 DriverManager, Connection, Preparedstatement, ResultSet 클래스 및 인터페이스에 대해서 정리해보고자 한다.

DriverManager 클래스

데이터베이스에 연결을 구하는 방법은 DataSource 또는 DriverManager를 이용해서 정의한다.

DataSource는 JDBC 2.0부터 도입된 인터페이스로, 커넥션 풀링과 분산 트랜잭션 등 엔터프라이즈(기업용 서버) 환경에서 필요한 기능을 지원한다. javax.sql 패키지에 정의된 DataSource 인터페이스를 각 벤더(HikariCP, Apache DBCP, MariaDB 등)가 구현한 구현체를 사용하여 데이터베이스 연결을 관리한다.

DriverManager는 JDBC 1.0부터 제공된 구체 클래스로, 데이터베이스 드라이버를 등록하고 관리하는 역할을 한다. getConnection(url, user, password) 메서드는 등록된 드라이버들 중에서 주어진 URL을 처리할 수 있는 드라이버를 찾아 해당 드라이버의 Connection 구현체를 반환한다.

예를 들어, MariaDB JDBC 드라이버를 사용할 경우, DriverManager.getConnection()org.mariadb.jdbc.Connection 구현체의 인스턴스를 반환한다. 이 구현체는 java.sql.Connection 인터페이스를 구현하여 데이터베이스와의 실제 연결을 담당한다.

DataSource와 DriverManager의 주요 차이점

  1. 연결 방식
    • DriverManager: 매번 새로운 데이터베이스 연결을 생성
    • DataSource: 커넥션 풀을 통한 연결 재사용 가능
  2. 설정 관리
    • DriverManager: URL, 사용자 이름, 비밀번호 등을 매번 제공해야 함
    • DataSource: 한 번 설정 후 재사용 가능
  3. 트랜잭션 지원
    • DriverManager: 기본적인 트랜잭션만 지원
    • DataSource: 분산 트랜잭션 지원 (XA 트랜잭션)

장단점

DriverManager

  • 장점
    • 사용이 간단함
    • 설정이 minimal함
    • 단순한 애플리케이션에 적합
  • 단점
    • 성능 최적화의 한계
    • 연결 관리의 유연성 부족
    • 확장성이 제한적

DataSource

  • 장점
    • 커넥션 풀링을 통한 성능 향상
    • 설정의 중앙화
    • 확장성과 유연성이 뛰어남
  • 단점
    • 초기 설정이 더 복잡할 수 있음
    • 학습 곡선이 더 높을 수 있음

커넥션 풀링

커넥션 풀은 데이터베이스 연결을 미리 생성하고 보관하는 기법이다. 애플리케이션이 데이터베이스 연결을 요청할 때마다 새로운 연결을 생성하는 대신, 이미 생성된 연결을 재사용함으로써 다음과 같은 이점을 제공한다:

  1. 성능 향상

    • 연결 생성/종료 비용 감소
    • 빠른 응답 시간
  2. 리소스 관리

    • 동시 연결 수 제한 가능
    • 시스템 자원 효율적 사용
  3. 안정성

    • 연결 누수 방지
    • 장애 대응 기능

    Connection을 사용하기 이전에 Class.forName("org.mariadb.jdbc.Driver") 를 통해 해당 드라이버를 먼저 로드시키는 작업이 필요하다.

Class.forName()의 호출은

  1. 지정된 클래스가 메모리에 로드되어 있는지 확인
  2. 없다면 클래스 로더를 통해 클래스 파일 찾기
  3. 클래스 파일을 메모리에 로드
  4. static 초기화 블록 실행
  5. Class 객체 반환

이렇게 해서 JDBC 드라이버가 로드되고 초기화된다.

JDBC 4.0 부터는 Class.forName() 호출이 필수는 아니게 되었다. 하지만, 하위 호환성을 위해 여전히 이 코드를 사용한다.

Connection 인터페이스

java.sql 의 Connection 클래스는 인터페이스이므로 따로 설명할 건 없고,

MariaDB JDBC 드라이버의 경우 해당 인터페이스를 구현한 Connection 구체 클래스를 제공한다.

PreparedStatement 인터페이스

MariaDB JDBC 에서 PreparedStatement의 구현체는 ClientPreparedStatementServerPreparedStatement 두가지가 존재한다. (BasePreparedStatement 추상 클래스도 존재함 → 이 클래스를 상속받아 구현)

어떤것을 사용할지의 결정은 쿼리의 특성과 드라이버의 설정에 따라 자동적으로 결정된다.

  • ClientPreparedStatement
    • SQL 파싱이 클라이언트(Java 애플리케이션) 측에서 수행됨
    • 매번 쿼리 실행시 서버로 완성된 SQL문이 전송됨
    • 네트워크 트래픽이 더 많이 발생할 수 있음
    • 서버 리소스 사용이 적음
    • 단순한 쿼리에 적합
  • ServerPreparedStatement
    • SQL 파싱이 데이터베이스 서버에서 수행됨
    • 최초 1회만 쿼리를 전송하고, 이후에는 파라미터만 전송
    • 네트워크 트래픽이 감소
    • 서버에서 쿼리 실행 계획을 캐시하여 재사용
    • 서버 리소스를 더 사용하지만 성능이 향상됨
    • 복잡하거나 자주 실행되는 쿼리에 적합

명시적으로 설정할 수 있지만, 대부분의 경우 드라이버가 자동으로 적절한 구현체를 선택하므로, 특별한 이유가 없으면 기본 설정을 권장한다.

ClientPreparedStatement 의 설명을 보면 Statement 와의 차이점이 살짝 모호해진 감이 있다. 하지만 보안성(Injection), 특수문자처리, 코드품질, 유지보수 측면에서 PreparedStatement 가 훨씬 뛰어나므로 사용이 권장된다.

ResultSet 인터페이스

위의 PreparedStatement 와 비슷하게 Result라는 추상메서드가 정의되어있고, 이것을 상속받아 CompleteResultStreamingResult 라는 2개의 구현체가 존재한다.

각각의 특징은

  • CompleteResult:
    • 모든 결과를 한 번에 메모리에 로드
    • 빠른 데이터 접근
    • 메모리 사용량이 큼
    • 작은 결과셋에 적합
  • StreamingResult:
    • 필요할 때마다 데이터를 서버에서 가져옴
    • 메모리 사용량 적음
    • 네트워크 통신 더 많음
    • 대용량 데이터 처리에 적합

이것도 드라이버가 상황에 따라 적절한 구현체를 선택하므로, 개발자가 직접 구현체를 선택할 일은 거의 없다.

profile
성장과 발전에는 열려있고, 안주와 정체에는 닫혀있는 개발자 이영섭입니다.

0개의 댓글