[Cloudinary] client-side upload

mia·2023년 5월 25일
0

사용자가 사진을 직접 업로드하는 것은 생각보다 어려운 일이었다.
프로그램을 만들며 어려웠던 부분과 해결방안들을 적어보려고 한다.

1. 선택한 사진 파일 보여주기

input이니까 당연히 파일 경로도 e.target.value로 접근하면 될 것이라고 생각했다. 하지만 보안상의 문제로 fake path가 포함된 이상한 경로가 나왔다.

그렇다면 어떻게 해결을 해야할까..?
다행히 input에는 files라는 속성이 있다.

이제 img 태그에 src를 넣어주기 위해 필요한 메서드는 URL.createObjectURL()이다.

URL.createObjectURL()은 파일에 대한 임시 URL을 생성하여 해당 URL을 통해 파일에 접근할 수 있는 방법을 제공한다.

간단히 말해서, URL.createObjectURL()은 파일을 메모리에 저장하고 그에 대한 고유한 URL을 생성하는 것이다. 이 URL은 파일에 대한 참조를 나타내며, 이를 사용하여 이미지, 비디오, 오디오 등과 같은 미디어 파일을 로드하거나 표시할 수 있다.

URL.createObjectURL()을 사용하면 파일을 서버로 업로드하지 않고도 브라우저에서 파일을 로드하거나 표시할 수 있다. 이는 파일의 로컬 버전을 사용하여 미리보기를 제공하거나, 사용자가 선택한 이미지를 동적으로 변경하는 등 다양한 상황에서 유용하다.

다만 브라우저 정책상 해당 메서드를 통해 생성된 url은 로컬에서만 유효하기 때문에 서버에 파일을 업로드하고 다른 사용자와 공유하기 위해서는 이 메서드가 적절하지 않다.

하지만 일단 미리보기에는 아주 적절하기 때문에 해당 메서드를 사용했다.


export function Example() {
	const [file, setFile] = useState();

	const handleChange = (e) => {
		setFile(e.target.files[0])
	};
	
  	return (
    	<form>
      		<img src={URL.createObjectURL(file)} alt="img">
      		<input type="file" accpt="image/*" onChange={handleChange} />
      	</form>
    )
}

2. 사진 업로드하기

위에서 언급한 것과 같이 사진을 공유하기 위해서는 사진을 업로드하는 작업이 필요하다. 어딘가에 업로드 후 해당 url을 얻어 서버에 저장을 해주어야하는데 Cloudinary에서 client-side upload를 할 수 있다고 하여 사용해보았다.

cloudinary에 로그인하면 고유한 cloud name과 upload-preset을 얻을 수 있다.
REST API를 사용해 post로 사진을 업로드 하면된다.

export async function uploadCloudinary(file) {
	const url = "https://api.cloudinary.com/v1_1/<cloud name>/image/upload"

	const formData = new FormData();
	formData.append('file', file);
  	formData.append('upload_preset', //upload-preset);
    
    const url = await axios.post(url, formData).then(res => res.data.url)
	
  	return url;
}
  • FormData : 웹 폼(form) 데이터를 동적으로 생성하고 제출하는 데 사용된다. 이 객체를 사용하면 HTML 폼 요소의 값을 수집하여 HTTP 요청의 본문(body)에 포함시킬 수 있다. FormData를 사용하면 파일 업로드, AJAX 통신, 서버로 데이터 전송 등 다양한 작업을 수행할 수 있다.
    - append : form 데이터에 새로운 key-value 쌍을 추가해준다.

3. firebase에 업로드하기

마지막으로 firebase에 업로드해주면 끝이다.

// firebase.js

export function setNewProduct(product) {
	return set(ref(database, `products/${uuid()}`), product)
}
// products.jsx

const handleSubmit = () => {
	uploadCloudinary(file).then(imgUrl => {
    	const newProduct = {...product, imgUrl};
      	setNewProduct(newProduct);
    })
}

(참고) produts 파일에는 이미 product 객체가 state로 저장되어 있다.

profile
노 포기 킾고잉

0개의 댓글