1, 2번 둘 다 콜백함수를 처리하는 로직을 Promise로 감싸서 처리해주면 됩니다.
```
const getPreviewPhoto = async (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
}
reader.onerror = (error) => {
reject(error);
}
reader.readAsDataURL(file);
});
}
```
이렇게 Promise로 감싸주면 코드를 호출하는 곳에서 async/await로 파일을 받아올 수 있습니다.
에러 핸들링을 위해 onloadend 대신에 onload와 onerror를 사용했습니다. (onload와 onloadend의 차이는 onloadend는 성공/실패와 상관없이 호출되고, onload는 성공하는 경우에만 호출됩니다.)
```
const previewPhoto = await getPreviewPhoto(file);
```
만약 파일을 읽는 중에 에러 처리가 필요하다면 try/catch 로 감싸주는 작업이 필요합니다.
2번 질문도 동일합니다.
```
return new Promise((resolve, reject) => {
storageUploading.on(
'state_changed',
null,
(error) => { reject(error); },
() => {
storageUploading.snapshot.ref.getDownloadURL()
.then((url) => resolve(url))
.catch((error) => reject(error));
}
)
});
```
콜백 지옥, Promise 등의 키워드로 검색하면 참고하실 수 있는 글이 엄청 많이 나옵니다. 조금 더 나아가 이벤트 루프까지 공부하시면 나중에 면접에도 도움이 되실거에요.