카드스터디 프로젝트 (진행중)
소개
카드스터디는 카드를 가지고 학습할 수 있는 웹사이트입니다.
카드의 앞 면에는 질문, 뒷 면에는 정답이 쓰여 있어 앞면을 보고 정답을 생각해낸 후 카드를 뒤집어서 답을 확인하는 방법으로 학습이 가능합니다.
자신이 직접 카드를 만들어 학습할 수 있고, 다른 사람이 만든 카드로도 학습이 가능합니다.
컴퓨터 공학 지식을 공부하던 중, 내가 필요한 내용만을 효율적으로 외우고 또 언제 어디서나 복습할 수 있는 서비스가 있으면 좋겠다는 생각이 들어 제작하게 되었습니다.
🔗 링크
Github: https://github.com/dlwhd990/CardStudy
배포 링크: https://card-study.vercel.app
🛠 사용 기술
React, Next.js, Typescript, Redux
MongoDB
Google OAuth (JWT)
👍 배우게 된 것들 & 느낀 점
Next.js를 사용하여 Pre-Rendering, Hydration, SSG에 대한 이해와 실제 구현을 경험 해보았고 SSG의 경우에는 페이지 소스를 확인하여 실제 적용 여부를 테스트 해보았습니다.
Redux-Toolkit의 useDispatch, useSelector를 사용하여 Props Drilling을 제거하였습니다.
비슷하지만 조금 다른 컴포넌트들을 따로 제작하는 것이 아니라 합성 컴포넌트를 제작하여 컴포넌트 재사용성을 높였습니다.
코드의 재사용을 줄이기 위해, 자주 사용되는 과정을 유틸 함수로 분리하고 import로 불러와서 사용하도록 하였습니다. 지난 프로젝트들에서는 같은 역할을 하는 함수들을 여러 컴포넌트에서 재선언하여 사용하는 경우가 많았는데 이런 문제점을 인식하여 이번 프로젝트에서 반영할 수 있었습니다.
자주 사용되는 객체들을 Type Alias로 타입을 정의하여 사용하고 Next.js의 useRouter query 등의 Union type을 갖는 프로퍼티들에는 Type guard를 사용하는 등의 방법으로 타입 불일치 문제를 없애고 개발 과정에서 실수로 일어난 오류를 빌드 과정에서 미리 알게되어 배포 전에 이를 수정하는 경험을 해보았습니다.
Intersection Observer를 사용하여 스크롤 위치에 따라 Element의 Style을 변경하였습니다.
next-seo를 사용하여 페이지마다 적절한 meta태그들을 적용시켜 보았습니다.
🤔 더 나은 서비스를 만들기 위한 노력
1. SSR vs SSG
카드 묶음 목록을 보여주는 페이지, 문제를 푸는 페이지는 웹사이트의 핵심적인 내용들(회원들이 만든 카드 묶음과 문제들)이 보이는 페이지 들입니다.
그렇기 때문에 추후에 검색 엔진을 통해 웹사이트가 노출되는 것 까지 대비하여, 이 페이지들은 ServerSide-Rendering(SSR) 또는 Static Page Generation(SSG)으로 만드는 것을 목표로 하였습니다.
이 페이지들은 사용자들이 카드 묶음을 생성하거나 문제를 생성 시 마다 변경 내용이 반영되어야 하기 때문에 SSR로 제작하는 것이 좋겠다고 생각하여 getServerSideProps를 사용하게 되었습니다.
하지만, vercel을 통해 배포를 하고 보니 이 페이지들의 평균 로드 속도는 약 4 ~ 4.5초정도였고, 이는 사용하기 매우 답답한 속도였습니다.
그래서 저는 해결 방법을 찾기 위해 Next.js의 공식 문서를 보게 되었습니다.
정리하자면 다음과 같습니다.
성능상 SSR보다 SSG를 추천한다.
CSR + SSG (즉 initial props가 있지만 사용하지 않고 SSG되는 것)을 사용하면 페이지의 일부 (데이터를 불러오지 않아도 되는 부분)은 빠르게 렌더링 될 것이다.
여기서 고민을 하게 되었습니다.
SEO를 포기하고 CSR로 할 것인지, 또는 변경사항이 즉시 반영되지 않더라도 SSG로 할 것인지 결정해야 했습니다.
결국 제가 내린 결론은 SSG였습니다.
잘 생각해보니 이 페이지들의 내용에 계속해서 변동이 일어날 수는 있지만, 그것이 항상 바로 반영 되어야 할 필요는 없다고 생각했기 때문입니다.
그래서 저는 getStaticProps를 사용하여 정적 파일을 빌드시에 생성하도록 하였고, revalidate 시간을 10으로 두어 어느 정도의 시간 뒤에는 정적 페이지가 재생성되어 변경 사항을 볼 수 있도록 하였습니다.
그 결과, 이렇게 놀라운 성능 향상(4310ms => 21ms)을 얻을 수 있었습니다.
2. 사용자 배려
사용자는 웹사이트와 상호작용을 해야 하는데, 웹사이트 측에서 아무런 피드백도 없다면 매우 답답할 것입니다.
예를 들어 1글자 닉네임으로 변경하려 하지만 웹사이트에서는 닉네임을 2글자 이상으로 제한 하는 경우, 사용자 입장에서는 '변경' 버튼을 눌러도 아무 일도 일어나지 않는다면 어떨까요? 어딘가에 오류가 발생했다고 생각하거나 기능 자체가 제대로 작동하지 않는 것이 아닌지 의심하는 등 좋지 않은 인상을 주게 될 가능성이 큽니다.
이것이 없어도 기능 상 문제가 되는 것은 아니지만, 제가 사용자의 입장에서 여러 웹사이트를 이용하며 좋지 않은 인상을 받은 적이 많기 때문에 자연스레 이런 점들에 신경을 쓰게 되었습니다.
이렇게 모바일 앱의 Toast Message와 같은 방식으로 몇 초간 알림 메세지를 띄우고 사라지는 팝업을 통해 사용자에게 사용자의 행동에 대한 피드백을 줄 수 있었습니다.
window의 alert를 사용할 수도 있겠지만, 확인 버튼을 누르지 않으면 화면이 멈추는 문제와 디자인이 마음에 들지 않는 이유로 따로 컴포넌트를 제작하여 사용하였습니다.
0개의 댓글