DB에서 전달 받은 BLOB데이터 처리하기

2023. 11. 24. 10:45Programming Language/Java

프로젝트를 하다가 DB에 BLOB형태로 들어 있는 이미지 파일을 마이바티스로 꺼내다가 JSP로 뿌려줘야 하는 일이 들어 왔었다. 일을 주시는 분이 "BLOB형태로 들어 있는 그 데이터 그냥 긁어다 URL에 뿌리면 이미지로 보여 그냥 쓰면 돼" 라는 말을 듣고 그냥 쓰려고 했다 한참 삽질을 했다 ㅋㅋ..지금까지도 그 BLOB을 어떻게 그냥 갖다가 URL에 뿌리라는건지(DB에서 긁어서 가져와도 URL길이 때문에 보이질 않앗음..)이해는 못했으나 그 과정에 이해한 내용을 적어보려고 한다.


🤔BLOB이란?

BLOB은 "Binary Large Object"의 약자로, 이진 형태로 구성된 대용량 데이터를 나타내는 용어이다.

BLOB 데이터 는 주로 멀티미디어 파일( 이미지, 비디오, 사운드, 문서 등 )을 저장하거나 전송하기 위해 사용된다.

BLOB 데이터는 데이터베이스나 파일 시스템 등에 저장되며, 일반적으로 텍스트 데이터와는 다른 방식으로 다뤄진다.

 

1. 이진 형태의 데이터 저장: BLOB 데이터 타입은 이진 데이터를 저장하기 위해 사용된다. 파일의 바이너리 형태를 그대로 저장할 수 있다.

2. 대용량 데이터 저장: BLOB 데이터 타입은 대용량 데이터를 저장할 수 있다. 이진 데이터의 크기에 제한을 받지 않으며, 테이블의 다른 열과는 독립적으로 저장된다.

3. 데이터 압축 및 암호화: BLOB 데이터 타입은 데이터 압축 및 암호화 기능을 제공한다. 압축을 통해 저장 공간을 절약하거나, 암호화를 통해 데이터의 안전성을 강화할 수 있다.

4. 효율적인 검색 및 처리: BLOB 데이터 타입은 인덱스를 생성할 수 있어 효율적인 검색이 가능하다. 또한, 데이터베이스 내에서 BLOB 데이터에 대한 집계나 연산을 수행할 수도 있다.

 

BLOB 데이터 타입은 주로 이미지나 멀티미디어 파일과 같은 대용량의 이진 데이터를 저장하는 용도로 사용된다. 데이터베이스에서 BLOB 데이터를 다루기 위해서는 데이터의 삽입, 업데이트, 검색 등을 위한 적절한 SQL 문을 사용해야 한다.

 


😁DB에서 BLOB데이터를 다루기

DB에서 데이터를 받아올때는 Mybatis를 사용해서 Java로 가져왔었는데 DB에서 BLOB형태의 데이터를 그대로 받아오면 어떻게 나오게 될까?

	<select id="nameOfMethod" parameterType="Map" resultType="HashMap">
		SELECT Query
	</select>

위와 같이 BLOB데이터를 가지고 있는 테이블을 조회하는 SELECT 쿼리를 실행했을때 가져오는 BLOB데이터를 SYSOUT으로 출력했을때 아래와 같은 결과를 보여준다.

이는 결국 BLOB형태의 데이터가 저장되어 있는 주소값을 담고 있는 것인데 DB에서 BLOB 데이터를 가져올 때 oracle.sql.BLOB@6a99e341와 같이 주소값으로 표시되는 이유는 BLOB 객체의 기본적인 문자열 표현 방식이다. 이 주소값은 BLOB 객체의 실제 데이터를 가리키는 참조(Reference)이다.

BLOB은 이진 형태의 대용량 데이터를 저장하는 데이터 타입이기 때문에 메모리에 직접 데이터를 저장하는 것이 비효율적이기에 메모리에 있는 데이터의 위치를 참조하는 방식으로 처리한다. oracle.sql.BLOB@6a99e341와 같은 주소값은 이러한 참조를 나타내는 것이다.

