✍ 계기
집 근처 도서관에서 Clean Code 빌려 읽어내려가면서
내가 열심히 공부하고 써내려왔던 지난날의 코드들을 다시 생각해보게 되었다.
그것도 React를 막 배우고 어서빨리 사용해보고 싶어서 후다닥 만들어보았던 코드가 계속 밟혔다.
그래서 책을 잠시 덮고 내 코드를 살펴보게 되었고
생각보다 더 엉망이었다.
Clean Code에서 제안하는 방식으로 봐도 엉망이었고
무엇보다 코드의 퀄리티를 수정하기 전에 수정할 것들이 자꾸 눈에 밟혔다.
조금 더 React에 대해서 알게 된 현재의 내가 봐도 엉망이었다.
따라서 계획해두었던 새 웹은 잠시 미뤄두고 React로 만든 첫 웹인 Mbti 과몰입 테스트를 다시 뜯어보기로 했다.
🩰 디자인
처음으로 뜯어고친 부분은 디자인이었다.
이유
- 급박한 기능적인 문제가 발생하지는 않고 있었다.
- 디자인이 너무 보기 싫었다..
디자인에 소질이 너무 없어서 버튼모양이나 shadow는 codepen에 있는 소스를 참고했다.
결과
이 전 디자인은 초록색 바탕의.. 아무튼 정말 별로였다.
📥 FireBase 저장 방법 변경
이유
비효율적인 사용량
4 /16
- 읽기 : 4만
- 쓰기 : 23
이다.
쓰기 수 == 테스트 시행 수라는 것을 생각해보면 자그마치 4만이라는 읽기 수는 이해하기 어렵다.
다른 날을 보자
4 / 6
- 읽기 : 441
- 쓰기 : 1
왜 쓰기는 하나인데 읽기는 441번이지?
이유는 내가 만든 테스트 특성에 있다.
- 테스트를 끝낸 다음에 나와 같은 Mbti를 가진 사람들 중 이 결과가 나온 사람의 Mbti의 수를 보여주고
- 이 결과가 나온 상위 5개의 Mbti의 비율을 표로 만들어서 보여주었다.
=> 모든 문서를 읽어와 그 결과를 계산한다
이 때문에 테스트를 한번 시행할 때마다 기존의 모든 테스트 횟수만큼의 문서를 읽을 수밖에 없다.
그러나 이 문제는 다시 말해 트레픽이 조금이라도 몰리게 되면 상상하지도 못한 문서 양이 상상하지도 못한 속도로 증가한다는 것을 의미한다.
1명이 10개의 문서를 돌면서 읽으면 읽기 횟수는 10이 되지만
10명이 1000개의 문서를 돌면서 읽으면 읽기 횟수는 1000*10+10 이 되고 만다.
결과
firestore에서 난수로 저장되던 문서들을 하나의 문서 안의 배열로 옮겨담았다.
새로운 테스트 결과가 추가될 때 마다 배열의 마지막에 sync로 추가시켰다.
그 과정에서 now.Data()를 추가해 배열의 기존 값과 새롭게 들어오는 값이 중복되지 않게 했다.
다시 그래프를 보자
4 / 21
- 읽기 : 135
- 쓰기 : 50
이다.
그러나 아직 쓰기보다 읽기가 많은 이유는 찾지 못했다.😿
📊 top 5 막대
이유
특정 Mbti에게서 특정 결과가 많이 나오는 것도 아니고 수치를 보고 무언가를 판단할 수 있는 근거가 되지도 않을 것 같았다.
- 이 테스트에 참여하는 유저의 Mbti 비율이 일정하다면 근거 있는 수치가 되었을지도 모르지만 테스트 사용 유저의 Mbti 비율을 제어할 수 없다.
- 게다가 제어되지 않은 간단한 테스트 결과로 특정 Mbti에 대한 편견이 더 공고해진다면 이 테스트를 만든 의미가 왜곡될 수도 있다는 걱정이 있었다.
기존 화면
<graph.jsx>
const Graph = ({ point, mbti, pointRange, result }) => {
const [testArray, setTestArray] = useState([]); // 전체 test를 한 사람들의 모든 배열
const [sameRangeArr, setSameRangeArr] = useState([]);
const [sameMbtiArr, setSameMbtiArr] = useState([]);
const [topFiveArr, setTopFiveArr] = useState([]);
const [openRes, setOpenRes] = useState(false);
const getResultArrFromFireBase = async () => {
await onSnapshot(doc(db, "userResults", "resultArr"), (doc) => {
setTestArray((prev) => [...doc.data().resultArr]);
});
};
console.log(testArray);
const onClick = () => {
const sameRange = testArray.filter((res) => res.Range === pointRange); // 전체 test를 한 사람 중 같은 범위에 있는 사람들의 배열
setSameRangeArr(sameRange);
// showRank(sameRange);
const sameMbti = sameRange.filter((res) => res.mbti === mbti); // 현재 범위에 속한 사람 중 나와 MBTI가 같은 사람들의 배열
setSameMbtiArr(sameMbti);
setOpenRes(true);
// console.log(topFiveArr);
// console.log(topFiveArr[0]); // undefined. 순서문제가 발생하고 있다.
};
const sameRange = testArray.filter((res) => res.Range === pointRange); // 전체 test를 한 사람 중 같은 범위에 있는 사람들의 배열
// setSameRangeArr(sameRange);
// showRank(sameRange);
const sameMbti = sameRange.filter((res) => res.mbti === mbti); // 현재 범위에 속한 사람 중 나와 MBTI가 같은 사람들의 배열
// setSameMbtiArr(sameMbti);
// // 많이 나온 mbti를 5위까지 보여주기 위한 함수
// const showRank = (sameRange) => {
// let result = {};
// sameRange.forEach((rank) => {
// result[rank.mbti] = (result[rank.mbti] || 0) + 1;
// });
// let sortable = [];
// for (let mbti in result) {
// sortable.push([mbti, result[mbti]]);
// }
// sortable.sort((a, b) => {
// return a[1] - b[1];
// });
// // top5개의 mbti를 보여주기 위한 함수
// const rangeLength = sameRange.length;
// const topFive = sortable.slice(sortable.length - 5);
// topFive.map((per) => {
// return (per[1] = ((per[1] / rangeLength) * 100).toFixed(2));
// });
// console.log(topFive);
// setTopFiveArr(topFive);
// };
// const per = ((sameMbtiArr.length / sameRangeArr.length) * 100).toFixed(2);
const per = ((sameMbti.length / sameRange.length) * 100).toFixed(2);
useEffect(() => {
getResultArrFromFireBase();
}, []);
return (
<section className={styles.graph}>
{/* <button
className={`${styles.btn} ${styles.btn__primary}`}
onClick={onClick}
>
수치 보기
</button> */}
{/* {openRes && ( */}
<div className={styles.openedBox}>
<h2 className={styles.testProgress}>
지금까지 {testArray.length}명이 테스트를 진행했어요
</h2>
<div>
<h3 className={styles.testPer}>
{/* [{result}]<p className={styles.topFive}>top5</p> */}
{/* <GraphBar topFiveArr={topFiveArr} /> */}
</h3>
<h3 className={styles.myMbtiPer}>
{mbti}유형의 사람의 {per}%가 같은 결과를 얻었습니다
</h3>
</div>
<Share />
</div>
{/* )} */}
</section>
);
};
export default Graph;
이런 코드를 통해 만들었었다
코드를 짠 나조차도 다시 보고 싶지 않은 복잡, 중구난방인 코드다.
결과
눈에 보기에도 깔끔하고
- 테스트 인원 수
- 유저와 Mbti가 같은 사람들이 이 결과를 얼마나 얻었는지
에 대해서만 보여주었다.
고친 코드
<graph.jsx>
import React, { useEffect, useState } from "react";
import { doc, onSnapshot } from "firebase/firestore";
import { db } from "../../fireB";
import styles from "./graph.module.css";
import Share from "../share/share";
const Graph = ({ mbti, pointRange }) => {
const [testArray, setTestArray] = useState([]);
const [openRes, setOpenRes] = useState(false);
const getResultArrFromFireBase = async () => {
await onSnapshot(doc(db, "userResults", "resultArr"), (doc) => {
setTestArray((prev) => [...doc.data().resultArr]);
});
};
const sameRange = testArray.filter((res) => res.Range === pointRange);
const sameMbti = sameRange.filter((res) => res.mbti === mbti);
const per = ((sameMbti.length / sameRange.length) * 100).toFixed(2);
useEffect(() => {
getResultArrFromFireBase();
}, []);
return (
<section className={styles.dataContainer}>
<h2 className={styles.testProgress}>
지금까지 {testArray.length}명이 테스트를 진행했어요
</h2>
<h3 className={styles.myMbtiPer}>
{mbti}유형의 사람의 {per}%가 같은 결과를 얻었습니다
</h3>
<Share />
</section>
);
};
export default Graph;
🔗 Home이 아닌 다른 url로 링크되었을 때 오류가 나는 현상
이 내용은 오늘의 회고 글에 작성했다.
4. 결과 페이지로 링크됐을 때 바로 결과 페이지로 이동하기
🤨 원인
결과 페이지 뿐만 아니라 '/'을 제외한 모든 링크로 접속하면 오류가 생겼다.
막 React를 배우고 코드를 짤 시 useLocation으로 값이 전달되지 않으면 오류가 생긴다는 점을 간과하고 있었다.
🤔 고민
테스트를 위해 첫 페이지로 돌려야 하나 링크로 전달받은 페이지에서부터 시작하게 해야 하나 고민했다
1. 아주 짧고 간단한 테스트다.
2. 대부분은 테스트를 하기 위해 들어오지 이를테면 mbti 선택 창을 보기 위해 접속하는 것이 아닐 것이다
🥳 결과
외부에서 '/' 이외의 링크에 접속하면 바로 '/'로 이동가능하게 했다.
👓 리팩토링
리팩토링에 대한 내용은 대부분 '오늘의 회고' 글에 작성했다.
대략적인 내용은 이렇다
- 필요없는 코드 삭제
- 주석으로 달아놓았던 코드 삭제
- 딱 봤을 때 감이 오지 않는 함수나 변수명 교체
<q_mbti.jsx>
useEffect(() => {
if (point >= 10) {
setPointRange(1);
} else if (point > 3) {
setPointRange(2);
} else if (point >= -3) {
setPointRange(3);
} else if (point > -10) {
setPointRange(4);
} else {
setPointRange(5);
}
}, []);
useEffect(() => {
if (location.state === null) {
navigate("/");
}
}, []);
🤨 원인
함수의 역할을 한눈에 알기가 어려웠다
똑같이 로드될 때 함수를 불러오는 useEffect가 특별한 이유 없이 두 번 쓰였다.
🤔 고민
=> 함수를 이용해서 역할을 한눈에 알아보기 쉽게 만들면 처음 코드를 보는 사람도 빠르게 이해할 수 있을 것 같다
=> useEffect를 하나로 통일하는 것이 낫겠다.
const isAccecedOutsideLink = () => {
if (location.state === null) {
navigate("/");
}
};
const calcPointRange = () => {
if (point >= 10) {
setPointRange(1);
} else if (point > 3) {
setPointRange(2);
} else if (point >= -3) {
setPointRange(3);
} else if (point > -10) {
setPointRange(4);
} else {
setPointRange(5);
}
};
useEffect(() => {
isAccecedOutsideLink();
calcPointRange();
}, []);
🥳 결과
이렇게 리펙토링해서
=> 함수명을 보고 하는 일이 바로 유추될 수 있도록 하였고
=> 쓸데없이 useEffect를 두번 사용하지 않게 했다.
🎀 그 외
HashRouter을 BrowserRouter로 바꾸기
피드백을 통해 특정 기기에서 Home의 form이 한 쪽으로 쏠리는 현상 교정
🤨 원인
트위터에 웹을 올리고 많은 분들이 테스트해주면서 피드백해주셨다.
정말 정말 감사합니다!
그 중 한 피드백이 아이폰 12 미니에서 home 화면 버튼과 form 쏠림 현상이 나타난다는 피드백이었다.
분명히 크롬 개발자 모드로 볼 수 있는 모바일 화면들을 두루두루 확인했다고 생각했지만,
예상치 못한 피드백이었지만 문제의 원인을 빠르게 파악할 수 있던 피드백이었기 때문에 다행이라고 생각했다.
🥳 결과
home.module.css에서 form width를 90%로 설정하니 form이 제 자리를 찾았다.
'🤸♀️ 내 프로젝트 > MBTI 과몰입 테스트' 카테고리의 다른 글
MBTI 과몰입 테스트 (0) | 2022.01.14 |
---|