Spring Boot에서 Hive JDBC 연동 및 데이터 조회 구현

개요

기존 데이터베이스로는 대용량 데이터 분석 시 성능 병목이 발생하는 경우가 많습니다. 이 글에서는 Spring Boot 환경에서 Hive 서버에 JDBC로 접속하여 데이터를 조회하고 처리하는 방법을 살펴봅니다. CDH(Cloudera Distribution Including Apache Hadoop) 환경을 기준으로 작성되었습니다.

실행 환경

구성 요소버전
Spring Boot2.1.8.RELEASE
CDH5.15.1
Hive1.1.0

Hive 버전 확인

먼저 서버에 접속하여 Hive 버전을 확인합니다.

hive --version

출력된 버전 정보를 확인한 후, 클라이언트 의존성도 동일한 버전으로 맞춰야 프로토콜 불일치 문제를 피할 수 있습니다.

프로젝트 설정

Maven 의존성 추가

pom.xml에 Hadoop 공통 라이브러리와 Hive JDBC 드라이버를 추가합니다. Hive 서버 버전이 1.1.0이므로 클라이언트도 동일하게 지정합니다.

<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>2.6.5</version>
</dependency>
<dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-jdbc</artifactId>
    <version>1.1.0</version>
</dependency>

샘플 애플리케이션

아래 예제는 CommandLineRunner를 활용해 애플리케이션 실행 시 자동으로 Hive 쿼리를 수행하는 코드입니다. 실제 환경에서는 설정 외부화와 예외 처리를 추가하시기 바랍니다.

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.sql.*;

@Slf4j
@SpringBootApplication
public class HiveAnalyticsRunner implements CommandLineRunner {

    private static final String HIVE_DRIVER = "org.apache.hive.jdbc.HiveDriver";
    private static final String JDBC_URL = "jdbc:hive2://datanode02:10000/test";
    private static final String USERNAME = "hive";
    private static final String PASSWORD = "";

    public static void main(String[] args) {
        SpringApplication.run(HiveAnalyticsRunner.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        loadDriver();
        
        try (Connection conn = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD);
             Statement st = conn.createStatement()) {
            
            String targetTable = "sample_metrics";
            
            initializeTable(st, targetTable);
            inspectSchema(st, targetTable);
            fetchAllRecords(st, targetTable);
            executeAggregation(st, targetTable);
        }
    }

    private void loadDriver() {
        try {
            Class.forName(HIVE_DRIVER);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException("Hive 라이버 로드 실패", ex);
        }
    }

    private void initializeTable(Statement statement, String table) throws SQLException {
        log.info("기존 테이블 제거 및 재생성");
        statement.execute(String.format("DROP TABLE IF EXISTS %s", table));
        statement.execute(String.format(
            "CREATE TABLE %s (metric_key INT, metric_value STRING)", table));
    }

    private void inspectSchema(Statement statement, String table) throws SQLException {
        log.info("테이블 스키마 확인");
        ResultSet rs = statement.executeQuery(String.format("DESCRIBE %s", table));
        while (rs.next()) {
            log.info("{} : {}", rs.getString(1), rs.getString(2));
        }
    }

    private void fetchAllRecords(Statement statement, String table) throws SQLException {
        log.info("전체 레코드 조회");
        ResultSet rs = statement.executeQuery(String.format("SELECT * FROM %s", table));
        while (rs.next()) {
            log.info("key={}, value={}", rs.getInt(1), rs.getString(2));
        }
    }

    private void executeAggregation(Statement statement, String table) throws SQLException {
        log.info("집계 쿼리 실행");
        ResultSet rs = statement.executeQuery(
            String.format("SELECT COUNT(1) AS total FROM %s", table));
        if (rs.next()) {
            log.info("레코드 수: {}", rs.getLong("total"));
        }
    }
}

실행 결과

애플리케이션을 실행하면 다음과 유사한 로그가 출력됩니다.

INFO  o.a.h.j.Utils : Supplied authorities: datanode02:10000
INFO  o.a.h.j.HiveConnection : Will try to open client transport with JDBC Uri: jdbc:hive2://datanode02:10000/test
INFO  c.e.d.HiveAnalyticsRunner : 기존 테이블 제거 및 재생성
INFO  c.e.d.HiveAnalyticsRunner : 테이블 스키마 확인
INFO  c.e.d.HiveAnalyticsRunner : metric_key : int
INFO  c.e.d.HiveAnalyticsRunner : metric_value : string
INFO  c.e.d.HiveAnalyticsRunner : 전체 레코드 조회
INFO  c.e.d.HiveAnalyticsRunner : 집계 쿼리 실행
INFO  c.e.d.HiveAnalyticsRunner : 레코드 수: 0

주의 사항

  • 드라이버 클래스 경로: 사용하는 hive-jdbc JAR에 따라 드라이버 클래스명이 상이할 수 있으므로, 실제 패키지 경로를 확인하세요. 일부 버전에서는 org.apache.hive.jdbc.HiveDriver 대신 다른 경로를 사용하기도 합니다.
  • 버전 호환성: 클라이언트와 서버의 Hive 메이저 버전이 다르면 연결 과정에서 오류가 발생할 수 있습니다.
  • 리소스 해제: JDBC 리소스는 try-with-resources 문법으로 자동 반납하도록 구성하는 것이 안전합니다.

태그: Hive Hive JDBC Spring Boot cdh Apache Hadoop

7월 20일 02:11에 게시됨