[ 본캠프 3일차 기록 ]
🖥️ 오늘 공부한 내용 🖥️
팀프로젝트 진행 (Firebase)
1. 이미지 업로드 기능 구현
firebase storage로 이미지 업로드 구현
index.html
// 헤더 설정
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Firebase Image Upload</title>
// Firebase의 JavaScript SDK를 불러오는 스크립트 태그
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-storage.js"></script>
</head>
// 이미지 업로드 요소
<div class="imageUpload">
// 1번
<input type="file" class="inp" onchange="getImageData(event)" style="display: none;"/>
// 2번
<button onclick="selectImage()" class="selectImage">Select Images</button>
// 3번
<span class="filedata"></span>
// 4번
<div class="progressBar">
<div class="progress"></div>
</div>
// 5번
<button onclick="uploadImage()" class="upload">Upload</button>
// 6번
<span class="loading">Loading...</span>
// 7번
<img class="img" id="uploadedImage" />
</div>
1번
- input에 type을 file로 지정해서 파일 업로드 필드로 지정
- onChane 이벤트로 이미지 데이터 가져오는 함수(getImageData(event)) 호출
// 파일 선택 시 파일 데이터를 가져오는 함수
const getImageData = (e) => {
// 이벤트 객체에서 선택된 파일 가져옴
// "e.target.files"는 파일 input에서 선택된 파일들의 목록을 나타내는 객체
file = e.target.files[0];
// 파일 이름을 랜덤으로 생성하여 파일명 중복 방지
fileName = Math.round(Math.random() * 9999) + file.name;
// 파일 이름을 화면에 표시
// 파일이 선택되었다면, 파일 정보를 보여주는 요소인 FileData를 화면에 보여줘라
if (fileName) {
fileData.style.display = "block";
}
// fileData의 내용을 새로운 파일 이름으로 설정해줘라
fileData.innerHTML = fileName;
};
2번
- 이미지 선택 버튼
- onChane 이벤트로 이미지 선택하는 함수(selectImage())를 호출
// 이미지 선택 버튼을 클릭하면 파일 선택 input을 클릭하는 함수
const selectImage = () => {
// Js의 'click()' 메소드를 사용해서 파일 선택 input을 대신 클릭해줌
// 기존 input 버튼 대신 직접 만든 버튼이 같은 동작을 하도록 지정하는 작업
inp.click();
};
3번
4번
- progressBar : 업로드 진행 상황을 보여주는 진행바
- progress : 실제 진행 상황을 나타내는 바
5번
- 이미지 업로드 버튼
- input 필드로 가져온 이미지 데이터를 storage로 업로드하는 함수(uploadImage())를 호출


