React 에서 files 다루기

 

React 를 통해 파일 업로드 기능을 구현하기 위해 우리는 미리 알아야할 지식이 있습니다.

  • 첫 번째는 이미지와 비디오, 오디오 파일과 같은 파일이 어떻게 이루어져 있는 지를 알아야 합니다.
  • 두 번째는 input 태그의 type 이 file 일 때 미리보기 기능의 경우 올린 파일의 URL 객체의 createObjectURL 메소드를 이용하는 것
  • 세 번째는 React 의 useRef Hook 을 사용해 직접적으로 HTML 요소의 reference 값에 접근하는 법 입니다.

 

Blob 이란? 

우리가 웹에서 객체를 다룰 때 흔히 json 이라는 형식의 key, value 쌍으로 이루어진 형식으로 다루게 됩니다.

하지만 파일이나 영상 이미지와 같이 용량이 큰 파일은 어떯게 다루어야 할까요?? 

우리는 웹에서 이렇게 멀티미디어 데이터를 다룰 때 Blob 이라는 데이터 타입을 이용합니다. 

Blob 에는 데이터의 size 를 알아내거나 데이터 송 수신을 위해 더 작은 blob 객체로 나누는 등 다양한 범위에서 사용할 수 있습니다.

 

URL.createObjectURL

서비스에서 내가 올린 파일을 서버를 통해 전송하기 전 내가 올린 파일을 서비스내에서 직관적으로 확인하고 싶은 경우가 있습니다.

이 때 사용하는 것이 URL.createObjectURL 메소드 입니다. 이 메소드를 이용하면 내가 업로드한 파일의 url 을 만들어 줍니다.

단 이 때 만들어진 url 은 서버로 전송되는 것이 아니라 client 단에서 이용이 가능하다는 것입니다.

 

사용해보기

 

기본적으로 type 은 file 이라고 설정을 해야 합니다. 또한 accept 부분은 어떤 이미지 파일들만 허용할 것인지 정해주는 기능입니다.

multiple 은 여러개의 파일들을 선택할 수 있게 도와줍니다. 

이렇게 설정을 한 뒤에 useRef 를 통해 사용할 변수를 하나 설정해주고 내가 참조하고 싶은 HTML 요소에 ref 속성으로 주면 됩니다.

 

전체 코드

import React, { useRef, useState } from 'react';
import './App.css';

function App() {
  const [files, setFiles] = useState<File[] | null>(null);
  const fileRef = useRef<HTMLInputElement>(null);

  const fileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const fileList = e.target.files;
    
    if (fileList && fileList.length > 0) {
      setFiles(Array.from(fileList));
    }
  };

  const onSubmit = () => {
    fileRef.current?.click();
  };

  console.log(files);
  return (
    <div>
      <input
        type="file"
        accept="image/jpg, image/jpeg, image/png"
        ref={fileRef}
        onChange={fileUpload}
        multiple
      />
      <button onClick={onSubmit}>제출하기</button>
    </div>
  );
}

export default App;

 

위에 코드는 최종 코드 입니다. 기본적으로 TSX 를 사용하고 있기 때문에 타입 지정을 명확하게 해 주어야 오류가 나지 않으며

가져온 이미지 파일들을 files 라는 변수에 담아주고 console.log 로 찍어주면 밑에 사진처럼 나오게 됩니다.

 

 

 

이미지 확인해보기

 

이미지를 내가 원하는 대로 이름을 붙이고 size 를 줄이고 해당 이미지를 서버로 전송하기 전에 확인하고 싶다면

밑에 코드처럼 사용하면 됩니다.

 

import React, { useRef, useState } from 'react';
import './App.css';

interface FileDetail {
  name: string;
  size: string;
  type: string;
  url: string;
}

function App() {
  const [files, setFiles] = useState<FileDetail[] | null>(null);
  const fileRef = useRef<HTMLInputElement>(null);

  const fileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const fileList = e.target.files;

    if (fileList && fileList.length > 0) {
      const myFileList = Array.from(fileList).map((item, index) => {
        return {
          name: `item-${index}`,
          size: (item.size / (1024 * 1024)).toFixed(2) + 'mb',
          type: item.type,
          url: URL.createObjectURL(item),
        };
      });
      setFiles(myFileList);
    }
  };

  const onSubmit = () => {
    fileRef.current?.click();
  };

  console.log(files);
  return (
    <div>
      <input
        type="file"
        accept="image/jpg, image/jpeg, image/png"
        ref={fileRef}
        onChange={fileUpload}
        multiple
      />
      <button onClick={onSubmit}>제출하기</button>
      {files?.map((item) => (
        <img
          key={item.name}
          src={item.url}
          style={{ width: '200px', height: '200px' }}
        />
      ))}
    </div>
  );
}

export default App;

 

'React' 카테고리의 다른 글

React-throttle  (0) 2024.08.12
React-Debounce  (2) 2024.08.08
Axios  (0) 2024.07.28
React Redux  (0) 2024.07.10
useCallback  (0) 2024.05.03