블로그
전체 4#카테고리
- 풀스택
#태그
- 풀스택
- 웹개발
- Next.js
- Supabase
2025. 03. 30.
0
[인프런 워밍업 클럽 3기 풀스택] 4주차 발자국
학습 내용마지막 주에는 인스타그램 프로젝트 클론코딩과 Vercel, AWS EC2 배포, 도메인 등록 및 연결까지 진행했다. Supabase Auth를 활용해 인증을 다루고, Supabase Realtime에 대해 알아보고 실시간 DM 채팅을 구현했다.Supabase Auth를 이용해 인증방식 기획, 회원가입/로그인/로그아웃 기능 구현회원가입 방식: Confirmation URL / 6-Digit OTP로그인 방식: Email, password카카오 소셜 로그인/회원가입SMTP 서비스랜덤 이미지 API로 유저 프로필 이미지 적용Supabase Realtime으로 채팅 구현 Postgres Changes로 DB 상태 변경 실시간 추적 - message INSERT 이벤트 구독, 실시간 채팅 구현Presence로 유저 실시간 추적 - 온라인 유저 파악, 유저별 마지막 접속시간 표시Supabase RLS(Row Level Security) 설정 - 테이블 접근 권한 설정, Client-Side에서 Supabase 접근Vercel, AWS EC2로 프로젝트 배포도메인 구매 및 등록(Vercel과 연결하기) 미션이제까지 만드신 모든 프로젝트를 배포하신 후 배포된 링크를 업로드 해주세요.강의 내용대로 배포를 진행하니 Vercel로 모두 배포할 수 있었다. Vercel은 Next.js 팀이 만든 플랫폼이라 Next.js 프로젝트를 배포하기에 수월하겠다는 생각이 들었다. 지금까지의 프로젝트는 모두 Github에 올려놓았기에, 이를 연동해 배포할 리포지토리를 고르고 Import를 눌러 환경변수를 입력한 뒤 Deploy하면 끝이었다. Deploy에 앞서 프로젝트 build에 문제가 없는지 체크한 후 진행했다.모두 배포를 완료한 뒤 인스타그램 프로젝트에서 카카오 로그인을 시도하니 리다이렉트 문제를 겪어 처음에 당황했는데 강의 질문 답변을 보고 Supabase Authentication에서 Redirect URLs에 배포 URL를 추가하니 해결되었다. 마무리예상대로 마지막 4주차 내용이 가장 어려워 따라가기 쉽지 않았다. 이전까지는 어떻게든 이해가 됐었는데, Supabase Realtime의 Presence를 이용하는 부분은 처음에 도저히 이해되질 않아서 일단 똑같이 따라만 했던 기억이 난다. 그래도 이렇게 복잡할 수 있는 부분을 쉽게 따라가며 습득할 수 있다는 것에 감사했다😌짧은 시간 동안 다양한 핵심 기술과 유용한 기능 구현도 빠르게 터득할 수 있었고, 덕분에 구현에 대한 자신감도 조금씩 늘어 의미 있는 시간이었던 것 같다. 또 예전에 AWS EC2를 이용해 겨우 배포해보고 배포는 너무 어려운 것이라 느끼고 흥미를 잃었었는데 이번에 전체적인 EC2 배포 과정도 알아가고, Vercel로 프로젝트가 정말 쉽게 배포되는 걸 보면서 ‘이제 뭐든 시도하고 만들어 올려볼 수 있겠다’는 생각이 들었다!개인적으로는 배포만이라도 하는 것이 목표였기에…ㅎㅎ 일단 완주했다는 것에 만족하고 있다. 자유자재로 코드를 바꾸지 못할 때, 발견한 문제를 해결하고 싶어도 방법을 모를 때😂 스스로의 부족함에 고민도 많았던 것 같다. 그럼에도 포기하지 않고 여기까지 올 수 있었던 건 워밍업 클럽에 참여하고 강의를 진행하며 느낀 성취 덕분이라고 생각한다.가끔씩 처음 코딩을 시작했을 때를 떠올리며 몰랐던 성장을 체감하곤 했는데, 이번 워밍업 클럽도 마찬가지로 나중에 돌이켜보면 한 달 동안 내 생각보다 많은 것을 배우고 해냈다고 느끼리라는 생각이 들었다. 이번 학습이 헛되지 않도록 배운 것을 활용한 간단한 프로젝트부터 만들어보고 전진할 생각이다.🙂 많은 도움 되는 시간 만들어주신 강사님과 인프런에 감사드리고, 함께 워밍업에 참여한 분들도 진심 대단하세요! 모두 응원합니다!
풀스택
・
풀스택
・
웹개발
・
Next.js
・
Supabase
2025. 03. 23.
0
[인프런 워밍업 클럽 3기 풀스택] 3주차 발자국
학습 내용이번 주에는 Netflix 프로젝트 클론코딩을 진행했다. 영화 목록 페이지 및 검색 기능과 개별 영화 상세페이지를 구현했다.supabase에서 영화 테이블을 만들고, 준비된 csv 파일로 바로 영화 데이터를 추가header에서 입력한 검색어를 다른 컴포넌트에서 사용하기 위해 Recoil 사용dynamic routing으로 개별 영화 상세페이지 구현영화 목록을 보여줄 때 무한스크롤 적용react-intersection-observer 라이브러리를 사용해, 보이지 않는 태그를 심어놓고 감지react-query의 useQuery 대신 무한스크롤을 쉽게 구현할 수 있는 useInfiniteQuery 이용상세페이지의 동적 meta tag 생성을 위해 generateMetadata() 사용해 SEO 작업 미션Netflix Clone 프로젝트에 “찜하기” 기능을 추가하세요.공용 즐겨찾기 기능을 구현하고, 찜한 영화를 리스트 최상단에 보이도록 정렬했다. 찜한 영화 리스트를 가져와서 별도의 찜 목록 페이지에서 보여주는 방법도 고려해볼 수 있을 것 같다.movie 테이블에 bool 타입의 bookmarked column을 추가하고 초기값은 FALSE로 설정searchMovies()에서 order()로 정렬 기준을 추가해 찜한 영화부터 보이도록 하고 다중 정렬하여 찜한 영화 중에서도 id 순서대로 정렬되도록 작성 const { data, error } = await supabase .from("movie") .select("*") .like("title", `%${search}%`) .order("bookmarked", { ascending: false }) .order("id", { ascending: true }) .range((page - 1) * pageSize, page * pageSize - 1); 북마크 버튼을 누르면 북마크 상태가 반대로 바뀔 수 있도록 Server Action 작성export async function updateBookmark(id, status) { const supabase = await createServerSupabaseClient(); const { error } = await supabase .from("movie") .update({ bookmarked: !status }) // 현재 상태 반대로 변경 .eq("id", id); handleError(error); return !status; } movie-card에서 북마크 mutation을 작성해 updateBookmark()를 실행하고 성공하면 화면이 바로 업데이트되도록 함const updateBookmarkMutation = useMutation({ mutationFn: () => updateBookmark(movie.id, movie.bookmarked), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["movie"] }); }, }); bookmarked 값에 따라 북마크 icon을 다르게 표시하고,북마크 클릭 시 mutation을 실행해 해당 영화의 bookmarked 값을 반대로 바꿔줌return ( ... {/* Bookmark 부분 */} updateBookmarkMutation.mutate()} className={`text-yellow-600 drop-shadow-md absolute flex items-center justify-center p-2 text-2xl top-2 right-2 z-20 ${ movie.bookmarked ? "fa-solid fa-bookmark" : "fa-regular fa-bookmark" }`} > ... ) 마무리이번 주에 배운 기능 중에는 이미 한두 번 다뤄본 내용들도 있었는데, 특히 useInfiniteQuery를 이용해 무한스크롤을 더 편리하게 적용해볼 수 있었던 것 같다(그래도 어려웠다…😅). 중간에 막히는 부분도 있었지만, 자세한 사용법을 찾아보고 강의를 따라가며 무한스크롤 구현 과정을 되짚어볼 수 있었다. Next.js가 알아서 해주는 동적 메타데이터 생성으로 간편하게 SEO 적용하는 방법도 알아갈 수 있었다. 현재 아쉬운 점 중 하나는 찜하기 기능을 적용했을 때 비교적 아래쪽의 영화를 찜하니 모든 영화 데이터를 다시 요청해오느라 북마크 표시가 늦게 반영된다는 것인데, 이번 경험으로 invalidateQueries() 대신 setQueryData() 활용을 고려하는 등 네트워크 요청 최적화의 필요성을 느꼈다. 마지막으로 다음 주가 가장 어려운 부분이 될 것 같지만, 끝까지 완주하는 것을 목표로 최선을 다해보려 한다!
풀스택
・
풀스택
・
웹개발
・
Next.js
・
Supabase
2025. 03. 15.
0
[인프런 워밍업 클럽 3기 풀스택] 2주차 발자국
학습 내용이번 주에는 Supabase Storage를 활용하여 파일 업로드가 가능한 Minibox 프로젝트 클론코딩을 진행했다.Supabase Storage Bucket 생성 및 접근 정책 설정 방법파일 업로드, 검색, 삭제 Server Action과 기능 구현같은 파일명이 있을 경우 덮어쓰는 upsert 옵션storage bucket에 올라간 이미지 URL 구조를 확인해보고, 업로드 응답으로 받는 path를 활용해 직접 URL을 만드는 getImageUrl() 함수 작성해 화면에 이미지 표시react-dropzone 라이브러리를 적용해 Drag & Drop으로 파일 업로드 기능 구현react-dropzone 라이브러리의 useDropzone에 multiple 옵션을 적용하고 멀티 파일 업로드 구현1주차에 만든 TODO List 프로젝트 코드를 활용해 빠르게 초기 설정을 마치고, 저번 주 학습 내용에 익숙해지면서 Supabase Storage 사용법과 파일을 다루는 방법을 익힐 수 있었다. 미션Dropbox Clone 프로젝트에 파일의 마지막 수정(업로드) 시간을 표시하는 기능을 추가하세요.파일 목록에서 각 파일의 “마지막 수정 시간”을 표시 📌 참고 문서: Supabase Storage - 파일 목록 가져오기 https://supabase.com/docs/reference/javascript/storage-from-list위의 참고 문서에서 파일 리스트를 가져올 때 받는 data에 updated_at 값이 포함된다는 것을 알 수 있었고, 이를 활용해 파일의 마지막 수정(업로드) 시간을 표시하기로 했다.파일들의 data를 받아오면 DropboxImage 컴포넌트에 전달된다. 이 컴포넌트에서 각 파일 data(image)의 image.updated_at(마지막 수정 시간)을 파일 이름 바로 아래에 표시해주었다. 이때 TODO List 미션 때 작성했던 날짜 포맷 함수를 적용했다.... {/* FileName */} {image.name} {/* Updated_at */} {formatDate(image.updated_at)} ... 마무리이번 주는 파일 업로드와 Drag & Drop 등 자주 쓰이는 유용한 기능을 따라 구현해볼 수 있었어서 앞으로 필요할 때 쉽게 적용할 수 있을 것 같다. 다만 한글 파일명은 업로드되지 않는 문제와 첫 글자부터 입력해야만 뜨는 검색 기능도 별도로 개선이 필요할 것 같다.🥺또한 이번주에는 중간점검 라이브가 진행됐는데, 질문에 대해 자세히 답해주셔서 앞으로의 방향 설정에도 많은 도움이 되었고 짧지만 유익한 시간이었다! 벌써 진도의 절반이 지나가고 있는데 지금까지의 내용도 잘 보강하면서 나머지 강의와 미션도 끝까지 해내고 싶다🙂
풀스택
・
풀스택
・
웹개발
・
Next.js
・
Supabase
2025. 03. 09.
0
[인프런 워밍업 클럽 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 필드 값을 가져와 사용나중에 완료 시각이 추가되어도 생성 시간은 위치가 바뀌지 않게 위쪽에 배치 {title} {formatDate(todo.created_at)} 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도 포맷팅하여 완료 시각을 표시하고, 조건부 렌더링을 적용해 완료 시각이 없을 때는 아이콘과 시각 모두 표시하지 않도록 작성 {title} {formatDate(todo.created_at)} {todo.completed_at ? ( {formatDate(todo.completed_at)} ) : null} 마무리이번 주 학습에서는 스스로 부족한 점을 많이 느꼈던 것 같다... 처음 배운 것, 지금까지 잘 몰랐던 것도 많았고 버전 문제 등 사소한 이슈를 많이 겪어서 시간이 꽤 들었다.그래도 생각보다 간단하게 Todo List가 만들어지는 걸 보면서, 완강할 때쯤 되면 나만의 프로젝트도 만들 수 있겠다는 자신감이 생기고 있다🙂 아직 너무나 익숙하지 않지만 클론하다 보면 조금씩 감이 잡힐 것 같다.미션을 진행하면서 발전시킬 수 있는 부분도 많을 것 같은데 이번 주에는 시간을 거의 내지 못해 아쉬웠다. 다음 주에는 더 열심히 따라가고 싶다!
풀스택
・
풀스택
・
웹개발
・
Next.js
・
Supabase