자바 애플리케이션을 개발하다 보면 로고, 사진 같은 이미지 파일을 데이터베이스에 직접 저장해야 하는 경우가 있습니다. 이 글에서는 JDBC(Java Database Connectivity)를 사용해 이미지를 데이터베이스에 삽입하는 방법을 단계별로 살펴보겠습니다.
setBinaryStream() 메서드란?
PreparedStatement 인터페이스의 setBinaryStream() 메서드는 매개변수의 인덱스를 나타내는 정수값과 InputStream 객체를 인자로 받아, 해당 매개변수를 지정된 InputStream 객체로 설정합니다.
일반적으로 아주 큰 바이너리(binary) 값을 데이터베이스로 전송해야 할 때 이 메서드를 사용합니다. 이미지, 오디오, 동영상 등 대용량 바이너리 데이터를 다룰 때 유용한 방식입니다.
BLOB 데이터 타입 이해하기
SQL 데이터베이스는 BLOB(Binary Large Object)라는 데이터 타입을 제공합니다. BLOB 컬럼에는 이미지처럼 용량이 큰 바이너리 데이터를 그대로 저장할 수 있어, 파일 시스템이 아닌 데이터베이스 내에서 이미지를 관리할 수 있습니다.
JDBC로 이미지 저장하는 절차
JDBC 프로그램으로 데이터베이스에 이미지를 저장하려면 먼저 BLOB 타입의 컬럼을 포함한 테이블을 생성해야 합니다.
CREATE TABLE Tutorial(Name VARCHAR(255), Type INT NOT NULL, Logo BLOB);
테이블 생성 후, JDBC로 데이터베이스에 연결하고 위 테이블에 값을 삽입하기 위한 PreparedStatement를 준비합니다.
String query = "INSERT INTO Tutorial(Name, Type, Logo) VALUES (?, ?, ?)"; PreparedStatement pstmt = con.prepareStatement(query);
그다음 PreparedStatement 인터페이스의 setter 메서드를 사용해 플레이스홀더(?)에 값을 설정합니다. 일반 문자열은 setString()으로, BLOB 타입에는 setBinaryStream() 메서드를 사용해 이미지 파일 스트림을 전달합니다.
FileInputStream fin = new FileInputStream("javafx_logo.jpg");
pstmt.setBinaryStream(3, fin);전체 예제 코드
아래는 JDBC 프로그램을 통해 MySQL 데이터베이스에 이미지를 삽입하는 전체 예제입니다. BLOB 타입 컬럼을 가진 테이블을 생성하고, setBinaryStream()으로 이미지 파일을 삽입한 뒤, 테이블의 내용을 다시 조회하는 과정까지 포함되어 있습니다.
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class InsertingImageToDatabase {
public static void main(String args[]) throws Exception {
// 드라이버 등록
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
// 데이터베이스 연결
String mysqlUrl = "jdbc:mysql://localhost/sampleDB";
Connection con = DriverManager.getConnection(mysqlUrl, "root", "password");
System.out.println("Connection established......");
// Statement 생성
Statement stmt = con.createStatement();
// 테이블 생성 쿼리 실행
String createTable = "CREATE TABLE Tutorial( "
+ "Name VARCHAR(255), "
+ "Type VARCHAR(50), "
+ "Logo BLOB)";
stmt.execute(createTable);
// 데이터 삽입
String query = "INSERT INTO Tutorial(Name, Type, Logo) VALUES (?, ?, ?)";
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.setString(1, "JavaFX");
pstmt.setString(2, "Java_library");
FileInputStream fin = new FileInputStream("E:\\images\\javafx_logo.jpg");
pstmt.setBinaryStream(3, fin);
pstmt.execute();
pstmt.setString(1, "CoffeeScript");
pstmt.setString(2, "scripting Language");
fin = new FileInputStream("E:\\images\\coffeescript_logo.jpg");
pstmt.setBinaryStream(3, fin);
pstmt.execute();
pstmt.setString(1, "Cassandra");
pstmt.setString(2, "NoSQL database");
fin = new FileInputStream("E:\\images\\cassandra_logo.jpg");
pstmt.setBinaryStream(3, fin);
pstmt.execute();
System.out.println("Data inserted");
ResultSet rs = stmt.executeQuery("Select *from Tutorial");
while(rs.next()) {
System.out.print("Name: "+rs.getString("Name")+", ");
System.out.print("Tutorial Type: "+rs.getString("Type")+", ");
System.out.print("Logo: "+rs.getBlob("Logo"));
System.out.println();
}
}
}실행 결과
Connection established...... Data inserted Name: JavaFX, Tutorial Type: Java_library, Logo: com.mysql.jdbc.Blob@7dc5e7b4 Name: CoffeeScript, Tutorial Type: scripting Language, Logo: com.mysql.jdbc.Blob@1ee0005 Name: Cassandra, Tutorial Type: NoSQL database, Logo: com.mysql.jdbc.Blob@75a1cd57
출력 결과에서 Logo 값이 객체 참조 형태(com.mysql.jdbc.Blob@...)로 표시되는 것은, 조회 시 BLOB 객체 자체가 반환되기 때문입니다. 실제 이미지를 화면에 표시하려면 getBlob()으로 가져온 데이터를 다시 InputStream으로 읽어 파일로 저장하거나 이미지 컴포넌트에 렌더링하면 됩니다.
주의사항
JDBC 프로그램으로 저장하고 조회할 수 있는 이미지는 .gif, .jpeg, .png 형식뿐이라는 점에 유의하세요. 또한 대용량 이미지를 다룰 경우 MySQL의 max_allowed_packet 설정이나 메모리 사용량도 함께 고려하는 것이 좋습니다.