🎁[속보] 인프런 내 깜짝 선물 출현 중🎁

[인프런 워밍업 클럽 Full-Stack 3기] 1주차 발자국 - TODO List 구현

[인프런 워밍업 클럽 Full-Stack 3기] 1주차 발자국 - TODO List 구현

이제 막 3개월차에 들어가는 새내기 개발자. 일을 다니면서 퇴근 후 개인공부 또는 개발을 하며 멋있는 삶을 보내는 나날을 상상했지만 현실은 퇴근하면 누워있기 바쁜 그런 회사원A. 그러던 차에 인프런에서 스터디를 한다는 소식을 들었다.

이런 프로젝트가 있다는 것은 이미 알고 있었지만, 이전에는 이미 들은 강의이거나 기술이 맞지 않아 참여를 하지 않았었는데 마침 관심있던 Supabase와 요즘 실무에서도 사용중인 Next.js를 결합한 프로젝트 강의라니! 심지어 할인된 가격에! 이건 안할 수 없겠다 싶어서 바로 신청했다. 솔직히 사놓고 안듣고있는 강의가 넘치는데 이런 프로그램에라도 참여해야 강의를 완강할 수 있겠다 싶은 생각도 있긴했다. ㅠㅠ

 

수강 내용

Section 1, 2 : OT 및 기술 소개

Section 1과 2에선 전체 프로젝트에 대한 소개와 사용 기술에 대한 설명이 주를 이뤘다.

이번 강의로 다음과 같은 기술 스택들을 배울 수 있다고 했다.

  • Supabase에서는 Storage, Database, Auth, Realtime 등

     

  • Next.js 14, Typescript, Tailwind CSS, Meterial UI Tailwind, Recoil, Tanstack Query

  • AWS, Vercel, GoDaddy(Domain)

     

확실히 기존에 개인 프로젝트를 할 때 Firebase를 사용했었는데 Firebase같은 경우는 나온지 오래되서 그런지 레퍼런스들이 굉장히 많았다면 Supabase는 그런 점이 좀 부족하다 생각했었는데 강의로 그런 부분들을 채울 수 있어서 좋았다. 실제로 혼자 한번 Supabase를 설정하려고 했었는데 안되서 한참 찾아봤던 문제를 강의에서 짚어주신 부분도 있었다.

