![[인프런 워밍업 클럽 3기 풀스택] 1주차 발자국](https://cdn.inflearn.com/public/files/blogs/20ecf90d-5001-4f2b-af8c-c007a825ae21/336235.png)
[인프런 워밍업 클럽 3기 풀스택] 1주차 발자국
학습 내용
1주차에는 주로 사용할 기술들에 대한 소개와 기본 문법을 배우고 이를 이용해 TODO List를 만들었다.
Firebase 이후 등장한 Supabase에 대해서 배웠다.
오픈소스 프로젝트여서 자체 서버구축이 가능하고 특히 개인/소규모 풀스택 개발에 필요한 것이 대부분 갖춰져 있다는 장점이 있어 앞으로 진행할 프로젝트에 적절한 서비스임을 느꼈다. 부족한 문서 한글화가 단점이라고 하셨는데 강의에서 설정 방법을 자세히 알려주셔서 초보인 나도 쉽게 적용시킬 수 있었다.
Next.js는 풀스택 개발에 최적화된 프레임워크로, SSR을 지원하고 별도 서버 구축 없이도 API 구축이 가능하다.
이외에도 TailwindCSS(+MaterialUI), Recoil, React Query(TanStack Query)에 대해 배우고 사용해보았다.
기존에 GraphQL을 써봤는데, 이번 기회에 궁금했던 React Query의 장점과 기본 문법을 알게 되어서 좋았다. 사용법 자체는 비슷하기도 해서 금방 적응할 수 있을 것 같았다.
나는 프론트엔드만 더듬더듬 배운 적이 있고 제공되는 백엔드 API를 사용하기만 했었는데(만드는 걸 아주 간단하게 배운 적 있는데 엄청 어려웠다) Server Action 함수 만들고 호출하기만 해도 백엔드 없이 직접 DB를 조작할 수 있다는 게 신기했다.
미션
생성된 TODO의 생성 시간을 저장하고 이를 표시하는 기능을 추가하세요.
TODO 항목 옆에 생성 시간을 표시하기
날짜 포맷 함수 만들기
// utils/formatDate.ts export const formatDate = (dateString?: string): string => { if (!dateString) return ""; const date = new Date(dateString); const yyyy = date.getFullYear(); const mm = String(date.getMonth() + 1).padStart(2, "0"); const dd = String(date.getDate()).padStart(2, "0"); const hh = String(date.getHours()).padStart(2, "0"); const min = String(date.getMinutes()).padStart(2, "0"); const ss = String(date.getSeconds()).padStart(2, "0"); return `${yyyy}-${mm}-${dd} ${hh}:${min}:${ss}`; };
생성 시각은 이미 supabase에 있으므로 created_at 필드 값을 가져와 사용
나중에 완료 시각이 추가되어도 생성 시간은 위치가 바뀌지 않게 위쪽에 배치<> <p className={`flex-1 ${completed && "line-through"}`}>{title}</p> <div className="grid grid-rows-2 items-end pr-1"> <p className="text-xs text-right text-gray-500"> <i className="fas fa-pen pr-1" /> {formatDate(todo.created_at)} </p> <p className="text-xs text-right text-gray-500"></p> </div> </>
completed_at 필드를 추가하여 완료한 시간도 함께 저장하기
created_at과 같이 supabase에 completed_at 필드부터 추가(Allow Nullable 체크)
이후 npm run generate-types 실행해 타입 파일도 수정todo가 체크되어 completed가 true일 때는, completed_at에 완료 시각을 저장하도록 updateTodo Server Action을 수정
export async function updateTodo(todo: TodoRowUpdate) { const supabase = await createServerSupabaseClient(); const { data, error } = await supabase .from("todo") .update({ ...todo, updated_at: new Date().toISOString(), completed_at: todo.completed ? new Date().toISOString() : null, }) .eq("id", todo.id); if (error) { handleError(error); } return data; }
마지막으로 completed_at도 포맷팅하여 완료 시각을 표시하고, 조건부 렌더링을 적용해 완료 시각이 없을 때는 아이콘과 시각 모두 표시하지 않도록 작성
<> <p className={`flex-1 ${completed && "line-through"}`}>{title}</p> <div className="grid grid-rows-2 items-end pr-1"> <p className="text-xs text-right text-gray-500"> <i className="fas fa-pen pr-1" /> {formatDate(todo.created_at)} </p> <p className="text-xs text-right text-gray-500"> {todo.completed_at ? ( <> <i className="fas fa-check mr-2" /> {formatDate(todo.completed_at)} </> ) : null} </p> </div> </>
마무리
이번 주 학습에서는 스스로 부족한 점을 많이 느꼈던 것 같다... 처음 배운 것, 지금까지 잘 몰랐던 것도 많았고 버전 문제 등 사소한 이슈를 많이 겪어서 시간이 꽤 들었다.
그래도 생각보다 간단하게 Todo List가 만들어지는 걸 보면서, 완강할 때쯤 되면 나만의 프로젝트도 만들 수 있겠다는 자신감이 생기고 있다🙂 아직 너무나 익숙하지 않지만 클론하다 보면 조금씩 감이 잡힐 것 같다.
미션을 진행하면서 발전시킬 수 있는 부분도 많을 것 같은데 이번 주에는 시간을 거의 내지 못해 아쉬웠다. 다음 주에는 더 열심히 따라가고 싶다!
댓글을 작성해보세요.