주소값을 통해 BLOB 객체를 식별하고 참조할 수 있으며, 필요한 시점에 해당 주소를 사용하여 실제 데이터에 접근하고 처리할 수 있다. 그러나 이 주소값은 데이터의 실제 내용을 직접 표현하는 것이 아니기 때문에, 실제 데이터를 접근하려면 해당 주소를 활용하여 추가적인 작업을 수행해야 한다.

 

DB에서 BLOB데이터를 받아 JAVA에서 사용하기 위해서는 두가지 방법이 있다.

1. BLOB 데이터를 받아 인코딩해서 사용하기

DB에서 받아온 BLOB데이터는 참조값으로 담겨 있기에 바로 사용이 불가능하다. 먼저 그 참조값을 기반으로 객체에 존재하는 데이터를 뽑아내는게 우선이다.

import java.sql.Blob;

	...

//1. BLOB 참조값을 이용해 데이터를 가져와 byte[]으로 변환하기

Map<String, Object> resultMap = getBlobData(paramerter);
Blob rsultBlob = (Blob)resultMap.get("IamBlobDate") //-> BLOB데이터를 Blob데이터 타입에 담는다.
int resultBlobLength = (int)resultBlob.length(); // -> BLOB데이터를 byte배열로 부르기 위한 길이를 변수로 저장
byte[] resultBlobByteArr = resultBlob.getBytes(1, resultBlobLength); // -> BLOB데이터를 byte배열로 변환

/*
	Blob.getBytes() 함수 
    .getBytes(읽어들일 byte의 시작 위치(1부터 시작), 얼만큼의 byte를 읽을지에 대한 길이) 반환값 -> byte[]
*/

이후 데이터를 JSP에서 사용하기 위함이라면 base64의 형태로 변환(인코딩)해줘야 한다.

2. 변환한 byte배열을 이용해서 base64로 인코딩한다
String resultBlobByteArrToBase64 = Base64.getEncoder().encodeToString(resultBlobByteArr);

 

2. BLOB 데이터를 받아올때 byte배열로 받아 인코딩하기

기존엔 mapper를 통해서 resultType='Map or HashMap'과 같이 받던 것을 resultMap을 사용하여 DB에서 받는 해당 데이터는 Java에서 어떤 타입으로 받아줄것이다 라고 지정할수가 있다.

<!-- 
    resultMap 부분
    (DB에서 가져올 데이터를 Java에서는 어떤 타입으로 받아줄것인지에 대해 작성하는 부분)
-->
    
    <resultMap id="imgData" type="java.util.Map">
		<result property="IMAGE_DATA" column="IMAGE_DATA" jdbcType="BLOB" javaType="[B"/>
	</resultMap>
    
    <!-- 
    	DB에 있는 column이름이 IMAGE_DATA인 컬럼에서 받는 데이터(column="IMAGE_DATA")는 
        DB에서는 BLOB형태이고(jdbcType="BLOB") 받아서 
        자바에서 담을때 byte배열으로 받을 것이며(javaType="[B")
        이 데이터를 받아올때 컬럼의 이름은 IMAGE_DATA로 할것이다(property="IMAGE_DATA")
        
        그리고 실제로 받아서 자바에서 저장하는 전체 타입은 Map형식인데(type="java.util.Map")
        실제 SELECT를 하는 쿼리를 실행하는 SELECT 태그에서는 반환 타입이름을 imgData로 하겠다(id="imgData")
    -->
    
    *정확히 [B에 대한 내용에 대한 이해는 부족하다, 하지만 byte[]으로 작성해도 byte배열로 받아오긴 
    했었다. 둘다 되는 것인지 버전에 따라 다른것인지는 정확히 모름..*
    
    <!--
    	SELECT 태그
    -->
    
    	<select id="nameOfMethod" parameterType="Map" resultMap="imgData">
			SELECT Query
		</select>

이후에 받아온 데이터의 형태를 보면 

타입이 BLOB이 아닌 [B로 받아진것을 볼수 있음.

그러고 나서 base64로 인코딩만 해주면 JSP에서 바로 사용할수 있게 된다.

		byte[] resultBlobByteArr = (byte[])resultMap.get("IMAGE_DATA");
		String resultBlobByteArrToBase64 = Base64.getEncoder().encodeToString(resultBlobByteArr);

 

'Programming Language > Java' 카테고리의 다른 글

Java Roadmap  (0) 2023.10.12