- 프로젝트명 : 푸드 나침반
- 프로젝트 소개 : 푸드 나침반은 "내가 찾는 맛집을 더 쉽게"라는 슬로건 아래, 개인의 취향을 기반으로 맛집 탐색 경험을 제공하는 서비스이다. 사용자는 지역별, 음식 카테고리별 맛집 정보를 지도를 활용하여 직관적으로 공유할 수 있다.
- 진행계기 : 광고 없는 나만의 찐맛집을 다른 사람들에게 알리고 다른 사람들의 맛집도 지역별로 또, 지도상으로 한눈에 볼 수 있는 서비스를 만들어보고자 진행
- 진행기간 : 24.09.12 ~ 24.09.23
시연 영상
담당 기능
- 장성현 (팀장) : 로그인 및 회원가입, 댓글 CRUD 및 페이지네이션, 날씨 API 활용
- 김경혜 (팀원) : 메인페이지 및 전체 레이아웃, 지도에서 주소 검색 및 마크 표시, 탭으로 게시글 필터링
- 유재희 (팀원) : 게시글 작성 및 수정페이지(이미지 업로드, 내용 입력, 음식 카테고리 선택 기능)
- 박민정 (팀원) : 마이 페이지(내 작성글 모아보기, 정보 수정), 유튜브 API 활용하여 카테고리별 동영상 불러오기
- 정희록 (팀원) : 게시글 상세 페이지 (게시글 삭제기능), 수정 페이지로 리다이렉션, 캐러셀 슬라이드 구현
주요 기능
기술 스택
트러블 슈팅
💣 문제 : 유튜브 API 요청이 하루 할당량이 정해져 있어 작업을 하다 보면 더 이상 영상을 불러오지 못하는 문제
- 해결 방법
- 관련 영상이 항상 새로울 필요는 없다고 판단하였고 요청 횟수를 줄여 비용을 절감하여 할당량이 너무 빨리 소진되지 않도록 staleTime을 적용
기존 코드⬇️
const {
data: videoData,
isPending,
isError,
refetch
} = useQuery({
queryKey: ['videos'],
queryFn: async () => {
const response = await axios.get(`https://www.googleapis.com/youtube/v3/search?
part=snippet&maxResults=3&type=video&videoEmbeddable=true&q=${keyword}&key=${key}`);
return response.data.items;
}
});
수정 코드⬇️
const {
data: videoData,
isPending,
isError,
refetch
} = useQuery({
queryKey: ['videos'],
queryFn: async () => {
const response = await axios.get(`https://www.googleapis.com/youtube/v3/search?
part=snippet&maxResults=3&type=video&videoEmbeddable=true&q=${keyword}&key=${key}`);
return response.data.items;
},
staleTime: 1000 * 60 * 60 // staleTime 1시간 설정
});
💣 문제 : 댓글을 불러오지 못하는 문제, 댓글 페이지네이션 기능에서 1페이지에서 2페이지로 넘어가도 1페이지에 해당하는 댓글들만 보이는 문제
문제 화면⬇️
에러 코드⬇️
// postId에 해당하는 댓글들 개수 가져오는 useQuery
const {
data: totalCommentsCount,
isLoading: isCountLoading,
isError: isCountError
} = useQuery({
queryKey: ['comments', postId, page],
queryFn: () => getCommentCount(postId)
});
const totalPages = Math.ceil(totalCommentsCount / limit);
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
// postId에 해당하는 댓글들 페이지처리 해서 가져오는 useQuery
const {
data: comments,
isLoading: isCommentLoading,
isError: isCommentError
} = useQuery({
queryKey: ['comments', postId, page],
queryFn: () => getComments(postId, page, limit)
});
- 원인
- 위 두개의 useQuery에서 같은 queryKey를 사용하고 있어 내 의도와 다르게 동작
- 위 두개의 useQuery의 queryKey가 같으면 **안 되는 이유
- 서로 다른 데이터가 캐시에 저장되면서 데이터 덮어쓰기 문제가 발생
- 캐시 무효화 시 의도하지 않은 쿼리가 다시 호출되고 성능 저하 유발
- 잘못된 데이터가 표시되거나, 댓글 목록이나 개수를 제대로 불러오지 못하는 오류 발생
- 해결 방법
- 두 useQuery는 서로 다른 데이터를 캐시하고 관리하는 용도이기 때문에 queryKey를 분리하는 것이 적절
수정 코드⬇️
// postId에 해당하는 댓글들 개수 가져오는 useQuery
const {
data: totalCommentsCount,
isLoading: isCountLoading,
isError: isCountError
} = useQuery({
queryKey: ['commentCount', postId],
queryFn: () => getCommentCount(postId)
});
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
// postId에 해당하는 댓글들 페이지처리 해서 가져오는 useQuery
const {
data: comments,
isLoading: isCommentLoading,
isError: isCommentError
} = useQuery({
queryKey: ['comments', postId, page],
queryFn: () => getComments(postId, page, limit)
});
수정 후 화면⬇️
💣 문제 : 게시글 업로드 시 파일을 선택했을 때 미리 보기가 되지 않는 문제
에러 코드⬇️
const handleChange = (e) => {
const { name, files } = e.target;
// 이미지 처리
if (name === 'image' && files.length > 0) {
const file = files[0];
// FileReader 생성
const reader = new FileReader();
setFormData((prev) => ({
...prev,
image: file
}));
reader.readAsDataURL(file);
reader.onloadend = function () {
const imgUrl = reader.result;
setImagePreview(imgUrl);
};
} else {
setFormData((prev) => ({
...prev,
[name]: e.target.value
}));
}
};
- 원인
- FileReader는 비동기적으로 파일을 읽는데, 파일이 완전히 읽히기 전에 상태를 먼저 업데이트하면서 문제가 생김
- 해결 방법
- 파일을 성공적으로 읽은 후에 상태 업데이트가 reader.onloadend 이벤트 내에서 호출되도록 수정
수정 코드⬇️
if (name === 'image' && files && files[0]) {
const file = files[0];
// FileReader 생성
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
const imgUrl = reader.result;
setImagePreview(imgUrl);
setFormData((prev) => ({
...prev,
image: imgUrl
}));
};
}
팀원 소감
- 장성현 : 외부 API를 사용하면서 공식문서나 reference를 분석하는 것이 어려웠지만 좋은 경험이었습니다.
- 김경혜 : 이번에 외부 API와 json-server를 깊게 알고 다루어야 하는 작업을 하면서 이에 대한 이해가 크게 상승한 것을 느꼈고, 내가 원하는 기능을 구현하려면 postData와 같은 연결되는 데이터나 활용 가능한 기능을 잘 이해해야 한다는 것을 알게 되었다.
- 유재희 : 게시글 작성 페이지를 맡으면서 데이터가 어떻게 저장되는지에 대한 구성도 중요하다는 것을 깨달았습니다. 게시글을 저장하고 필요할 때 쉽게 불러올 수 있도록 설계하는 과정이 유익했습니다! 프로젝트를 문제없이 마무리해 낸 조원들에게 감사드리고 모두 고생하셨습니다!!
- 박민정 : 데이터를 가져오고 활용하면서 axios, useQuery 등에 대한 이해도가 상승하였고, 외부데이터를 가져와서 사용하는 경험을 통해 보다 풍부하게 웹 사이트를 구현 할 수 있게 되어 아주 유익한 시간이었습니다. 또한 처음 배포를 해봄으로써 진행이 수월하지만은 못했지만 팀원분들과 함께 해결해 나가면서 협업의 가치 및 중요성을 배웠습니다 팀원분들께 감사드립니다
- 정희록 : 요번 프로젝트를 통해 외부 API와 서버에 대한 이해도가 깊어져서 정말 유익했다고 생각합니다. 또한 배포 과정 및 배포 후에도 오류가 많이 날 수 있다는 것을 경험했고 다음 프로젝트에는 QA기간을 더 늘리면 좋겠다는 생각을 했습니다. 마지막으로 끝까지 고생해준 팀원들에게 너무 감사드립니다.
'팀프로젝트' 카테고리의 다른 글
가취뽀 프로젝트 트러블슈팅 (2) | 2024.10.17 |
---|---|
가취뽀 프로젝트 - 1 (2) | 2024.10.10 |
food compass 프로젝트 트러블 슈팅 (0) | 2024.09.20 |
devnote 프로젝트 - 4 최종 (1) | 2024.09.04 |
devnote 프로젝트 - 3 (0) | 2024.09.03 |