묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
(7.14) 포스트 삭제 후 무한 스크롤이 작동하지 않는 문제
안녕하세요. 좋은 강의 잘 수강하고 있습니다!다름이 아니라 포스트 삭제 후에 무한 스크롤이 작동하지 않는 문제가 발생했습니다.문제 상황은 다음과 같습니다.첫 페이지(다음 페이지의 데이터를 페칭하지 않은 상태)에서 작성한 포스트를 삭제이후 페이지 최하단까지 스크롤 했지만 무한 스크롤 데이터 페칭이 이루어지지 않음 부족한 실력이라 AI의 도움을 받아 원인을 분석했을 때 다음과 같았습니다. 아래는 AI의 답변입니다.무한 스크롤이 작동하지 않는 원인 분석:getNextPageParam의 로직useInfinitePostData 훅에서 다음 페이지를 불러올지 결정하는 로직은 다음과 같습니다:// src\hooks\queries\use-infinite-posts-data.ts // ... const PAGE_SIZE = 5; // ... getNextPageParam: (lastPage, allPages) => { if (lastPage.length < PAGE_SIZE) return undefined; // 🚫 문제의 원인 return allPages.length; }, 이 로직은 "마지막으로 불러온 페이지의 항목 개수가 PAGE_SIZE (5개)보다 적으면, 더 이상 데이터가 없으므로undefined를 반환하라 (즉, 다음 페이지를 불러오지 마라)"고 지시합니다. 삭제가 로직에 미치는 영향:초기 상태: 0번 페이지에 5개의 게시글이 있습니다. (lastPage.length = 5)삭제 이벤트: 사용자가 0번 페이지의 게시글 1개를 삭제합니다.캐시 업데이트:useDeletePost의 onSuccess에서 해당 게시글 ID를 0번 페이지의 캐시 데이터에서 제거합니다.결과: 0번 페이지의 항목 개수가 5개에서 4개로 줄어듭니다.무한 스크롤 시도: 사용자가 스크롤하여 ref(inView)가 활성화됩니다.getNextPageParam 실행: React Query는 0번 페이지의 현재 캐시 데이터를 확인합니다. lastPage.length는 이제 4입니다.잘못된 판단:4 < PAGE_SIZE (5)이므로, getNextPageParam은 즉시 undefined를 반환합니다.따라서 1번 페이지(실제 서버에는 데이터가 있을 수 있음)를 불러오기도 전에, 캐시 데이터가 줄어든 것 때문에 다음 페이지 로딩이 차단되어 무한 스크롤이 작동하지 않게 되는 것입니다.마지막 페이지에 속한 포스트를 삭제했을 때, PAGE_SIZE보다 항상 작아지니 다음 페이지가 없다라고 판단하기에 무한 스크롤이 작동하지 않는다고 이해했습니다.캐시를 무효화해 리페칭해서 해결하려고 하는데, 다른 대안이 있을까요?혹여 제 실수로 잘못된 동작이 일어난 건지 GitHub Repo도 같이 첨부했습니다!https://github.com/scseong/onebite-sns
-
해결됨한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
토큰 관리에 대해 질문을 드리고 싶습니다.
안녕하세요 멘토님, 정말 쉽게 설명해주셔서 수업 잘 듣고 있습니다.인증 처리하기 부분에 대해서 흐름도를 자세하고 재밌게 설명해주셔서 덕분에 이해하기 수월했습니다. 다만 현재 토큰들을 localStorage에 저장하고 이 값을 zustand로 관리하고 있는 것 같은데 사실 토큰을 storage에 저장하는 방식이 일반적이지는 않은 것 같습니다.이 부분에 대해서 찾아본 결과 supabase를 이용하기에 쿠키에 저장하는 건 무리인 것 같고, 그렇다면 그나마 토큰을 메모리에 저장하는 방식이 안전할 것 같습니다.로그인을 진행하면 토큰이 localStorage에 저장되는 형태인데, 이때 만약 storage에 저장하지 않고 메모리에 받게하려면 어떻게 할 수 있을까요 .. ?또한 사실 토큰 자체를 zustand에서 가지고 있는 것도 괜찮은지 의문입니다.. 전역상태로 들고 있는 것이라서 충분히 탈취위험이 있을 것이라고 생각이 되어서요..사실 백엔드 서버가 있었다면 쿠키에 저장하는 로직으로 진행했을 거 같은데만약 이때는 로그인 상태를 어떻게 판별하는지에 대해서도 궁금합니다 !
-
미해결한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
fetch api의 상태값 유지
안녕하세요..강의 잘 보고 있습니다. import { ITodoInfo } from "@/utils/types"; export async function fetchTodos(blngCoCd:string, userId:string) { const respose = await fetch( `${process.env.NEXT_PUBLIC_API_SERVER_URL}/todo/list?blngCoCd=${blngCoCd}&userId=${userId}` ); if (!respose.ok) { throw new Error("Fetch Todo Error"); } const data: ITodoInfo[] = await respose.json(); console.log('todo data=',JSON.stringify(data, null, 2)); return data; } import { fetchTodos } from "@/api/todo/fetch-todos"; import useUserInfoStore from "@/store/user-info-store"; import { ILoginUserInfo } from "@/utils/types"; import { useQuery } from "@tanstack/react-query"; export function UserTodosData() { const loinData: ILoginUserInfo = useUserInfoStore((state) => state.userInfo); return useQuery({ queryFn: () => fetchTodos(loinData.blngCoCd, loinData.userId) , queryKey: ["todos"], }); }이런식으로 zustand의 유저 정보를 가져와 훅에서 api를 호출을 하면 처음은 정보를 가져오는데.refresh를 하면 다시 가져 올때 blngCoCd와 userId가 null이 되면서 리스트를 가져오지 못하네요.zustand의 정보는 localstorage로 보관하고 있고... const loinData: ILoginUserInfo| null = useUserInfoStore((state) => state.userInfo); const blngCoCd = loinData?.blngCoCd; const userId = loinData?.userId; // blngCoCd와 userId가 모두 존재할 때만 쿼리를 활성화합니다. const enabled = !!blngCoCd && !!userId; return useQuery({ queryFn: () => fetchTodos(blngCoCd, userId) , queryKey: ["todos", blngCoCd, userId], enabled: enabled, });이렇게 변경을 했는데...api에 파라미터를 넘겨야 하는경우 새로고침을 할 경우 이런식으로 하는게 일반적인가요?
-
미해결[플러터플로우] 실전! 앱 출시를 위한 끝장 노하우!
커스텀액션 maybeCreateUser 오류가 납니다.
전 질문 내용 검색해 보고 해도 안되는데요..확인 좀 부탁 드립니다.
-
해결됨비개발자 4주만에 수익화 서비스 만들기: AI 바이브코딩 웹 + 앱 ALL IN ONE
Lovabe - supabese 연동이 노베이스 비개발자에겐 너무 어렵습니다.
💬 좋은 질문 예시[진도] 1주차 5강 웹사이트 만들기[질문] Lovable 에 자체 클라우드가 생기면서 supabase를 연동하기 힘들어 졌습니다.Lovable유료결제 까지 하면서 원인을 찾아보려고 했는데 일주일 동안 찾지 못 했습니다.전에 같은 질문을 하신분의 답변에 다른 분의 영상을 봤는데도, 그것으로는 해결이 되지 않는 상황입니다.아예 베이스가 없기 때문에 supabase가 뭔지도 모르는 상황이고 이 둘을 어떻게 연결해야 할지도 모르는 상황입니다. 현재 바뀐 상황을 들여다 본 후 답변 주셨으면 좋겠습니다.혹은, supabase 연동 없이 Lovable 자체 클라우드를 활용해서 강의를 진행해도 괜찮을지 알려주시면 supabese 없이 Lovable 클라우드로 진행해 보겠습니다.제가 변화에 대처하질 못하는 상황이지만, 항상 질 높은 강의 감사드립니다.
-
미해결한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
댓글 수정, 삭제 시 캐시 수정
강의 정말 잘 듣고있습니다!10.6 강의 수강 중 댓글 추가 시에는 Comment 타입과 일치시키기 위해 프로필 데이터를 조회해서 author 객체를 포함시켜주었는데 수정, 삭제 시에는 왜 따로 처리를 하지 않는지 궁금합니다.삭제 시에는 해당 데이터를 삭제하기에 불필요하다고 생각되긴하는데 수정 시에는 왜 에러가 발생하지 않나요??
-
해결됨한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
forget-password 이후 reset password 이메일이 오지 않네요.
강의 잘 듣고 있습니다. 다름이 아니라, forget-password 로 정상적으로 처리가 되었다고 하는데요. 그러나, 등록해 둔 이메일로 reset password 메일이 오지 않네요. 혹시 Supabase 셋팅에서 어떤 부분을 확인해야 할까요? 검색을 해보니 이렇게 셋팅하라고 해서 한 상태입니다답변 부탁드립니다.
-
해결됨한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
Zustand 사용 중 컴포넌트 리렌더링 관련 질문
관련 챕터: Zustand 기본 사용법 2질문 관련 부분: 4:34 ~ 6:20 질문 내용: 역할에 따라 컴포넌트를 분리하는 과정에서,count 값 변경 시 Controller 컴포넌트까지 리렌더링되는 이유에 대해 설명해주셨는데요. 제가 맞게 이해했는지 헷갈려서 질문 드립니다.count 값이 바뀔 때마다 Viewer, Controller 컴포넌트가 동시에 리렌더링된다. 버튼 태그를 포함하는 Controller 컴포넌트까지 리렌더링되는 이유는 1. Zustand는 store 안의 state가 바뀌면 store를 가져다 쓴 모든 컴포넌트가 다시 그 state값을 반영하도록 리렌더링된다. 2. Controller는 구조분해 할당으로 increase, decrease만 쓴다고 해도, 훅이 반환한 객체 안에 count도 포함돼 있으므로 count가 바뀌면 Controller도 리렌더링된다. 제가 맞게 이해한 걸까요?
-
미해결한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
tailwind css / sass 사용율? 에 대해서 궁금합니다
저는 항상 scss를 많이 사용해서 쭉 사용하고있었는데 tailwind 가 무섭게 치고 올라오는거 같더라구요 ㅎㅎ 둘다 공부를 하면서 사용해보고있는데 혹시 실무나 이런쪽에서는 어느걸 더 많이 활용하는지도 궁금합니다 ㅎㅎ
-
해결됨비전공자 혼자서 하루 만에 수익화 앱 출시하기
xcode 오류
애플계정이 있는데 xcode에서 계속 'Communication with Apple failed'오류가나는데 업데이트하고 계정을 다시 등록해도 해결이 안되는데 해결방법 있을까요?
-
미해결한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
supabase를 사용하는 기업들이 많이 있나요?
supabase를 사용하는 기업들이 많이 있나요?보통은 스프링부트 또는 노드, 네스트를 사용할거같은데 supabase를 사용하는 사례들이 많은지,중소및 스타트업위주로 사용하는지 궁금합니다.
-
미해결한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
6.8 zustand 강의에서 devtools 미들웨어에 대한 질문입니다.
zustand 강의에서 devtools 미들웨어를 사용하여브라우저 도구 Redux 툴에서 Action 과 State 를 살펴보는데 강의 영상에서는 Action의 이름이 setSession 으로 나오는 데...제 Redux 툴에서는 액션 명이 anonymous로 표시됩니다. 어떻게 액션명이 표시되는 지 궁금합니다. set 함수에서 액션명 표시하려면 이름을 주어 표시했는데 . 뭔가 다른가요 ?//... set({session, isLoaded: true}, undefined, 'setSession'); //...
-
미해결한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
21강. 강의와 다른부분에서 todo 타입 에러가 납니다.
import type { Todo } from "@/types"; import { create } from "zustand"; import { combine } from "zustand/middleware"; import { immer } from "zustand/middleware/immer"; const initialState: { todos: Todo[]; } = { todos: [], }; const useTodosStore = create( immer( combine(initialState, (set) => ({ actions: { createTodo: (content: string) => { set((state) => { state.todos.push({ id: new Date().getTime(), content }); }); }, deleteTodo: (targetId: number) => { set((state) => { state.todos = state.todos.filter((todo) => todo.id !== targetId); }); }, }, })), ), );export interface Todo { id: number; content: string; } 오히려 강의에서 7분에 'never'에러나던 state.todos.push({ id: new Date().getTime(), content}); 이 코드 작성 시에는 에러가 나지않고,state.todos.filter((todo) => todo.id !== targetId); 여기서 todo 부분에서 에러가 납니다.'todo' 매개 변수에는 암시적으로 'any' 형식이 포함됩니다.state.todos에 마우스오버해서 확인해보니 any 타입으로 뜹니다.제가 중간에 설정하는 부분이나 놓친부분이 있는걸까요 ㅠㅠ?
-
해결됨비전공자 혼자서 하루 만에 수익화 앱 출시하기
코드에서
강의 잘 보고 있습니다!좋은 강의 만들어 주셔서 감사해요강의 보다가 그냥 좀 어색한 부분이 있는거 같아서 공유드립니다~ 65. Supabase로 공지사항 다이얼로그 띄우기 (2)수업중 아래 파일의 코드에서 하나 확인 부탁드립니다.lib/widget/announcement_dialog.dart 3번의 prefs.setStringList 가 2번의 if 문 안으로 들어가는게 맞을거 같아요. static Future<void> _setViewed(int announcementId) async { final prefs = await SharedPreferences.getInstance(); // 1. 기존의 공지사항 아이디를 가져온다. final viewedIds = prefs.getStringList(_viewedAnnouncementsKey) ?? []; // 2. 가져온 아이디에 포함여부 확인. if (!viewedIds.contains(announcementId.toString())) { viewedIds.add(announcementId.toString()); } // 3. 포함되어 있지 않다면 새로 추가한다. await prefs.setStringList(_viewedAnnouncementsKey, viewedIds); }
-
미해결한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
(6.1) 인증과 인가 아해하기
질문은 아니고오타가 있어서 제보 합니다. 이해하기 인데 아해하기로 되어 있네요(6.1) 인증과 인가 아해하기
-
미해결한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
next.js가 아닌 react.js로 강의를 한이유가 궁금합니다.
next.js가 더 좋은거같은데 react.js로 하는이유가 있을까요?next.js요즘 안쓰는사람많던데 이유가 궁금합니다.
-
해결됨비개발자 4주만에 수익화 서비스 만들기: AI 바이브코딩 웹 + 앱 ALL IN ONE
1주차 과제제출 디스코드 링크
1주차 과제 제출을 위해 디스코드 링크로 들어가려는데 해당 채팅이 없다고 나옵니다.혹시 어떻게 접근하여 제출하면 될까요?
-
미해결한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
컴포넌트 네이밍 컨벤션 관련 질문 드립니다.
안녕하세요! 강의 잘 보고 있습니다.정환님이 제작하신 강의는 모두 수강하고 있는데요,리액트나 넥스트 강의에서 보면 컴포넌트 파일명도 케밥 케이스로 작성하시던데, 일반적으로 컴포넌트는 파스칼 케이스로 작성하는 경우가 많아서 혹시 특별한 이유가 있는지 궁금합니다!
-
미해결한 입 크기로 잘라먹는 실전 프로젝트 - SNS 편
Zustand의 get/set 메서드 관련 질문 드립니다.
안녕하세요! 강의 잘 듣고 있습니다.(3.2) Zustand 기본 사용법 1 강의의 9분 21초경에서 궁금한 점이 생겨 질문드립니다. 강의에서 get 메서드는 store(객체) 전체를 반환한다고 설명하셨습니다.그리고 set 메서드는 인자로 전달된 객체의 프로퍼티만을 갱신한다고 하셨는데요.그런데 아래 코드처럼 보면,set 내부에서는 따로 get()을 호출하지 않아도 count 값을 바로 참조해 업데이트하고 있습니다. increase: () => { const count = get().count; // 여기서 store의 count 프로퍼티를 가져온다 set({ count: count + 1 }); // 그런데 여기서는 count를 직접 사용할 수 있다? } 제가 이해하기로는 store의 값을 변경하기 위해 프로퍼티를 참조할 때에도(여기서는 count:) 먼저 get()으로 현재 store의 참조를 얻은 뒤 수정해야 할 것 같은데,set({ count: count + 1 })처럼 직접 count를 갱신할 수 있는 이유가 궁금합니다.즉, set은 내부적으로 get()을 다시 호출해서 현재 store 상태를 알고 있는 건가요?아니면 set이 store 객체의 참조를 이미 가지고 있어서 가능한 건가요?
-
해결됨비개발자 4주만에 수익화 서비스 만들기: AI 바이브코딩 웹 + 앱 ALL IN ONE
cursor 유료가 과거에는 “500 fast 요청 + 무제한 slow” 같은 횟수 기반(레이트) 모델이었는데, 지금은 크레딧 기반으로 바뀌었습니다 라고 하는데 맞나요?
현재 수강 진도를 함께 알려주세요! "1주차 3강까지 완료" 또는 "2주차 실습 중"처럼 어디까지 들으셨는지 적어주시면 맞춤형 답변을 드릴 수 있어요 📚구체적인 상황과 함께 질문해주세요! "AI가 안 된다"보다는 "Cursor에서 이런 프롬프트를 입력했는데 이런 에러가 나와요"처럼 상세하게 적어주시면 더 정확한 답변을 드릴 수 있어요 🎯스크린샷이나 코드를 첨부해주세요. 에러 화면, 현재 진행 상황을 보여주시면 문제 해결이 10배 빨라집니다! 마크다운 코드 블록(```)을 활용하면 더 깔끔하게 정리할 수 있어요 📸커뮤니티 검색을 먼저 해보세요. 같은 문제로 고민하신 분들이 이미 해결책을 찾았을 수도 있어요. 검색 후 못 찾으시면 언제든 새로 질문해주세요! 🔍서로 도우며 함께 성장해요. 나도 모르는 건 "저도 궁금해요!"라고 댓글 달아주시고, 아는 건 적극적으로 공유해주세요. 가르치면서 더 잘하게 됩니다 💪바이브코딩 관련 질문은 환영, 기술 세부사항은 GPT 활용! 프롬프트 작성법, AI 도구 사용법은 여기서, 복잡한 코딩 문법은 ChatGPT에게 물어보시는 게 더 빨라요 🤖진도나 과제 관련 문의는 1:1 문의를 이용해주세요. 개인적인 학습 계획, 환불, 수강 기간 연장 등은 따로 문의해주시면 더 자세히 상담드릴게요 📞실패 사례도 공유해주세요! "이렇게 했더니 망했어요" 같은 경험담도 다른 수강생들에게 큰 도움이 됩니다. 실패도 소중한 학습 자료예요 💡💬 좋은 질문 예시[진도] 2주차 5강 - React 컴포넌트 생성까지 완료[질문] Cursor에서 버튼 컴포넌트 생성 시 에러 발생상황: 2주차 실습 중 버튼 컴포넌트를 만들려고 하는데프롬프트: "빨간색 버튼 컴포넌트 만들어줘"에러 메시지: [스크린샷 첨부]시도해본 것: GPT에게도 물어봤는데 같은 에러 발생어떻게 해결하면 될까요?