Blob 객체로 이미지 로드하기

1. React에서 이미지를 불러오기

React에서 네트워크 요청으로 이미지를 받아 화면에 나타내고자 할 때, 아래처럼 src에 직접 링크를 넣어 불러오도록 할 수 있음.

const Image = () => {
    return (
        <div>
            <img src="http://www.ex.com/1.jpg" alt="테스트 이미지" />
        </div>
    );
}

 이미지 용량이 크지 않을 경우, 이 방법도 문제가 없지만 이미지의 용량이 커지면 아래 사진처럼 이미지가 로드될 때까지 사용자는 빈 화면이나 잘린 이미지만 보게 되어 바람직하지 않음.

사용자는 잘린 이미지를 볼 수밖에 없음

이미지를 보여주는 컴포넌트가 App 컴포넌트 등 첫화면에 바로 보이는 컴포넌트라면 로딩 컴포넌트를 이용하는 방법이 있지만, Image 컴포넌트처럼 그것의 하위 컴포넌트라면 첫 화면에서 로딩, Image 컴포넌트를 렌더링하고 로딩하는 워터폴 문제가 발생함. 현재 Image 컴포넌트는 <img>에 src 속성으로 이미지 링크를 바로 넣었기 때문에 컴포넌트가 마운트되고 나서야 네트워크 요청이 이루어짐. Image 컴포넌트를 화면에 렌더링하기 전에 백그라운드에서 이미지를 미리 받아올 수 있다면 이러한 문제는 해결됨.

 

 

 

2. Blob 객체 이용하기

Blob은 미가공된 파일(File) 객체를 표현하는 객체로, Javascript에서 문자열, 배열, 객체 등이 아닌 형태의 데이터(ex. 이미지, 사운드, 동영상 등)를 표현하는데 사용될 수 있음.

const Image = ({ src }) => {  // 이미지 파일의 링크를 Props로 전달받음
    const [img, setImg] = useState(null);
    
    useEffect(() => {
        if (!src) return;

        (async () => {
            const res = await fetch(src);
            const imageBlob = await res.blob();  // 1. 응답 객체를 Blob 객체로 변환
            const imageObjectURL = URL.createObjectURL(imageBlob);  // 2. Blob 객체로 URL 생성

            setImg(imageObjectURL);
        })();
    }, []);

    return (/*  */);
};

우리가 Fetch API로 데이터를 받아올 때 Content-Type이 "application/json"이면 json() 메서드, "text/html"이면 text() 메서드를 이용해 Response 객체를 가공했던 것처럼, 그 외의 MIME 타입에 해당하는 메서드가 존재함. MIME 타입이 image라면 응답 body를 Blob 객체로 변환해줄 수 있는 blob() 메서드를 사용할 수 있음. blob() 메서드로 이미지를 Blob 객체로 변환했지만 Blob 객체를 바로 <img> 요소에 넣어줄 수는 없음. 이때, URL의 정적 메서드인 URL.createObjectURL()를 이용하면 <img> 요소의 src 속성에 넣을 수 있는 URL이 생성됨.

 

※ URL 객체는 문서가 종료되면 소멸하지만 그 전까지는 계속 메모리에 남아 있으므로 해당 URL 객체가 필요 없어지면 바로 URL.revokeObjectURL(Object의 URL)로 URL 객체를 제거해줘야 함에 주의!

Do I always need to call URL.revokeObjectURL() explicitly?

/* 이미지를 클릭했을 때 원본 이미지를 보여주는 컴포넌트 */
const ImageModal = ({ img }) => {
    return (
        <Modal>
            <img src={img} />
        </Modal>
    );
};

앞서 생성한 Blob 객체의 URL을 모달 컴포넌트에 넘겨 <img> 요소에 사용할 수 있도록 함. 

 

사용자는 더이상 이미지 로딩을 보지 않아도 됨

 

 

 

 

 

 

[참고]

Blob(블랍) 이해하기