한국외대 Drop 랭킹
21-1학기 수강신청 취소 랭킹 https://hufs-drop.surge.sh
계기
저번 학기 컴퓨터 구조 수업이 너무 어려워서 20명의 학생이 드롭했다. 반토막 난 학생 수를 본 교수님의 당황한 표정이 인상 깊어서 만들게 됐다.
기술 스택
- React.js
- React-Table
- Recharts
- Evergreen UI
- No Backend
노 백엔드
백엔드가 없다.
서버 띄우기 귀찮아서 필요한 데이터는 미리 전처리해서 JSON 파일로 만들었다.
클라이언트에서 이 JSON 파일을 가져와서 필요한 데이터를 뽑아 쓴다.
데이터 수집
매일 밤 10시 수강취소 시간이 끝나고 수동으로 강의 크롤링을 했다.
크롤러를 FaaS에 올려서 크론을 돌리는 식으로 자동화했어야 했는데 너무 부지런했다.
데이터 전처리
타입스크립트와 lodash를 써서 전처리를 진행했다.
- 간단한 검증작업을 거친다. (강의 개수 등)
- 6일 치 강의 데이터를 같은 강의끼리 합친다.
unzip
사용 - 탈주자, 비율, 추세 같은 통계 자료를 추출한다.
- 각 캠퍼스 별로 분리한다.
- 각 강의별 캠퍼스 내의 랭킹을 구한다.
- 다시 합쳐서 JSON 파일로 만든다.
프론트엔드
페이지 구성
총 4개의 페이지로 구성된다.
- 홈
- 목록
- 검색
- 자세히 보기
홈
각 캠퍼스/과정 별 드롭 랭킹, 총 드롭수, 관짝으로 들어간 강의 목록을 보여준다.
물방울 모양의 로고는 Figma로 직접 만들었다.
목록
강의목록을 캠퍼스, 과정, 학과 별로 볼 수 있다.
테이블 구현
React-table
을 사용해서 테이블을 렌더링했다.
useTable
훅을 통해 페이지네이션, 정렬 로직을 바로 사용할 수 있어서 편하게 필수 기능을 구현했다.
뒤로가기/새로고침 페이지 상태 유지
다른 페이지에서 뒤로 가기 시 테이블로 보던 데이터를 유지하기 위해서
캠퍼스, 학과, 페이지 크기, 페이지 인덱스 정보를 변경 시마다 URL의 쿼리 파라미터에 업데이트했다.
검색
강의 목록을 강의명과 교수명으로 검색할 수 있다.
쿼리 디바운스
검색 시 3000개의 강의를 순차탐색한다.
매 키 입력마다 검색 기능이 실행되면 사용하지도 않을 데이터를 찾느라 CPU 타임을 낭비하면서 UI 쓰레드를 멈추게 한다.
입력과 검색에 사용되는 변수를 따로 둬서 텍스트 입력의 반응성은 유지하면서 검색은 필요할 때만 작동하게 했다.
- 쿼리 입력
- 0.5초 뒤 URL 파리미터 업데이트
- URL 파라미터 변경 감지한
useEffect
훅이 쿼리에 맞게 강의 필터링
자세히 보기
강의의 기본 정보와 일자별 탈출자, 등록현황을 볼 수 있다.
토스 증권의 기업 보기 UI를 따라 했다.
떨어지는 학생 수 그래프가 내 코인 그래프 같다.
교수명을 입력하면 검색 페이지로 넘어가서 해당 교수의 강의 목록을 볼 수 있다.
학교 커뮤니티 반응
힘든 수업에 대한 공감을 이끌어 낸 것 같다.
느낀 점
리액트 좋다. 특히 Hook API.
v-model
을 제외한 Vue.js의 기능이 Hook API로 제공돼서 기능 구현에 불편함이 없었다.
data
->useState
computed
->useMemo
watch
->useEffect
methods
->useCallback
$refs
->useRef
composition api
->useXXX
오히려 useEffect
는 변경을 탐지할 값을 한 번에 적을 수 있어서 Vue의 watch
보다 더 간편하다.
컴포넌트 분리는 어렵다.
공통으로 사용할 컴포넌트는 따로 분리해놓는다. (ex, 내비게이션 바)
그런데, 간단한 컴포넌트도 재활용이 생각만큼 잘 안 돼서 비슷하지만 조금씩 다른 컴포넌트를 다시 구현하게 된다.
컴포넌트가 여러 요구사항을 지원하도록 하다 보면 코드가 필요 이상으로 복잡해져서 그냥 따로 구현하는 게 나은 경우도 생긴다.
이 딜레마에서 벗어 날 수 있도록 아토믹 디자인을 수련해야겠다.