강의에서도 좀 중요하게 강조했던 부분이 있다면 Tanstack Query가 아닐 까 싶다. 사실 좋다 좋다 해서 사용하지 왜 좋은지 왜 사용하는지 잘 알지 못하고 썼었는데 이번 기회에 왜 사용하는지, 어떻게 사용하는지 좀 더 잘 알게 된 것 같아서 나중에 효율적으로 사용할 수 있을 것 같다는 생각이 들었다.

  • Tanstack Query (React Query)

    • 서버와 통신할 때 관리해야 하는 상태들이 많이 다양한데, 이런 상태 관리를 클라이언트에서 사용하는 데 도움을 주는 라이브러리.

    • fetching, caching, 서버 데이터와의 동기화를 지원해주는 라이브러리

    • 캐싱 : 캐싱을 통해 동일한 데이터에 대한 반복적인 비동기 데이터 호출을 방지하고, 불필요한 API 콜을 줄여 서버에 대한 부하를 줄이는 결과를 갖는다.

    • Client 데이터와 Server 데이터 간의 분리 : 프로젝트 규모가 커지고 관리해야 할 데이터가 넘치다보면 클라이언트에서 관리하는 데이터와 서버에서 관리하는 데이터가 분리될 필요성을 느낀다.

      • 서버에서 가져오는 데이터 : react-query

         

      • 클라이언트에서 관리하는 데이터 : recoil, zustand ...

    • useQuery : 데이터를 가져오는 작업에 사용

    • useMutation : 데이터를 변경하는 작업(PUT, POST, DELETE)에 사용

    • queryClient.invalidateQueries : queryClient를 사용해 쿼리 요청을 다시 진행할 수 있다. (다른 곳에서 refetch를 진행하기 위함

Section 3. TODO LIST 만들기

(UI 구현은 블로그 글로는 생략...)

본격적으로 프로젝트를 만들어보는 시간이다. Supabase에는 Table Editor, SQL Editor, Database, Authentication, Storage 등 어떤 기능들이 있는지 각각 자세하게 설명해주셨다.

그리고 Supabase를 사용하기 위한 환경변수를 설정하고, Supabase Database를 사용할 때 쉽게 types를 추가하기 위해 script를 추가했는데 처음엔 몰랐는데 나중에 미션을 진행하다보니 자동으로 supabase에 있는 table에 대한 타입을 추가해준다는게 굉장히 편리했다.

"scripts": {
  // dev, build, start, lint
  "generate-types": "npx supabase gen types typescript --project-id [project_id] --schema public > types_db.ts"
}

그리고 이제 Supabase 사용하기 위한 client server middleware 설정도 진행했다. 혼자 공식문서를 봤으면 한참 해멨을 텐데 간단하게 설정이 완료됬다. 이 부분은 나중에 supabase로 개인 프로젝트를 진행할 때 요긴하게 사용할 듯.

이제 Next.js Server Action을 구현했다.

  • server action : api 구현 없이 함수 호출만으로도 api를 대신할 수 있는 기능

getTodo, createTodo, updateTodo, deleteTodo를 만들었다. 그 중 getTodocreateTodo를 보면 다음과 같다.

export async function getTodos({ searchInput = "" }): Promise<TodoRow[]> {
  const supabase = await createServerSupabaseClient();
  const { data, error } = await supabase
	.from("todo")
	.select("*")
	.like("title", `%${searchInput}%`)
	.order("created_at", { ascending: true });
 
  if (error) {
	handleError(error);
  }

  return data;
}
  • from : 가져올 Table 선택

     

  • select : 가져올 부분 선택

  • like : titlesearchInput이 앞뒤로 들어가 있는 부분이 있다면 모두 가져온다.

  • order : 정렬

export async function createTodo(todo: TodoRowInsert) {
  const supabase = await createServerSupabaseClient();
  const { data, error } = await supabase.from("todo").insert({
	...todo,
	created_at: new Date().toISOString(),
  });

  if (error) {
	handleError(error);
  }
  
  return data;
}
  • created_at : 사용자가 잘못 입력할 수도 있어 데이터가 생성될 때 서버에서 자동으로 날짜가 생성되도록 구현

actions들도 모두 구현했으니 이제 DOM에 이벤트를 달아줄 일만 남았다. 위에서 Tanstack Query를 사용하는 방법을 배웠듯 서버에서 데이터를 가져오는 것은 useQuery를 사용하고 데이터를 생성, 수정, 삭제하는 부분은 useMutation을 사용해 구현할 것이다.

const { data, isLoading, refetch } = useQuery({
  queryKey: ["todos"],
  queryFn: () => getTodos({ searchInput }),
});
const { mutate, isPending } = useMutation({
  mutationKey: ["todos"],
  mutationFn: () =>
    createTodo({
      title: "New Todo",
      completed: false,
    }),
  onSuccess: () => refetch(),
});

useQuery useMutation을 담당하는 부분들의 일부를 한번 가져왔다. 이렇게 데이터를 get 할 때는 useQuery 그리고 create 등을 할 때 useMutation을 사용했다.

강의를 모두 마치면 CRUD 기능을 모두 할 수 있는 TODO List가 완성된다.

미션

1주차 미션은 "생성 시간과 완료 시간"을 표시하는 것.

생성 시간은 이미 존재하므로 완료 시간만 Supabase Todo Table에 completed_at 컬럼을 추가했다. 이 때 아까 위에서 말했듯 generate script를 통해 쉽게 table type을 정의할 수 있어서 간편했다.

actions에 updateTodo 부분에 completed_at을 추가하고 todo.completedtrue일 경우 새 날짜를 작성하도록 구현했다.

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 ?? 0);

그리고 시간을 표시하기위해 Date를 바꾸는 함수를 추가했다. (YYYY-MM-DD HH-MM-SS 형식)

export const formatDate = (dateString: string) => {
  if (!dateString) return "";
  const date = new Date(dateString);
  const formattedDate = date.toLocaleDateString("en-CA");
  const formattedTime = date.toLocaleTimeString("en-GB", {
    hour12: false,
  });
  return `${formattedDate} ${formattedTime}`; 
  // 이부분 ${} 이 연속된 부분인데 현재 코드 블럭에서 이상하게 나온다.
};

따라서 생성 날짜와 수정된 날짜를 표시하면 다음과 같이 결과물이 완성된다.

image

마무리

 직장과 병행하며 프로그램을 수행한다는 것이 조금 어려웠지만 무사히 1주차 미션들을 달성해서 뿌듯하다. 혼자라면 중간에 포기하거나 조금 루즈해지거나 했을텐데 다들 열심히 사는 것 같아 나도 뒤쳐지지 않도록 노력했다.

개인적으로 이번 강의를 모두 마치고 목표가 있다면 Supabase + Next.js를 통해 나만의 블로그를 만드는 것. 강의를 들으면서 나중에 이 기능은 어떻게 활용하면 좋겠다라는 상상도 해보고 하는 시간들이 즐거웠다. 또 강사님께서 차근차근 친절히 알려주셔서 더 쉽게 학습됬었던 듯 하다. 개인적으로 supabase이외에도 react query를 좀 더 상세하게 알 수 있었던 시간이라 (위에서도 말했듯 이전에 사용할 때에는 그냥 좋다니까 썼지 제대로 쓴다는 느낌은 받지 못했다) 굳이 fullstack 스택이 아니더라도 front-end 개발자 입장에서도 한단계 스킬 업한 느낌이었다.

앞으로 3, 4주차에 좀 타이트하게 진행된다고 했는데 이번주는 스케쥴에 딱 맞게 진행해서.. 다음주에는 조금 더 신경써서 시간을 할애해봐야겠다. 스터디원들 모두 화이팅...!

댓글을 작성해보세요.


채널톡 아이콘