오늘은 카테고리 별 심리테스트 보여주기를 해볼 것이다. 규모가 큰, 백엔드 개발자 분들과 함께한 프로젝트였다면 카테고리를 누를 때마다 서로 다른 url로 요청이 가는 식으로 처리가 되었을텐데, 지금은 연습하는 토이프로젝트이니 전체 테스트 리스트에서 filter 처리를 해주는 방식으로 구현하였다.
원래는 Layout 컴포넌트에 헤더와 네비게이션 바 컴포넌트를 모두 넣었다가 index.js에서 카테고리 관련 state 관리를 해주기 위해 뺐다. 사실 그냥 Layout 컴포넌트에 있었어도 상관은 없었을텐데, 테스트 중일 때는 헤더만 보이는게 나을 것 같기도하고.. 해서 그냥 빼줬다.
// layout.js
import Header from "./header";
import Head from "next/head";
export default function Layout(props) {
return (
<div className="flex flex-col h-screen">
<Head>
<title>psy-test</title>
<meta name="description" content="What is today's psycology test?" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Header className="sticky top-0" handleReset={props.handleReset} />
<div className="flex-1 overflow-auto">{props.children}</div>
</div>
);
}
index.js에 두 개의 상태를 만들어줬다. 그리고 상태 끌어올리기를 통해 카테고리가 바뀌면 filter를 해주거나 헤더가 클릭되면 전체 리스트를 보여주는 식으로 처리해주었다.
// index.js
export default function Home({ lists }) {
const [category, setCategory] = useState("");
const [isClicked, setIsClicked] = useState(false);
const [reset, setReset] = useState(false);
const [testList, setTestList] = useState(lists);
useEffect(() => {
if (isClicked) {
setTestList(lists.filter((el) => el.category === category));
setIsClicked(!isClicked);
}
}, [isClicked]);
useEffect(() => {
if (reset) {
setTestList(lists);
setReset(false);
}
}, [reset]);
return (
<Layout handleReset={setReset}>
<NavBar
className="sticky top-0"
changeCategory={setCategory}
handleClick={setIsClicked}
/>
{testList.length ? (
<TestList testList={testList} />
) : (
<div className="flex flex-col items-center justify-center my-28">
<div className="text-2xl font-bold text-gray-400">
아직 준비된 테스트가 없습니다.
</div>
</div>
)}
</Layout>
);
}
[testId] 의 index.js, 즉 테스트 중 일 때도 헤더를 누르면 전체 리스트를 볼 수 있도록 적용하였다.
추가적으로, 테스트 아이템 컴포넌트가 눌리면 확대되어보이는 효과는 다음과 같은 코드를 추가해주어 적용하였다.
<div
className="col-span-6 md:col-span-4 lg:col-span-3 w-full bg-purple-200 cursor-pointer transition duration-200
ease-in transform sm:hover:scale-105 hover:z-50"
onClick={handleShowDetails}
>
확대 효과 코드 참고한 블로그)
https://garve32.tistory.com/37
이제 왠만한 주요 기능은 구현이 완료된 것 같다. 매일 하루에 자기 전 1~2시간 정도 개발했던 것 같고, 총 개발 기간은 정말 넉넉 잡아2주 정도 소요되었던 것 같다. 사실 Styled-Components로 만들었으면 거짓말 보태서 하루면 다 만들었을 것 같다 ㅋㅋㅋ 페이지가 하나이기 때문에^^ 그만큼 새로운 스택때문에 버벅 거렸다는...
이 토이 프로젝트를 시작하게 된 이유가 꼭 나만의 심리테스트 모음집을 만들고 싶어서도 있었지만 SSR로 자주 언급되는 매우 핫한 슈스(?)NextJS와 짝꿍으로 언급되는 Vercel, 그리고 Tailwind CSS까지, 새로운 스택을 맛보고자 하는 마음에 시작된 것이였다. 말은 거창하지만 사실 유데미 리액트 강의에서 NextJS를 다루는 섹션을 반복적으로 수강했음에도 확실히 감이 오지않아서 직접 써보면서 이해하고 싶어서 시작하게 되었다.
짧은 시간이였지만 NextJS와 Tailwind CSS, Firestore를 써 본 소감을 남겨보자.
NextJS는 라우팅을 설정해주지 않아도된다는 것이 편했다. SEO에도 좋고 페이지가 로딩되기 전에 이미 데이터가 받아와져 렌더링되어있다는 점이 매우 매력적이였다. 게시판과 같이 CRUD 기능이 없는 앱이였어서 상대적으로 간단했지만, 꼭 NextJS로 CRUD 기능이 있는 앱도 만들어보고 싶다.
Tailwind CSS는 코드 길이를 상당히 줄여준다. Styled-Components에서처럼 클래스 이름을 애써 정해줄 필요도 없고, 간단하게 반응형까지 구현할 수 있다. 코드 길이를 줄여주는 것도 줄여주는 것이지만 반응형을 너무 지원을 잘해줘서 놀랐다. 세부적인 CSS를 사용할 때는 인라인 스타일링을 함께 곁들여줘야하는 것 같지만, 장점이 정말 명확하고 사용하기에도 편리할 뿐더러 러닝커브도 낮아서 좋았다. 지피티의 도움도 많이 받긴했지만..^^(아, 매우 많이 받긴 했지만으로 고쳐야 하나?)
마지막으로, FireStore는 역시 명불허전... 프론트엔드가 혼자 토이 프로젝트할 때는 이만한게 없다. 데이터베이스를 직접 만들지 않아도 된다는 점에서 정말 편하다. 물론 규모가 있는 프로젝트나 실무에서는 많이 사용되지 않을 수도 있지만 프론트엔드 초보(?)가 혼자 간단한 프로젝트 만들어보고 싶을 땐 매우 좋은 선택지가 된다. 러닝 커브도 상당히 낮다. 원래는 json-server로 서버를 처리해주려고 했는데, 기왕 해보는거 Firestore을 사용해보고 싶어서 노선을 틀었다. 결론적으로 노선 튼 건 잘한 것 같다. 6월에 스터디원분과 같이 진행해볼 프로젝트에서 Firebase를 쓸 가능성이 높아졌기 때문이다! 정말 간단한 GET 요청 정도만 받아왔지만, 써보길 잘한 것 같다.
이제 데이터를 좀 더 채워넣고 Vercel로 배포하는 과정만 남은 것 같다. Vercel도 러닝 커브가 낮으니 금방 배포해 줄 수 있을 것 같다.
작지만 내가 꼭 해보고 싶었던 주제로 초 미니미(?) 토이 프로젝트를 하는 것은 참 재밌는 것 같다. 기회가 된다면 좀 더 규모가 큰, CRUD 기능이 다 들어간 아이템(?)을 도전해보고 싶다. 그때도 NextJS와 Tailwind CSS 조합을 쓰고 싶다.
'프로젝트 > 오심테(오늘의 심리테스트)' 카테고리의 다른 글
[NextJS] Image 컴포넌트 Legacy prop 리팩토링 (0) | 2023.05.27 |
---|---|
[warning] has "fill" but is missing "sizes" prop. Please add it to improve page performance (0) | 2023.05.27 |
[NextJS] Image 컴포넌트 warning (0) | 2023.05.24 |
[NextJS & Firestore] getStaticPaths() 사용하여 동적 라우팅해주기 (0) | 2023.05.24 |
[NextJS & Firestore] NextJS에 Firestore 연동해보기 (0) | 2023.05.23 |