프론트엔드 웹/React

REACT 웹에서 S3로 이미지 올리기 (3) _ React code

세리둥절 2022. 6. 21. 23:08
반응형

이제 AWS에서 S3와 IAM 설정이 끝났으니 React에서 코드를 만들어보자.
처음으로 aws-sdk를 프로젝트에 설치해준다

npm install aws-sdk


Input 태그에서 type을 'file'로 선택하면 파일을 받을 수 있는데 이 때 accept를 'image/*'로 설정하면 image만 골라서 받을 수 있다.
CSS는 tailwindCSS Version3 를 활용했다

interface Props {
	setImage: any
	inputRef: any
}

const InputImage = ({ setImage, inputRef }: Props) => {
	const handleFileInput = (e: any) => {
		const file = e.target.files[0]
		setImage(file)
	}

	return (
		<input
			className="block w-full text-sm text-slate-500
			file:mr-4 file:py-2 file:px-4 
			mb-2 file:rounded-full file:border-0 file:text-sm file:font-semibold
			file:bg-gray-60 file:text-blue-100"
			type={'file'}
			accept={'image/*'}
			onChange={handleFileInput}
			ref={inputRef}
		/>
	)
}

export default InputImage



그 다음에 AWS에 S3에 이미지를 업로드하는 함수를 설정하는데
IAM 설정할 때 외부에 저장해두었던
AWS-ACCESS-KEY와 SECRET-ACCESS-KEY를 여기에 지정해준다.

그럼 해당 user가 S3에 Full Access할 수 있는 권한을 얻게 된다.

import AWS from 'aws-sdk'

/* AWS 설정 */
const ACCESS_KEY = 'AWS_ACCESS_KEY'
const SECRET_ACCESS_KEY = 'AWS_SECRET_ACCESS_KEY'
const REGION = 'ap-northeast-2'
const S3_BUCKET = 'AWS에서 만든 S3 BUCKET 이름'
const FOLDER_NAME = 'AWS bucket에 만들 folder 이름'

AWS.config.update({
	accessKeyId: ACCESS_KEY,
	secretAccessKey: SECRET_ACCESS_KEY,
})

const myBucket = new AWS.S3({
	params: { Bucket: S3_BUCKET },
	region: REGION,
})

export const uploadImageFile = (image: any, setImage: any) => {
	const params = {
		ACL: 'public-read',
		Body: image,
		Bucket: S3_BUCKET,
		Key: FOLDER_NAME + '/' + image.name,
	}

	myBucket
		.putObject(params)
		.on('httpUploadProgress', (evt: any) => {
			setTimeout(() => {
				setImage(null)
			}, 3000)
		})
		.send((err) => {
			if (err) console.log('image upload error', err)
		})
}



그리고 위에서 만들었던 함수와 컴포넌트들을 import 해서 아래와 같이 구성해준다. ref를 활용해서 업로드를 끝낸 파일을 초기화시켜주었다.

import InputImage from './InputImage'
import SubmitButton from './SubmitButton'
import { uploadImageFile } from './utils'

const UploadImage = () => {

	const [loading, setLoading] = useState<boolean>(false)
	const [image, setImage] = useState<any>(null)

	// Image Input 값을 초기화
	const inputImageRef = useRef<any>(null)
	const onClearInput = () => {
		inputImageRef.current.value = ''
	}
    
    // 제출버튼을 클릭했을 때
	const onClick = async () => {
		try {
			setLoading(true)
			await uploadImageFile(image, setImage)
			alert('피드백 전송을 성공했습니다.')
		} catch (e) {
			alert('피드백 전송에 실패했습니다.')
		} finally {
			setLoading(false)
            		onClearInput()
		}
	}

	return (
		<div>
			<InputImage setImage={setImage} inputRef={inputImageRef} />
			<div className="flex justify-end">
				<SubmitButton onClick={onClick} loading={loading} />
			</div>
		</div>
	)
}


반응형