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 |