리액트에서 이미지 썸네일 미리보기 [TOY / Simple-SNS]

알락·2022년 11월 15일
0

Simple-SNS

목록 보기
2/9

진행 동기

Blob 이라고 하는 개념이 궁금했다. 과제 중 갑자기 툭 튀어나와서 "url로 바꾸면 보여요"라길래 허둥지둥 바꿔서 출력했더니 신기하게 이미지가 떴다. 하지만 아직 제대로 Blob을 알고있는 것은 아닌 것 같아 친해져보고자 진행하던 프로젝트에 적용해봤다.
현재 진행중인 '간단한 SNS 만들기' 프로젝트 주제가 SNS인 만큼 이미지 업로드는 중요하다. 특히 이번 구현은 클라이언트에서 이미지 업로드 요청을 보내기 전, 미리보기를 할 수 있는 기능까지만 구현했다.

Blob

Blob는 Binary Large Object 의 약자라고 한다.
사실 이미지를 업로드 할 때 내가 가장 먼저 확인하고 싶었던 것은 실체가 어떻게 전달되느냐였다. 기존에 HTML에서 input 태그를 통해 이미지를 업로드 할 때는 실체 확인이 힘들었다. 왜냐하면 input에 파일명이 뜨고, 같이 작성된 다른 input 들과 같이 하나의 form 형식으로 서버에 제출이되면 이미지도 알아서 넘어가 저장되었기 때문이다.
이제 Blob를 알고나서야 어떻게 이미지가 전해지는지 실마리를 얻게되었다.

[이미지 선정 후 input의 파일 접근]

사진을 올려놓은 input에 있는 파일에 직접 접근해봤다. 위와 같은 메타데이터가 나오는 것을 확인할 수 있다. 특히 객체명이 File로 지정된 것을 기억하자.
사실 File 객체는 javascript에서 제공하는 Blob 자료형을 쓰는 객체다. 결국 File도 Blob의 인터페이스를 사용하고 있는 것이다.
어느 정도 구현이 된 이후 Blob의 실체를 확인한 모습이다.

[Blob의 실체]

이 문자열이 이미지라니 정말 신기하다. 추후에 이렇게 변환된 문자열을 데이터베이스에 저장하는 형식으로 구현을 하려고 한다.

구현

[이미지 업로드 input 뷰]

<label className="btn-image-upload"/>
  <input type="file" className="image-upload-input" onChange={imageChangeHandler} accept=".jpeg, .jpg, .png, gif"/>
  <svg>
    <path/>
  </svg>
</label>

나는 뷰를 먼저 작성하는 편이라 업로드 input 먼저 설명하겠다. svg 태그가 섞여있는 이유는 input 폼 대신에 icon을 사용해보고 싶었기 때문이다. 하지만 icon을 클릭했을 때 input 작동 안 하는 문제를 해결해야했다. 이는 input과 icon을 다 함께 label태그로 감싸주는 방식으로 해결해주었다.

[이미지 업로드 핸들러]

const [image, setImage] = useState("");

const imageChangeHandler = async (e)=>{
        const filelist = e.target.files;
        const img = filelist[0];
        const reader = new FileReader();

        reader.onload = () => {
            setImage(reader.result);
        }

        reader.readAsDataURL(img);
        
    }

받아온 이미지 파일을 상태값으로 저장하려고 했다. input의 잠시 저장되어있는 이미지 파일에 접근하여 이미지를 얻어왔다. 그리고 FileReader라는 객체를 불러와 사용하였다.
FileReader는 클라이언트에서 파일을 이용할 때 필요한 인터페이스를 제공해준다. 특히 FileReader는 자체적으로 파일 관련한 이벤트를 가지고 있다. 나는 여기서 onload 이벤트를 사용해주어 파일이 불러와질 때, FileReader 내부적인 과정을 거친 이후의 결과값을 상태값에 저장하게 해주었다. FileReader에 파일을 넘겨주는 명령은 마지막줄에 작성되어 있다.

[이미지 미리보기 뷰]

{image ? 
    <div className="image-wrapper">
    	<img className="image" src={image}/>
   	</div> 
    : <></>
}

배운 것

  • 클라이언트에서 파일을 다루는 방법을 알 수 있었다.
  • Blob 을 통한 데이터 저장 방법을 알게 되었다.

참고

profile
블록체인 개발 공부 중입니다, 프로그래밍 공부합시다!

0개의 댓글