웹 개발 포트폴리오 | 예적금 상품 비교 플랫폼
내일배움캠프 4기 웹 개발 과정 React 트랙 수료생 최종 프로젝트 '팁퍼'를 소개합니다.
Sep 04, 2023
4조 프로젝트 : 팁퍼 (Tipper)
금융관리 초보자를 위한 팁을 드려요!
자금 마련의 기본인 예금, 적금 상품들을 비교해주고 꿀팁들을 공유하는 사이트입니다.
기능 소개
- 예적금 상품 비교 기능 설명
- 상품검색
상품 명, 은행 명을 입력하여 해당 상품을 찾아볼 수 있음
- 2-3개의 상품 비교
상품들 중 2-3개를 골라서 상품들의 조건과 만기 수령액을 미리 예상해 볼 수 있음
예금, 적금 상품들 끼리만 비교가 가능
각 상품이 단리, 복리인지 판단하여 적용
최고금리를 적용한 최대 만기 수령액을 제시
- 상품 찜하기 기능 (로그인 필요)
아 본 상품들이 마음에 든다면 찜하기 버튼을 눌러서 저장 가능함
찜한 상품은 언제든 상품 비교할 때 다시 선택하여 다른 상품과 비교 가능
마이페이지에서도 모아볼 수 있음
- 커뮤니티 기능 설명
- 금융상품 후기, 금융관리 노하우 총 2개의 탭으로 구성
- 게시글 CRUD 기능 구현 - 이미지 업로드 가능
- 게시글에 좋아요 기능 구현
- 마이페이지에서 내가 쓴 글과 좋아요를 누른 게시글 확인 가능
🏗 아키텍쳐
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252F1b11605f-9eec-4672-8f5d-5d2a8d3a020e%252FUntitled.png%3Ftable%3Dblock%26id%3D85eabc82-69e4-49dd-9ea0-77e9b76523a4%26cache%3Dv2&w=3840&q=75)
🍀 주요 기술
- firebase
- axios
- vercel
- lodash
🛠 트러블슈팅
CORS에러로 인한 문제
- Cross-Origin Resource Sharing(교차 출처 리소스 공유 정책)
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252Fec34af08-6bb2-4c85-9e6d-ae72e88851bd%252FcorsError.png%3Ftable%3Dblock%26id%3Ddcfeddae-3ec3-406c-8c21-a96f23f35103%26cache%3Dv2&w=3840&q=75)
cors에러로 openAPI의 data를 가져오지 못함
✅ 해결
→ CORS 를 해결하기 위해서는 (서버 측)Origin Allow 속성에 클라이언트에서 보내는 출처를 추가해주어야 하고 또한 배포하는 AWS 같은 곳에서도 따로 설정을 해주어야 한다고한다.
→ 서버를 수정할 수도 없어 heroku-anywhere이라는 프록시서버 설정을 사용
https://cors-anywhere.herokuapp.com/https://finlife.fss.or.kr/finlifeapi/savingProductsSearch.json?auth=`${개인인증키}`&topFinGrpNo=020000&pageNo=1
아쉬웠던 점
- 리액트쿼리와 같이 실시간으로 데이터를 받아오는 경우 한번씩 연결 끊기거나 데이터를 받아오지 못하는 에러 발생
- 서버 연결 해주기 heroku에서 남용으로 인해서 버튼을 눌렀을때만 서버를 연결할 수 있도록 변경해두어서 서버가 끊기게 되면 데이터를 가져오지 못하는 상황 발생
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252Fbb1547b8-9db6-43df-bcc3-3a27f5939fab%252F%2525E1%252584%252589%2525E1%252585%2525B3%2525E1%252584%25258F%2525E1%252585%2525B3%2525E1%252584%252585%2525E1%252585%2525B5%2525E1%252586%2525AB%2525E1%252584%252589%2525E1%252585%2525A3%2525E1%252586%2525BA_2023-02-23_22.33.22.png%3Ftable%3Dblock%26id%3D55b55c6e-168f-4ab5-8361-98e59845cf5f%26cache%3Dv2&w=3840&q=75)
→위와 같은 사이트에 들어가서 서버 연결을 해줘야함
API 데이터 구조로 인한 문제
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252Fc767e208-8d04-416e-aa11-6db8b2ca6990%252Fbaselist05705.jpg%3Ftable%3Dblock%26id%3De308de7f-6f39-41ab-93c8-e968a4919457%26cache%3Dv2&w=3840&q=75)
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252F67839a1a-3849-4e26-8944-e02bdb5d6aee%252F05705.jpg%3Ftable%3Dblock%26id%3D0eb14f9b-8cf2-47b9-ab10-f246a2949436%26cache%3Dv2&w=3840&q=75)
- 한 상품에 대한 기본정보(BASE_LIST)와 금리에 대한 정보가 담긴 옵션 정보(OPTION_LIST)가 같이 저장되어 있지 않고 분리되어있음
✅ 해결
기본 정보를 기준으로 중복되는 속성값인 fin_prdt_cd가 같은 데이터를 옵션정보에서 찾아서 읽어옴
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252F3966a335-bb14-4958-88c6-9da7cc852efb%252Fcode4.png%3Ftable%3Dblock%26id%3Dd4f5a858-5b96-439f-a91d-574a087b6e86%26cache%3Dv2&w=3840&q=75)
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252Ff54effa7-b7a6-4ad1-84d9-ac1b7137ccaa%252Fcode5.png%3Ftable%3Dblock%26id%3D3d6c346c-6d86-4908-8fde-f39a6a64c548%26cache%3Dv2&w=3840&q=75)
코드 최적화 ( 상품 3개 선택후 비교 )
- 예금, 적금의 정보를 가져오는 함수를 각 2개씩 총 4개 생성(적금base, option / 예금base, option)
✅ 해결
→ Promiss.all() 메서드로 함수를 병렬실행
→ 전체 실행이 완료되면 한번에 모든 결과를 처리하도록 하여 최적화
- 2. 종류가 다른 3개의 배열로 선택된 금융상품의 상태 값을 각각 관리
✅ 해결
선택된 상품들의 정보를 하나의 배열에 순서대로 push함
//* 금융상품 리스트 가져오기 const handleButtonClick = async () => { const baseListPromises = [ getDocs(collection(db, "DEPOSIT_BASE_LIST")), getDocs(collection(db, "SAVING_BASE_LIST")), ]; const optionListPromises = [ getDocs(collection(db, "DEPOSIT_OPTION_LIST")), getDocs(collection(db, "SAVING_OPTION_LIST")), ]; const [baseListSnapshots, optionListSnapshots] = await Promise.all([ Promise.all(baseListPromises), Promise.all(optionListPromises), ]); const products = []; const depositOptionalList = []; const savingbaseList = []; const savingoptionalList = []; baseListSnapshots.forEach((snapshot, index) => { snapshot.forEach((doc) => { const newProduct = { id: doc.id, ...doc.data(), }; if (index === 0) { products.push(newProduct); } else { savingbaseList.push(newProduct); } }); }); optionListSnapshots.forEach((snapshot, index) => { snapshot.forEach((doc) => { const newProduct = { id: doc.id, ...doc.data(), }; if (index === 0) { depositOptionalList.push(newProduct); } else { savingoptionalList.push(newProduct); } }); }); setProducts(products); setdepositOptionalList(depositOptionalList); setSavingbaseList(savingbaseList); setSavingoptionalList(savingoptionalList); }; useEffect(() => { handleButtonClick(); }, []);
debounce처리 (lodash)
- 새 비밀번호 변경을 위해선 사용하고 있는 비밀번호를 입력하고 실시간으로 맞는지 유효성검사가 실행됨 (signInWithEmailAndPassword 메소드를 사용)
- 사용 이유 password input에서 onchange로 계속 값을 받고 있어서 signInWithEmailAndPassword메소드를 사용하는 것은 비효율적
✅ 해결
lodash에 debounce처리를 통해서 비밀번호 입력이 끝난 후 0.3초 후에 그때까지 입력된 값을 한번에 들고 한번만 함수가 실행
3번씩 호출하던 것에서 한번씩만 호출하는 것으로 효율성 높임
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252F57dbfc5d-07ef-449d-bf2b-8e3e944b8c67%252Fcarbon.png%3Ftable%3Dblock%26id%3Df6bf3f18-56e3-4014-97a4-43cdd75f844f%26cache%3Dv2&w=3840&q=75)
![왼쪽(debounce처리), 오른쪽 일반 onchange함수 실행](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252F6580fc8c-02e2-4de0-8795-1a29a8ae6b78%252F%2525E1%252584%252589%2525E1%252585%2525B3%2525E1%252584%25258F%2525E1%252585%2525B3%2525E1%252584%252585%2525E1%252585%2525B5%2525E1%252586%2525AB%2525E1%252584%252589%2525E1%252585%2525A3%2525E1%252586%2525BA_2023-03-08_11.45.21.png%3Ftable%3Dblock%26id%3D9655bede-bece-458d-b014-9eb15fd87198%26cache%3Dv2&w=3840&q=75)
**렌더링 되는 모습
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252Fa862c39e-1a70-47c5-986c-48fbd7866a1e%252F%2525E1%252584%25258E%2525E1%252585%2525AC%2525E1%252584%25258C%2525E1%252585%2525A5%2525E1%252586%2525A8%2525E1%252584%252592%2525E1%252585%2525AA_%2525E1%252584%25258C%2525E1%252585%2525A5%2525E1%252586%2525AB_AdobeExpress.gif%3Ftable%3Dblock%26id%3D009ef860-b3a6-460d-922c-dc82601fc8db%26cache%3Dv2&w=1080&q=75)
debounce처리 전 ⇒ 입력할 때 마다 렌더링
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252F2dc91989-aa3a-444e-b16b-7a3bdc4ad972%252F%2525E1%252584%25258E%2525E1%252585%2525AC%2525E1%252584%25258C%2525E1%252585%2525A5%2525E1%252586%2525A8%2525E1%252584%252592%2525E1%252585%2525AA_AdobeExpress.gif%3Ftable%3Dblock%26id%3Dec2122d0-e6e3-4d7c-8ec4-abf0ca451454%26cache%3Dv2&w=750&q=75)
debounce 처리 후 ⇒ 한번만 렌더링
🧑🏻💻👩🏻💻 팀원
이름(역할) | 맡은 업무와 기능수행 | Github |
남마리나(팀장) | 프로젝트 진행, 문서 제작, 기능 구현
상품비교 결과창, 커뮤니티 게시글 작성,수정 기능 구현 | |
박상우(부팀장) | 프로젝트 진행, 기능 구현
상품비교 조건 검색 기능, 랜딩 페이지 기능 구현 | |
김원준(팀원) | 기능 구현
상품비교 조건 검색 기능, 랜딩 페이지 기능 구현 | |
남동현(팀원) | 발표, 기능 구현
홈 UI 제작, 커뮤니티 게시글 불러오기, 삭제 기능 구현 | |
조성아(팀원) | 프로젝트 기능 구현 서포트, 기능 구현
상품명 검색하기 기능, 마이페이지 기능 구현 | |
안시은(팀원) | UX/UI 디자인 | ㅤ |
Share article
Subscribe to our newsletter