// 이미지를 firebase storage에 업로드하고, 그 과정에서 로딩 중임을 나타내는 함수
const uploadImage = () => {
// 로딩중임을 나타내는 요소 'loding'을 화면에 보이도록 스타일 지정 (1번의 block 부분과 유사)
loading.style.display = "block"; // 로딩 표시
// firebase storage에서 이미지를 저장할 위치를 설정
// "storage.ref()"는 firebase 스토리지의 루트 디렉토리를 나타냄
// "child("myimages")"는 "myimages"라는 디렉토리(폴더)를 생성하거나 참조 (위 사진 참고)
const storageRef = storage.ref().child("myimages");
// 업로드 할 이미지 파일에 대한 참조를 설정
// "myimages" 디렉토리 내에 "fileName"으로 가져온 파일명을 참조해 저장하기 위함 (위 사진 참고)
const folderRef = storageRef.child(fileName);
// 파일 업로드 작업을 생성
// "put()" 메소드는 파일 업로드하는 작업을 생성
// "file"은 업로드 할 이미지 파일을 가리킴
// "uploadtask"는 이 작업들을 나타내는 객체
const uploadtask = folderRef.put(file); // 파일 업로드 작업 생성
// 업로드 상태 변경 이벤트 (progress바에 대한 부분)
uploadtask.on(
"state_changed",
(snapshot) => {
progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; // 업로드 진행률 계산
progress = Math.round(progress); // 소수점 제거
progressbar.style.width = progress + "%"; // 프로그레스 바 업데이트
progressbar.innerHTML = progress + "%"; // 진행률 표시
uploadedFileName = snapshot.ref.name; // 업로드된 파일 이름 저장
},
(error) => {
console.log(error); // 에러 발생 시 콘솔에 로그 출력
},
() => {
// 업로드 완료 시 실행되는 콜백 함수
storage
// firebase storage에서 업로드된 이미지의 참조를 가져옴
// myimages : 이미지를 저장한 디렉토리
// uploadfiles : 업로드된 이미지 파일 이름
.ref("myimages")
.child(uploadedFileName)
// 이미지가 업로드된 후에 해당 이미지의 다운로드 URL을 가져오는 메소드
// 업로드된 이미지를 다시 다운로드할 때 사용
.getDownloadURL()
// Promise(외부 리소스 적근하는 작업)가 성공적으로 처리되면 실행되는 함수
// 이 함수는 이미지의 다운로드 URL을 매개변수 'url'로 받아와 처리
.then((url) => {
// 업로드된 이미지의 다운로드 URL을 로컬 스토리지에 저장
// 이를 통해 나중에 페이지를 새로고침해도 업로드된 이미지 다시 표시 가능
localStorage.setItem("uploadedImageUrl", url);
// 이미지 요소의 'src' 속성을 업로드된 이미지의 URL로 설정함
// 화면에 업로드된 이미지 표시
img.setAttribute("src", url); // 이미지 업데이트
// 이미지가 성공적으로 업로드되었으므로 로딩 중임을 나타내는 요소를 화면에서 숨김
loading.style.display = "none";
})
// 에러 발생 시 콘솔에 에러 메세지 출력
.catch((error) => {
console.error('Error getting download URL:', error);
});
}
);
};
6번
7번
8번
- 추가 코드
- 페이지 로드 시 local storage에서 이미지 URL을 가져와서 이미지 표시
// 페이지 로드될 때 발생하는 이벤트
window.onload = function() {
// localStorage에서 "uploadedImageUrl"이라는 키를 가진 데이터를 가져온다
// 이 데이터는 이미지의 URL을 포함
const uploadedImageUrl = localStorage.getItem("uploadedImageUrl");
// 가져온 이미지 URL이 존재한다면 실행된다
// localStorage에서 이미지 URL을 성공적으로 가져왔는지 확인
if (uploadedImageUrl) {
// 이미지 요소의 'src' 속성을 가져온 이미지 URL로 설정힌다
// 이미지가 화면에 표시되게 한다
img.setAttribute("src", uploadedImageUrl);
}
};
전체 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Firebase Image Upload</title>
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-storage.js"></script>
</head>
<body>
<div class="imageUpload">
<input type="file" class="inp" onchange="getImageData(event)" style="display: none;"/>
<button onclick="selectImage()" class="selectImage">Select Images</button>
<span class="filedata"></span>
<div class="progressBar">
<div class="progress"></div>
</div>
<button onclick="uploadImage()" class="upload">Upload</button>
<span class="loading">Loading...</span>
<img class="img" id="uploadedImage" />
</div>
<script>
const firebaseConfig = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
const app = firebase.initializeApp(firebaseConfig);
const storage = firebase.storage();
const inp = document.querySelector(".inp");
const progressbar = document.querySelector(".progress");
const img = document.querySelector(".img");
const fileData = document.querySelector(".filedata");
const loading = document.querySelector(".loading");
let file;
let fileName;
let progress;
let isLoading = false;
let uploadedFileName;
const selectImage = () => {
inp.click();
};
const getImageData = (e) => {
file = e.target.files[0];
fileName = Math.round(Math.random() * 9999) + file.name;
if (fileName) {
fileData.style.display = "block";
}
fileData.innerHTML = fileName;
};
const uploadImage = () => {
loading.style.display = "block";
const storageRef = storage.ref().child("myimages");
const folderRef = storageRef.child(fileName);
const uploadtask = folderRef.put(file);
uploadtask.on(
"state_changed",
(snapshot) => {
progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
progress = Math.round(progress);
progressbar.style.width = progress + "%";
progressbar.innerHTML = progress + "%";
uploadedFileName = snapshot.ref.name;
},
(error) => {
console.log(error);
},
() => {
storage
.ref("myimages")
.child(uploadedFileName)
.getDownloadURL()
.then((url) => {
localStorage.setItem("uploadedImageUrl", url);
img.setAttribute("src", url);
loading.style.display = "none";
})
.catch((error) => {
console.error('Error getting download URL:', error);
});
}
);
};
window.onload = function() {
const uploadedImageUrl = localStorage.getItem("uploadedImageUrl");
if (uploadedImageUrl) {
img.setAttribute("src", uploadedImageUrl);
}
};
</script>
</body>
</html>