# 상황 :
만일 소스 코드단에서 이미지를 불러와 다루어야 하는 상황이 발생하면
-> 보통 링크를 통해 불러오거나 혹은 로컬 폴더에 저장되어 있는 이미지 파일을 코드에서 제공하는 파일 시스템을 통해 상대경로로 불러와 다뤄본 경험이 있을 것이다.(하드 코딩이든, 절대 경로 지정이든, 상대 경로 지정이든)
이 같은 경우라면 파일도 결국 url과 같이 OS에 저장된 징검다리를 불러온 것과 다름이 없다.
그래서 보통 경로를 받아오면 되겠다, 파일 넣었을 때 그 경로를 알아내면 해결 되겠다. 라고 접근 하게 된다.
예전엔, activeX로 파일을 넣을 시 (Drag & Drop 또는 파일 위치 선택해서 불러오게끔) 경로 까지 알 수 있었다고 한다.
하지만, 그것으로 인해서 탐색기에 접근 하게 되며, 보안 위험에 문제가 생겨서, 요즘 날엔 activeX를 사용하지 말라고 함.
그래서, 경로를 하드 코딩 또는 변수로만 지정해서 불러와 쓸 수 밖에 없나? 라는 생각을 하게 되었다.
하지만, 다른 방법이 있다.
# 방법 :
base64로 변환해주면 우리가 직접 소스 코드단에 이미지 데이터 자체를 저장할 수 있게 된다.
한마디로 변수에 문자열이나 숫자를 저장하는 것처럼, 변수에 이미지를 저장할 수 있는 것이다.
base64는 이미지 데이터 값을 변환하는게 아닌 그냥 출력 형식을 변환하는 것이기 때문에,
이미지 자체가 바뀌는 것이 아니기에 가능한 것이다.
즉, 이미지 데이터 정보는 이미 base64 텍스트 자체에 포함되어 있기 때문에, 결과적으로 링크 url을 통해
서버에 요청하지 않고도 직접 이미지를 사용할 수 있게됨.
# 정리 :
★별도 이미지 파일이 필요 없음. base64 데이터 자체가 이미지이다.
☆ 브라우저 렌더링시, 문서로딩과 같이 로딩 되기에 끊기지 않고 불러옴, 또한 네트워크가 좋지 않아도
위와 같은 특징으로 이미지를 로딩할 수 있음.
★ 문자열이 매우 길기에 가독성이 떨어짐.
☆ base64 인코딩을 사용하면 원본보다 33%의 용량이 커져서, 남용할 경우 오히려 로딩 속도가 저하됨.
# 참고 :
숫자나 스트링이 아닌, 이미지나 비디오 같은 복잡한 멀티미디어 파일들은 어떻게 변수에 메모리 저장할 까?
변수에 이미지 url을 저장하는 것은 링크라는 징검다리를 저장하는 것이지, 이미지 데이터
그 자체를 저장하는 것이 아니다. --> 이미지 데이터 그 자체를 저장하려고 할 때, 사용 하는 것이 Base64
# Base64의 개념
0과 1로 이루어진 이진 데이터(바이너리)를 인코딩하여 텍스트 형식으로 변환하는 것을 말함.
# Base64로 변환하는 방법
# javascript
fetch 안에 들어갈 url은
구글 크롬에서 원하는 이미지를 url 주소로 검색하여 가져와서 사용한다.
(async () => {
const data = await fetch('https://cdn-icons-png.flaticon.com/512/29/29513.png');
const blob = await data.blob();
const reader = new FileReader();
reader.onload = () => {
const base64data = reader.result;
console.log(base64data)
console.log(blob)
console.log(reader)
};
reader.readAsDataURL(blob);
})();
개발자 도구 console에 보면
위에 나타난 긴 url을 복사 후 주소창에 입력 해보자.
이미지가 잘 불러와진 것을 확인 할 수 있다.
const blob = await data.blob();
reader는 readAsDataURL로 인해 읽은 데이터의 값들을 나타낸다.
reader.readAsDataURL(blob);
즉 받은 이미지 데이터인 위치 정보가 담긴 blob 바이너리 객체의 값을 readAsDataURL을 통해
파일의 URL을 읽어 들임. reader에 onload 걸어줘서 reader를 불러올 시 base64data로 만들어 주고,
콘솔 값을 찍어주는 형식이다.
이 외에도 여러 가지 있음
1. reader.readAsDataURL(blob); // base64 형태의 data url로 데이터를 읽어 변환
2. reader.readAsArrayBuffer(blob); // ArrayBuffer 형태로 데이터를 읽어 변환
3. reader.readAsText(blob, [encoding]); // encoding 방식에 맘ㅈ게 텍스트 형태로 데이터를 읽어 변환(기본 인코딩 방식 -UTF-8)
# 응용 :
html에
<img id="outPut" >
를 넣어준다.
reader.onload에
var outPut = document.getElementById('outPut');
outPut.src = base64data;
를 추가한다.
(async () => {
const data = await fetch('https://cdn-icons-png.flaticon.com/512/29/29513.png');
const blob = await data.blob();
const reader = new FileReader();
reader.onload = () => {
const base64data = reader.result;
console.log("base64data ",base64data)
console.log("blob ",blob)
console.log("reader ",reader)
var outPut = document.getElementById('outPut');
outPut.src = base64data;
};
reader.readAsDataURL(blob); // base64 형태의 data url로 데이터를 읽어 변환
})();
# 결과 :
base64에 담겨진 이미지 파일 데이터 자체를 src에 넣어서 불러와진다. 이걸 url에다가 쓰면 마찬가지로 저 이미지가 나타남.
# blob ( Binary Large object )
주로 이미지, 오디오, 비디오와 같은 멀티미디어 파일 바이너리를 객체 형태로 저장한 것을 의미함.
멀티미디어 파일들은 대다수 용량이 큰 경우가 많기 때문에, 이를 데이터베이스에 효과적으로 저장하기 위해 고안된 자료형이라 볼 수 있음. (String 타입, number 타입이 있듯이 blob 타입이 있다고 생각하면됨).
예를 들어 데이터베이스에 이미지 파일을 그대로 데이터로 저장하고 싶을 때, 바로 blob 포맷으로 변환한 뒤 저장한 것.
브라우저 환경에서도 자바스크립트를 이용해 이러한 blob 데이터에 접근하고 사용할 수 있다. 주로 자바스크립트에서
텍스트, 이미지, 사운드, 비디오와 같은 멀티미디어 데이터를 다룰 때 사용함.
# base64와 다른점
1. base64는 바이너리 데이터를 다루기 위해 텍스트(문자열) 형태로 저장한 포맷.
2. blob이란 바이너리 데이터를 달기 위해 객체(Object) 저장하는 것.
base64는 문자열이 굉장히 길어져 가독성이 안좋을 뿐만 아니라, base64 이미지를 이곳저곳 여러개 사용할 경우 결과적으로 용량 문제로 인해 문서 자체를 로딩하는 데 많은 시간이 걸려서 느려지는 단점이 있으나,
blob 데이터는 적절하게 object url로 변환만 해주면 심플하게 브라우저에서 사용할 수 있다.
blob는 객체이기에 다양한 코드 활용성을 지니고 있어, base64로 변홯날 수 도 있고 buffer로도 변환할 수 있다.
# 방법
1.
(async () => {
const data = await fetch('https://cdn-icons-png.flaticon.com/512/29/29513.png');
const blob = await data.blob(); // 이미지 blob 객체 얻기
const url = URL.createObjectURL(blob);
const outPut5 = document.getElementById("outPut5");
console.log("blob ", blob);
console.log("url ", url);
outPut5.src = url;
})()
여기서 나온 src를 blob:http://localhost:9080/8f8313da-7453-40f8-a67c-1ff83cc9e9c4 상단에 url 검색 해보면
2.
base64 데이터를 blob으로 바꾸기 위해 중간 과정으로 arrayBuffer가 쓰임.
(async () => {
const imgUrl = getBase64FromImageUrl("/model/puppy.jpg");
console.log("test testtesttest testtesttest test", test);
})()
// bas64를 blob으로 변환해주는 함수
function b64toBlob(b64Data, contentType = '', sliceSize = 512) {
const image_data = atob(b64Data.split(',')[1]); // data:image/gif;base64 필요없으니 떼주고, base64 인코딩을 풀어준다
const arraybuffer = new ArrayBuffer(image_data.length);
const view = new Uint8Array(arraybuffer);
for (let i = 0; i < image_data.length; i++) {
view[i] = image_data.charCodeAt(i) & 0xff;
// charCodeAt() 메서드는 주어진 인덱스에 대한 UTF-16 코드를 나타내는 0부터 65535 사이의 정수를 반환
// 비트연산자 & 와 0xff(255) 값은 숫자를 양수로 표현하기 위한 설정
}
return new Blob([arraybuffer], { type: contentType });
}
// 이미지를 base64 url로 변경해주고(dataURL) 그것을 버퍼를 통해 Blob 만들어 주며 최종적으로 만들어진 url을 이미지에 뿌려주는 함수
function getBase64FromImageUrl(url) {
var img = new Image();
var output = document.getElementById('outPut3');
var output4 = document.getElementById('outPut4');
img.setAttribute('crossOrigin', 'anonymous');
const contentType = 'image/png';
img.onload = function () {
var canvas = document.createElement("canvas");
canvas.width =this.width;
canvas.height =this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
var dataURL = canvas.toDataURL("image/png");
console.log("dataURL",dataURL);
console.log("test", dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
output.src = dataURL;
const bufferAndBlob = b64toBlob(dataURL,contentType);
console.log("bufferAndBlob ", bufferAndBlob);
const url = URL.createObjectURL(bufferAndBlob);
};
img.src = url;
output4.src = url;
}
# 팁 :
팀원과 테스트를 했는데,
내가 보이는 곳에서 blob 파일의 url을 팀원에게 보내주고, 팀원이 호출 했을 땐, 호출 되지 않았음.
파일이 없거나 이미 삭제됐다는 문구가 나옴.
그렇지만 이 컨트롤 단, localhost:9090/viewer 쪽에 들어 왔을 땐 blob 파일이 정상적으로 잘 보였고, 그것을 url로 입력
했을 시에는 자기 자신에게는 잘 보였음. 로컬 및 인코딩에 연관 있을 것이다고 짐작함. 정확한 원인 모름.
base64의 경우엔 URL이 길지만, 팀원에게 보내줬을 때도, base64로 된 이미지 데이터 그 자체여서 그런지, 팀원이
url 입력 했을 때 그림이 잘 보여졌다.
구글에 돌아다니는 url 이미지 주소 및 로컬 서버에 있는 이미지로 두번 다 테스트를 진행하였고, 결과는 같았다.
blob로 된 url을 자기자신은 잘 보이지만, 팀원에게 보냈을 때, 호출 하지 못하는 이유는
blob url은 로컬 브라우저 메모리에 저장된 파일 데이터를 참조하는 url이라서 그런것.
이는 브라우저가 생성한 객체 URL로, 로컬 브라우저 섹션에서만 유효함.
blob://http://~ 과 같은 url은 특정 사용자의 브라우저 섹션에 종속적이기 때문에 다른 사용자나 다른 브라우저에서는 동일한 Blob url을 사용할 수 없다.
# 이로써 해결 방법(사용방법에 가까움)
1. 파일 업로드와 서버에 저장.
사용자가 업로드한 파일을 서버에 저장하여 Blob 데이터를 영구적으로 보관. (흔히 사용하는 방식을 써라는 뜻)
ex) D:// C:// 해당 폴더에서 Blob 동적 데이터로 만들어서 blob 데이터를 만들어서 사용 또는 그냥 그 파일 읽게끔 해서 사용.
2. 파일 경로만 DB 제공 또는 DB안의 파일 데이터를 blob(바이너리)로 저장.
로 사용하기.
'개발 > javascript & jquery' 카테고리의 다른 글
[Thymeleaf] th안의 item value에서 콘솔(console.log)값 보는법 (0) | 2024.03.25 |
---|---|
eq() 선택자 => $('#선택자').eq(0)의 정의 및 예제 (0) | 2024.02.23 |
[JavaScript] $(function(){})이란? (0) | 2023.01.02 |
thymeleaf에서 자바스크립트 인라인을 사용할 때 // 백단 부르기 (0) | 2022.11.10 |
fetch , then 내림차순 오름차순 (0) | 2022.11.08 |