이번 글에서는 React로 파일 업로드를 하는 방법을 알아보도록 하겠습니다. 저는 파일을 업로드하기 위해 AWS S3를 이용하였습니다. S3는 Simple Storage Service의 약자로 인터넷용 스토리지 서비스입니다. S3를 선택한 이유는 일반적인 파일 서버는 트래픽이 증가함에 따라서 장비를 증설하는 작업을 해야 하는데 S3는 이러한 작업을 대행해 줍니다. 트래픽에 따른 시스템적인 문제를 걱정할 필요가 없어지는 거죠. 또 접근 권한도 설정할 수 있어서 외부에서 사용하는 것도 방지할 수 있습니다. 이러한 S3에서 사용되는 주요 용어들은 다음과 같습니다.
- 객체(object), AWS는 S3에 저장된 각각의 데이터를 객체라고 명명하는데, 하나 하나의 파일이라고 생각하시면 됩니다.
- 버킷(bucket), 객체가 파일이라면 버킷은 연관된 객체들을 그룹핑한 최상위 디렉토리라고 할 수 있습니다. 버킷 단위로 사용 지역을 지정할 수 있고, 또 버킷에 포함된 모든 객체에 대해서 일괄적으로 인증과 접속 제한을 걸 수 있습니다.
- 버전관리, S3에 저장된 객체들의 변화를 저장합니다. 예를들어, A라는 객체를 사용자가 삭제하거나 변경해도 각각의 변화를 모두 기록하기 때문에 실수를 만회할 수 있습니다.
S3를 이용해서 파일을 업로드하는 프로세스는 클라이언트에서 S3에 파일을 업로드하고 S3에 저장된 파일을 클라이언트에서 사용해야 하면 URL 객체로 불러와서 사용할 수 있습니다.
S3를 이용하기 위해서는 먼저 AWS에 가입하시고 버킷이라는 것을 생성해주셔야 합니다. 버킷을 생성하는 방법은 이 포스트에서 다루지 않겠습니다. 버킷을 생성하시고 다시 이 포스팅으로 넘어와 주세요.
[파일 불러오기]
먼저 파일 업로드하는 input 태그부터 코드를 보시면 아래와 같습니다. 저는 이미지 파일만을 업로드하여서 확장자를 걸었고, 파일 리더 생성자로 업로드한 파일을 읽어 불러왔습니다. 그리고 이미지 미리 보기를 위해 imageSrc에 파일 경로를 저장해 두었고, imageFile에는 나중에 S3로 보낼 파일 데이터를 저장해 두었습니다. 여기서는 이미지 미리 보기는 다루지 않을 거지만, 이미지 미리 보기에 관심이 있으신 분들을 위해 하단에 작업했던 링크 걸어두겠습니다.
const [imageFile, setImageFile]: any = useState(null);
const [imageSrc, setImageSrc]: any = useState(null);
const FormImageFile = () => {
const onUpload = (e: any) => {
const file = e.target.files[0];
const fileExt = file.name.split('.').pop();
// 확장자 제한
if (!['jpeg', 'png', 'jpg', 'JPG', 'PNG', 'JPEG'].includes(fileExt)) {
ons.alert('jpg, png, jpg 파일만 업로드가 가능합니다.');
return;
}
// 파일 리더
const reader = new FileReader();
reader.readAsDataURL(file);
// 파일 업로드
return new Promise<void>((resolve) => {
reader.onload = () => {
// 이미지 경로 선언
setImageSrc(reader.result || null);
// 이미지 파일 선언
setImageFile(file);
resolve();
};
});
}
return (
<input hidden
accept="image/*"
multiple
type="file"
ref={el => (inputRef.current[0] = el)}
onChange={e => onUpload(e)}
/>
)
}
[S3에 파일 업로드하기]
헷갈리실수도 있으실 것 같아 미리 말씀드리자면, 위의 input 태그와 아래 코드는 하나의 jsx에서 작성한 코드들입니다. 분리하여 설명하고자 구분했다는 것을 말씀드립니다. 아래 코드와 같이 본인이 S3에서 설정한 버킷, 계정 키 등을 설정하여 S3 Upload 생성자를 만들어 파일 폼을 보내주면 정상적으로 업로드됩니다.
// npm i aws-sdk
// yarn add aws-sdk
import AWS from "aws-sdk";
const BtnUpload = () => {
const uploadS3 = (formData: any) => {
const REGION = process.env.REACT_APP_REGION
const ACESS_KEY_ID = process.env.REACT_APP_ACCESS_KEY_ID
const SECRET_ACESS_KEY_ID = process.env.REACT_APP_SECRET_ACCESS_KEY_ID
AWS.config.update({
region: REGION,
accessKeyId: ACESS_KEY_ID,
secretAccessKey: SECRET_ACESS_KEY_ID,
});
const upload = new AWS.S3.ManagedUpload({
params: {
ACL: 'public-read',
Bucket: '버킷명',
Key: `upload/${imageFile.name}`,
Body: imageFile,
}
})
upload.promise()
.then(
console.log('업로드')
)
}
return(
<FormImageFile/>
<button type="button"
onClick={() => {
if (!imageSrc) {
ons.alert('이미지를 등록해 주세요.');
return;
}
const formData = new FormData();
formData.append('file', imageFile);
formData.append('name', imageFile.name);
uploadS3(formData);
}}
>업로드!</button>
)
}
버킷의 객체 안에 업로드한 파일이 들어간 것을 확인하실 수 있습니다.
References
'1. 웹개발 > 1_1_5 React JS' 카테고리의 다른 글
[React] React Query를 사용하는 이유 (vs Redux) (0) | 2023.12.14 |
---|---|
[React] 카카오 로그인 구현하는 방법 (0) | 2023.05.22 |
[React] useRef() 여러 개를 한 개로 관리하기 (2) | 2023.02.02 |
[React] 파일업로드 이미지 미리보기 구현하기 (1) | 2023.01.28 |
[React] MySQL, Node.js 연동하여 Insert, Update, Delete 구현하기 (0) | 2023.01.15 |