Spring 6기 32조의 팀원 프로필 페이지를 개발하면서 Firebase Firestore를 이용해 데이터를 동적으로 불러오고, 사용자 입력을 저장하는 기능을 구현했다.
이 과정에서 팀원 목록, 프로젝트 관리, 문의하기 기능을 개발했으며, 진행 중 발생한 문제와 해결 방법도 함께 정리했다.
teamMembers
데이터를 불러와 프로필 페이지를 동적으로 생성 team.html?name=팀원이름
형태로 이동하여 개별 프로필을 보여줌 $(document).ready(async function () {
const querySnapshot = await getDocs(collection(db, 'teamMembers'));
querySnapshot.forEach((doc) => {
let data = doc.data();
let memberCard = `
<div class="col-md-4">
<div class="card shadow-sm text-center p-4">
<img src="${data.profileImage}" class="rounded-circle mx-auto d-block" width="150" height="150" alt="프로필 이미지">
<h4 class="mt-3 fw-bold">${data.name}</h4>
<p class="text-muted">${data.role ? data.role : '직책 미정'}</p>
<button class="btn btn-primary btn-sm"
style="padding: 6px 16px; font-size: 0.9rem; width: fit-content; min-width: unset; display: block; margin: 0 auto;"
token interpolation">${encodeURIComponent(data.name)}';">
자세히 보기
</button>
</div>
</div>
`;
$('#teamList').append(memberCard);
});
});
img
태그의 크기를 100px로 설정했더니 너무 작아 보였음. object-fit: cover;
을 추가하여 비율 유지 img.rounded-circle {
width: 150px;
height: 150px;
object-fit: cover;
}
projects
컬렉션에서 데이터를 가져와 프로젝트 리스트를 표시 $(document).ready(async function () {
const querySnapshot = await getDocs(collection(db, 'projects'));
let projectHTML = '';
querySnapshot.forEach((doc) => {
let data = doc.data();
projectHTML += `
<div class="feature col">
<h3 class="fs-2 text-body-emphasis">${data.title}</h3>
<p>${data.description}</p>
<a href="${data.link}" target="_blank" class="icon-link">
자세히 보기
<svg class="bi">
<use xlink:href="#chevron-right"></use>
</svg>
</a>
</div>
`;
});
$('#projectList').html(projectHTML);
});
import { addDoc, collection } from 'https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js';
document.getElementById('contactForm').addEventListener('submit', async function (event) {
event.preventDefault(); // 기본 폼 제출 방지
let email = document.getElementById('contactEmail').value.trim();
let message = document.getElementById('contactMessage').value.trim();
if (!email || !message) {
alert('❌ 이메일과 문의 내용을 입력해주세요.');
return;
}
try {
await addDoc(collection(db, 'inquiries'), {
email: email,
message: message,
timestamp: new Date()
});
alert('✅ 문의가 성공적으로 제출되었습니다.');
document.getElementById('contactForm').reset();
} catch (error) {
console.error('문의 저장 실패:', error);
alert('❌ 문의 제출 중 오류가 발생했습니다.');
}
});
reset()
메서드를 호출하여 폼 초기화 document.getElementById('contactForm').reset();
fetch
를 사용하여 Firebase에서 데이터를 요청 async function loadProjects() {
try {
let response = await fetch("https://us-central1-YOUR_PROJECT_ID.cloudfunctions.net/getProjects");
let projects = await response.json();
let projectHTML = '';
projects.forEach((data) => {
projectHTML += `
<div class="feature col">
<h3 class="fs-2 text-body-emphasis">${data.title}</h3>
<p>${data.description}</p>
<a href="${data.link}" target="_blank" class="icon-link">
자세히 보기
<svg class="bi">
<use xlink:href="#chevron-right"></use>
</svg>
</a>
</div>
`;
});
document.getElementById('projectList').innerHTML = projectHTML;
} catch (error) {
console.error("Error loading projects:", error);
}
}
// 페이지 로드 시 실행
loadProjects();
getDocs()
로 데이터를 직접 가져오면 클라이언트에서 Firestore를 수정할 가능성이 있음 fetch
를 통한 데이터 요청으로 변경 ✅ Firestore에서 데이터를 동적으로 가져와 렌더링하는 방법을 배웠다.
✅ Firebase를 직접 호출하는 것과 fetch
를 통한 API 요청 방식의 차이를 이해했다.
✅ 폼 제출 후 입력 필드를 초기화하는 방법을 적용했다.
✅ 프로필 페이지 UI를 개선하고, 가독성을 높였다.
이제 Firebase를 활용한 CRUD 구현을 더 발전시켜, 인증 기능도 추가할 수 있으면 좋겠다!
성공적인 결과물!