팀원 소개 페이지를 개발하면서 저는 다음의 기능을 구현하고자 했습니다.
1. 로컬 PC에 있는 이미지를 웹 페이지에 업로드 시키면 이미지명을 uuid로 변환
2. Firebase Blob Storage로 이미지 업로드 및 이미지 다운로드 URL 응답 받아오기
3. 응답 받아온 URL을 NoSQL 데이터베이스에 Input
4. 데이터베이스에서 정보를 불러와 웹에 이미지 카드 형식으로 추가
처음 HTTP, CSS, Javascript를 사용해서 프로젝트를 진행하다보니 많은 문제들에 맞닥뜨리게 됐는데 그 중에서 2가지가 에러를 해결하는데 많은 시간을 소요됐습니다.
1. Storage Download URL 메서드를 실행했을 때 Promise Rejected 발생
2. try ~ catch 구문을 통한 예외 처리
이번에는 위 오류를 어떻게 해결했는지 정리해보도록 하겠습니다.
Promise Rejected 발생
다음 코드는 처음에 작성한 코드 버전 입니다.
Firebase SDK는 다음 링크를 참고했습니다.
아래 코드로 작성 했을 때 Promise Rejected 에러가 발생했음을 콘솔 로그를 통해 확인할 수 있었습니다.
// 2.Firebase Blob Storage로 이미지 업로드 및 다운로드 URL 가져오기
try {
// try 구문 안에서 에러가 발생하면 catch 구문으로 이동
// renameFile 변수를 rename으로 변경 후 에러를 일으키면 catch 구문으로 이동
const snapshot = uploadBytes(storageRef, renameFile);
console.log('Uploaded a blob', snapshot);
//업로드가 완료된 후 URL을 가져오기
url = getDownloadURL(storageRef);
console.log('File available at', url);
} catch (error) {
alert('파일 업로드 중 오류가 발생했습니다.');
console.error(error);
}
이는 다음의 과정을 거쳐 문제를 해결해 나갔습니다.
1. Promise가 무엇인가를 확인
우선 JS는 비동기 처리라는 특성을 가지고 있다는 것을 알게 되었습니다. 비동기 처리란 특정 코드의 실행이 끝날 때까지 기다려주지 않고 다음 코드를 실행하는 것을 말합니다. promise란 주로 서버에서 데이터를 화면에 표시할 때 사용하는 객체로 비동기 작업의 완료를 추적할 수 있도록 도와주는 객체 입니다. 즉 JS는 코드가 쭉 실행되더라도 promise가 아직 실행 중인 코드를 계속해서 추적한다는 개념으로 이해했습니다.
2. Promise Rejected는 어떤 상태인가
storage의 이미지 다운로드 URL을 가져오는 메서드를 실행했을 때 그 결과값으로 promise 객체가 반환되는 것을 콘솔 로그로 확인, 이 때 오류가 발생하는 것으로 추정 했습니다.
비동기 처리라는 개념과 promise 객체를 연관지어 혹시 업로드 후 URL을 받아와야 하는데 JS에서 이를 기다리지 않고 다음 코드가 실행되어 발생하는 에러가 아닐까 생각하였고 이를 해결할 수 있는 방법을 찾아보니 이미지 다운로드 URL을 받아올 때 까지 기다릴 수 있도록 async, await 예약어를 추가하니 정상 작동했습니다.
그 후 다음과 같이 코드를 수정하니 정상적으로 Storage에서 이미지 다운로드 URL을 fulfilled로 받아왔습니다.
// 2.Firebase Blob Storage로 이미지 업로드 및 다운로드 URL 가져오기
try {
// try 구문 안에서 에러가 발생하면 catch 구문으로 이동
// renameFile 변수를 rename으로 변경 후 에러를 일으키면 catch 구문으로 이동
const snapshot = await uploadBytes(storageRef, renameFile);
console.log('Uploaded a blob', snapshot);
//업로드가 완료된 후 URL을 가져오기
url = await getDownloadURL(storageRef);
console.log('File available at', url);
} catch (error) {
alert('파일 업로드 중 오류가 발생했습니다.');
console.error(error);
}
try ~ catch 구문을 통한 예외 처리
처음 예외 처리 방향성은 스토리지에 이미지를 업로드 또는 다운로드가 제대로 작동하지 못할 경우 "파일 업로드 중 오류가 발생했습니다." 라는 alert이 뜨도록 하는 것이였습니다.
에러 구문을 테스트 하기 위해 강제로 getDownloadURL() 함수 앞에 await을 강제로 삭제했습니다. 그 이유는 await을 삭제하게 되면 'Promise rejected'가 발생할 것이고 이를 통해 에러를 일으킬 수 있다고 생각했습니다.
// 2.Firebase Blob Storage로 이미지 업로드 및 다운로드 URL 가져오기
try {
// try 구문 안에서 에러가 발생하면 catch 구문으로 이동
// renameFile 변수를 rename으로 변경 후 에러를 일으키면 catch 구문으로 이동
const snapshot = await uploadBytes(storageRef, renameFile);
console.log('Uploaded a blob', snapshot);
//업로드가 완료된 후 URL을 가져오기
url = getDownloadURL(storageRef);
console.log('File available at', url);
} catch (error) {
alert('파일 업로드 중 오류가 발생했습니다.');
console.error(error);
}
하지만 catch 구문은 실행되지 않았습니다. 그에 따라 Javascript의 try ~ catch 구문을 다시 공부하였고 다음의 사실을 알게 되었습니다.
Promise 객체에 대해서는 await 구문을 사용하지 않는 경우, 에러가 발생해도 catch 블록으로 코드의 실행 흐름이 이동하지 않는다는 사실!
그에 따라 다시 코드를 롤백하고 Error 객체를 생성해서 던지는 방식으로 테스트를 진행하였습니다. 이를 통해 에러를 강제로 일으키는 방법, 에러 처리 방법도 동기, 비동기 방식 또는 Promise 객체인 경우마다 다르다는 것을 알게 되었습니다.
// 2.Firebase Blob Storage로 이미지 업로드 및 다운로드 URL 가져오기
try {
// try 구문 안에서 에러가 발생하면 catch 구문으로 이동
throw new Error('에러!');
const snapshot = await uploadBytes(storageRef, renameFile);
console.log('Uploaded a blob', snapshot);
//업로드가 완료된 후 URL을 가져오기
url = await getDownloadURL(storageRef);
console.log('File available at', url);
} catch (error) {
alert('파일 업로드 중 오류가 발생했습니다.');
console.error(error);
}
참고 링크
예외 처리
Javascript에는 예외 처리(Exception Handling)를 통해 코드 실행 중에 예기치 못한 에러가 발생했을 때, 이로부터 코드의 실행 흐름을 복구할 수 있는 기능이 포함되어 있다. 1. 동기식 코드에서의 예외
worldcenter96.tistory.com
Promise 객체
Promise 가 뭔가요?프로미스는 자바스크립트 비동기 처리에 사용되는 객체 입니다. 프로미스는 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용합니다. 일반적으로 웹 애플리케이션을 구현
worldcenter96.tistory.com
'Frontend > Javascript' 카테고리의 다른 글
[Javascript] async와 await (0) | 2024.08.30 |
---|---|
[Javascript] Promise 객체 (0) | 2024.08.30 |
[Javascript] 비동기 처리와 콜백 함수 (3) | 2024.08.30 |
[Javascript] 예외 처리 (0) | 2024.08.30 |
[Javascript] fetch 적용하기 (0) | 2024.08.12 |