inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

176만명의 커뮤니티!! 함께 토론해봐요.

수파베이스 데모 버전

해결됨

한 입 크기로 잘라먹는 React.js 실전 프로젝트 - SNS 편

모든 기능들을 실행하면 계속 이렇게 뜨네요 ㅠㅠ

  • react
  • typescript
  • react-query
  • supabase
  • zustand
키키키키키키키 댓글 1 좋아요 0 조회수 42

modal-root질문드립니다.

해결됨

한 입 크기로 잘라먹는 React.js 실전 프로젝트 - SNS 편

안녕하세요 강사님 강의처럼 따라후 돔요소를보니까 modal-root div안에 dialog가 있는게 아닌 body아래 독립적으로 존재하고있는데요 이러면 createportal을 왜쓰는건지 잘 이해가안갑니다.. import { ImageIcon } from "lucide-react"; import { Button } from "../ui/button"; import { Dialog, DialogContent, DialogTitle } from "../ui/dialog"; import { usePostEditorModal } from "@/store/post-editor-modal"; export default function PostEditorModal() { const { isOpen, close } = usePostEditorModal(); const handleCLoseModal = () => { close(); }; return ( <Dialog open={isOpen} onOpenChange={handleCLoseModal}> <DialogContent> <DialogTitle>포스트 작성</DialogTitle> <textarea /> <Button> <ImageIcon /> 이미지 추가 </Button> <Button>저장</Button> </DialogContent> </Dialog> ); }

  • react
  • typescript
  • react-query
  • supabase
  • zustand
나마스테 댓글 2 좋아요 0 조회수 70

모달 여러개 질문드립니다

해결됨

한 입 크기로 잘라먹는 React.js 실전 프로젝트 - SNS 편

안녕하세요 강사님 너무좋은강의 잘보고있습니다 궁금한점은 모달 UI가 페이지마다 다른경우 ( 모달이 여러개인경우 ) 실무에서는 모든 모달을 스토어에 등록하는형식으로 진행하는지 아니면 common-editor-modal같은 컴포넌트에 children을받고 사용하는 페이지컴포넌트에서 그 내부 디자인만 짜고 open등은 한개의 스토어로 관리하는지 궁금합니다

  • react
  • typescript
  • react-query
  • supabase
  • zustand
나마스테 댓글 2 좋아요 0 조회수 57

tsconfig.app.json 파일 설정(경로 별칭 옵션) 관련 질문입니다.

해결됨

한 입 크기로 잘라먹는 React.js 실전 프로젝트 - SNS 편

# 질문 1 "baseUrl": ".", "paths": { "@/*": ["./src/*"] } 해당 코드를 말씀 하신대로 tsconfig.app.json 파일의 "compilerOptions" 속성의 가장 마지막에 작성하였습니다. 그런데 "baseUrl": "." 부분에 빨간줄이 뜨면서 "'baseUrl’ 옵션은 더 이상 사용되지 않으며 TypeScript 7.0에서 작동하지 않습니다. 이 오류를 무시하려면 compilerOption '"ignoreDeprecations": "6.0"'을(를) 지정합니다.마이그레이션 정보를 보려면 https://aka.ms/ts6을 방문하세요." 오류가 발생합니다. TypeScript 7.0 관련 오류가 났을때 해결방법이 궁금합니다. # 질문 2 이전 시간에서 tsconfig.json 파일에서 오류가 뜨는 경우 Ctrl+Shift+P -> select type 을 통해 TypeScript 버전과 호환성을 맞추라고 말씀해주셨는데요! 그런데 강의에서는 "작업 영역 버전 사용" 항목을 선택하셨었는데, 저는 작업 영역 버전 사용이라는 항목이 뜨질 않네요... 이대로 넘어가도 괜찮은지도 궁금합니다! "VS Code의 버전 사용: 6.0.3"이 떠서 체크했더니 빨간줄은 사라졌습니다. -> VSCode를 껐다 켜니 tsconfig.node.json 파일에도 빨간줄이 뜨는 상황입니다.

  • react
  • typescript
  • react-query
  • supabase
  • zustand
박준형 댓글 2 좋아요 0 조회수 75

onSettled 질문드립니다.

해결됨

한 입 크기로 잘라먹는 React.js 실전 프로젝트 - SNS 편

이전에 onSuccess에서 window.location.reload 하던걸 invalidateQueries로 변경하셨는데 그 이후에 성공할때마다 캐시값을 갱신시키면 부하가있을수있으니 낙관적업데이트로 변경한다고 들었는데요 4.10강좌 캐시데이터 다루기4에서 마지막에 onSettled 함수를통해 데이터 수정이 성공하나 실패하나 무조건 실행되는데 이러면 똑같이 데이터가 크면 부하가있는게 맞을까요? 실무에서도 저러한 방향으로 하는지 궁금합니다.

  • react
  • typescript
  • react-query
  • supabase
  • zustand
나마스테 댓글 2 좋아요 0 조회수 68

디비를 조작하는데 사용하는 명령어가 ORM인가요?

미해결

AI 시대에 살아남기: Supabase로 백엔드 뚝딱!

Supabase JS는 ORM이 아니라하던데, 현재 강의에서 디비를 조작하는데 사용하는 문법이 뭔가요 그럼

  • node.js
  • dbms/rdbms
  • oauth
  • backend
  • supabase
Mytoggi 댓글 2 좋아요 0 조회수 67

커서 기본 세팅 질문

미해결

비개발자 4주만에 수익화 서비스 만들기: AI 바이브코딩 웹 + 앱 ALL IN ONE

안녕하세요. 한국어 설정을 어떻게 하는지 알려주실 수 있으실까요? 자동으로 뜨지 않아서요 ㅠ 다운받은 프로그램에서 폴더 열기까지했는데 오른쪽 마우스 눌러서 새파일 누르기? 이게 안됩니다 ㅠ 오른쪽 마우스를 눌러도 아무것도 안나와서요. ㅠㅠ

  • flutter
  • next.js
  • cursor
  • supabase
  • 바이브코딩
Sunny 댓글 2 좋아요 0 조회수 127

만일 실물을 택배로 배송해야 할 경우 주소지 입력하는 방법이 궁금해서요.

해결됨

결제 받고 출시까지, 클로드 코드로 완성하는 내 웹서비스

바이브 플러그님. 복습하다가 이런저런 질문이 생겨서요. 지금 예제 강의는 디지털상품이라 배송이 필요가 없는데, 만일 실제 물건을 보내야 하는 상황이면 구매자가 받을 주소를 입력할 창이 필요할 텐데, 좋은 방법이 있을까요? 실무에서는 보통 어떤 방법을 쓰시나요? 제 생각에는 택배보낼 곳 DB에는 기존에 이름과, 결재승인여부는 이미 확인했고(다른 테이블에서) 전화번호, 우편번호, 받을 주소 3개의 컬럼을 추가하면 될 것 같은데. 택배 배송을 위한 테이블만들 때 특별한 팁이 있나요? 왜 궂이 물어보냐하면, 우편번호는 우체국에 DB가 있을 것같고, 주소에 몇글자만 타이핑하면 우편번호와 기본주소를 가져오고, 세부주소를 타이핑하는거라서 좀 더 쉽게 하는 방법이 없나 해서요.

  • HTML/CSS
  • typescript
  • next.js
  • tailwindcss
  • supabase
  • claude
  • 바이브코딩
좋은하루 댓글 4 좋아요 1 조회수 101

31강 학습자료에 프롬프트가 엉뚱한것이 있어요

해결됨

결제 받고 출시까지, 클로드 코드로 완성하는 내 웹서비스

강의 잘 듣고 있습니다. 31강 영상에는 profiles 테이블에 역할을 저장할 role 컬럼을 추가해 줘... 로 시작되는 프롬프트인데 하단 학습자료에는 이전 시간에 했던, profiles 테이블 내용이 있습니다. 수정 부탁드려요

  • HTML/CSS
  • typescript
  • next.js
  • tailwindcss
  • supabase
  • claude
  • 바이브코딩
좋은하루 댓글 1 좋아요 1 조회수 68

강의 소스 코드는 어디서 볼수 있나여?

해결됨

결제 받고 출시까지, 클로드 코드로 완성하는 내 웹서비스

소스 코드는 어디서 볼수 있나여>?

  • HTML/CSS
  • typescript
  • next.js
  • tailwindcss
  • supabase
  • claude
  • 바이브코딩
김동선 댓글 1 좋아요 1 조회수 73

17강 강의에 목데이터 첨부파일이 없습니다.

해결됨

결제 받고 출시까지, 클로드 코드로 완성하는 내 웹서비스

목데이터가 찾을 수 가 없네요~~

  • HTML/CSS
  • typescript
  • next.js
  • tailwindcss
  • supabase
  • claude
  • 바이브코딩
땀모 댓글 2 좋아요 2 조회수 94

에이전트 에러

미해결

클로드 코드 완벽 가이드: 기초부터 서비스 배포까지

저 에러는 왜 뜨는 걸까요 ㅜㅜ 그리고 한국어로 어떻게 뜨게 하죠?

  • next.js
  • supabase
  • 인공지능(ai)
  • ai-agent
  • claude
  • 바이브코딩
  • ax(에이전트-경험)
gugugu2441 댓글 1 좋아요 0 조회수 89

커스텀 에이전트 생성하기

미해결

클로드 코드 완벽 가이드: 기초부터 서비스 배포까지

슬래시 에이전트 입력했는데 강사님 화면이랑 다르게 떠서요

  • next.js
  • supabase
  • 인공지능(ai)
  • ai-agent
  • claude
  • 바이브코딩
  • ax(에이전트-경험)
gugugu2441 댓글 1 좋아요 0 조회수 67

클로드 코드 시작하기

해결됨

클로드 코드 완벽 가이드: 기초부터 서비스 배포까지

스타트 파일 열고 터미널 여신 거 어떻게 하는 거죠? 단축키인가요?? 맥입니다

  • next.js
  • supabase
  • 인공지능(ai)
  • ai-agent
  • claude
  • 바이브코딩
  • ax(에이전트-경험)
gugugu2441 댓글 1 좋아요 0 조회수 64

Zustand의 Store 타입은 어떤 기준으로 작성하는 건가요?

해결됨

한 입 크기로 잘라먹는 React.js 실전 프로젝트 - SNS 편

안녕하세요, 선생님. Zustand 스토어에 타입을 지정하는 부분이 궁금해서 질문드립니다. 강의에서는 다음과 같이 상태와 액션을 Store 타입으로 선언한 뒤, create 함수의 제네릭으로 전달했습니다. type Store = { count: number; increase: () => void; decrease: () => void; }; const useStore = create<Store>((set, get) => ({ count: 0, increase: () => { const count = get().count; set({ count: count + 1 }); }, decrease: () => { set((store) => ({ count: store.count - 1, })); }, })); 처음 코드를 작성했을 때는 get() 의 반환값과 set 의 콜백 매개변수인 store 에서 타입 오류가 발생해서, 저는 해당 부분마다 타입을 직접 지정해야 한다고 생각했습니다. 그런데 강의를 보니 놀랍게도 create<Store> 처럼 제네릭만 지정해도 set 과 get 에 관련된 타입 오류가 모두 해결되었습니다. 여기서 제가 궁금한 점은 다음과 같습니다. 1. Store 타입에는 왜 count , increase , decrease 처럼 스토어 객체에 들어갈 상태와 액션만 작성하면 되는 건가요? 2. 처음 Zustand를 사용하는 사람은 Store 타입을 이런 형태로 작성해야 한다는 것을 공식 문서의 TypeScript 예제를 보고 알게 되는 건가요? 3. 아니면 패키지의 .d.ts 나 .d.mts 같은 타입 선언 파일을 직접 확인하고, create 와 StateCreator 의 타입 구조를 해석해서 작성하는 건가요? 4. create<Store> 에 지정한 타입이 내부의 set , get , 그리고 set 콜백의 store 타입까지 전달되기 때문에 오류가 해결된 것인지도 궁금합니다. 실제로 라이브러리를 사용할 때는 공식 문서의 사용법을 먼저 따라 하고, 타입이 적용되는 원리가 궁금하거나 오류가 발생했을 때 타입 선언 파일을 확인하는 방식이 일반적인지도 궁금합니다. AI가 아닌 정환선생님이 직접 답변 부탁드리겠습니다.

  • react
  • typescript
  • react-query
  • supabase
  • zustand
유혁스쿨 댓글 2 좋아요 0 조회수 97

타입 에러 관련 질문입니다.

미해결

Supabase, Next 풀 스택 시작하기 (feat. 슈파베이스 OAuth, nextjs 14)

todoList 생성하기 에서 content가 계속 타입 에러가 뜨는데 이유가 뭘까요?

  • react
  • 클론코딩
  • next.js
  • supabase
홍정웅 댓글 2 좋아요 1 조회수 74

마지막 강의 잘림

해결됨

AI 주식 자동 매매: Claude Code 하나로 완성하는 주식 자동매매 시스템 구축하기

마지막 강의가 잘린 것 같은데 올라오나요?

  • supabase
  • nextjs
  • ai-agent
  • mcp
  • claude
파라라라 댓글 1 좋아요 0 조회수 71

포스트 작성 중 이탈 방지 기능 (취소 버튼 클릭 시 오류)

해결됨

한 입 크기로 잘라먹는 React.js 실전 프로젝트 - SNS 편

안녕하세요 정환님, 이렇게 바로 또 질문을 드릴 줄은 몰랐는데.. 이번 포스트 작성 중 이탈 방지 기능 개발을 하다가 "확인 버튼"을 누르게 되면 정상적으로 모든 모달이 종료가 되지만, "취소 버튼"을 누르게 되면 AlertModal이 종료되지 않고 계속 리렌더링이 되는 현상이 발생합니다ㅠㅠ 해당 부분에 대해 저번처럼 메일로 프로젝트 파일을 압축해서 보내드려도 되는지 여쭤봅니다!

  • react
  • typescript
  • react-query
  • supabase
  • zustand
rkdla666 댓글 2 좋아요 0 조회수 102

"포스트 생성에 실패했습니다" 실패 문구와 함께 에러가 발생합니다ㅠㅠ

해결됨

한 입 크기로 잘라먹는 React.js 실전 프로젝트 - SNS 편

안녕하세요 정환님! 정환님의 강의를 들으면서 코드를 따라 작성해보다가 포스트와 이미지를 최종적으로 업로드 하는 과정에서 아래의 캡쳐 사진과 같이 포스트 생성에 실패했다는 에러 메시지가 뜨게됩니다. 네트워크 탭에 보면, 포스트 부분은 잘 전달이 되는거같은데 이미지 생성에 관한 결과가 보이지 않는 것으로 보아 이미지 생성 관련 코드에서 문제가 생긴것같은데 무슨 문제일까요??..ㅠ 아래는 해당 코드들입니다. 이미지 생성 관련 코드를 가져왔는데 혹여나 다른 부분의 코드가 필요하면 추가 업로드 드리겠습니다. api/post.ts import type { PostEntity } from './../types'; import supabase from '@/lib/supabase'; export async function createPost(content: string) { const { data, error } = await supabase .from('post') .insert({ content }) .select() .single() if (error) throw error return data } export async function createPostWithImages({ content, images, userId }: { content: string images: File[] userId: string }) { // 1. 새로운 포스트 생성 (맨 위에서 생성한 포스트 비동기 함수 가져오기) const post = await createPost(content) if (images.length === 0) return post // 2. 이미지 업로드 try { const imageUrls = await Promise.all( images.map((image) => { const fileExtension = image.name.split(".").pop() || "webp" const fileName = `${Date.now()}-${crypto.randomUUID()}.${fileExtension}` const filePath = `${userId}/${post.id}/${fileName}` return uploadImage({ file: image, filePath }) }) ) // 3. 포스트 테이블 업데이트 const updatedPost = await updatePost({ id: post.id, image_urls: imageUrls }) return updatedPost } catch(error) { await deletePost(post.id) throw error } } export async function updatePost(post: Partial<PostEntity> & { id: number }) { const { data, error } = await supabase .from("post") .update(post) .eq("id", post.id) .select() .single() if (error) throw error return data } export async function deletePost(id: number) { const { data, error } = await supabase .from("post") .delete() .eq("id", id) .select() .single() if (error) throw error return data } hooks/mutations/post/use-create-post.ts import type { UseMutationCallback } from './../../../types'; import { createPost, createPostWithImages } from '@/api/post'; import { useMutation } from '@tanstack/react-query'; export function useCreatePost(callbacks?:UseMutationCallback) { return useMutation({ mutationFn: createPostWithImages, onSuccess: () => { if(callbacks?.onSuccess) callbacks.onSuccess() }, onError: (error) => { if (callbacks?.onError) callbacks.onError(error) } }) } components/modal/post-editor-modal.tsx import { Button } from '@/components/ui/button' import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog' import { useCreatePost } from '@/hooks/mutations/post/use-create-post' import { usePostEditorModal } from '@/store/post-editor-modal' import { useSession } from '@/store/session' import { ImageIcon, XIcon } from 'lucide-react' import { useRef, useState, useEffect, ChangeEvent } from 'react' import { toast } from "sonner" import { Carousel, CarouselContent, CarouselItem } from '../ui/carousel' type Image = { file: File, previewUrl: string } export default function PostEditorModal() { const session = useSession() const { isOpen, close } = usePostEditorModal() const { mutate: createPost, isPending: isCreatePostPending } = useCreatePost({ onSuccess: () => { close() }, onError: (error) => { toast.error("포스트 생성에 실패했습니다", { position: "top-center" }) } }) const [content, setContent] = useState("") const [images, setImages] = useState<Image[]>([]) const textareaRef = useRef<HTMLTextAreaElement>(null) const fileInputRef = useRef<HTMLInputElement>(null) const handleCloseModal = () => { close() } const handleCreatePostClick = () => { if (content.trim() === "") return createPost({ content, images: images.map((image) => image.file), userId: session!.user.id }) } const handleSelectImages = (e:ChangeEvent<HTMLInputElement>) => { if (e.target.files) { const files = Array.from(e.target.files) files.forEach((file) => { setImages((prev) => [ ...prev, { file, previewUrl: URL.createObjectURL(file) }, ]) }) } e.target.value = "" } const handleDeleteImage = (image:Image) => { setImages((prevImages) => prevImages.filter((item) => item.previewUrl !== image.previewUrl)) } useEffect(() => { if (textareaRef.current) { textareaRef.current.style.height = "auto" textareaRef.current.style.height = textareaRef.current.scrollHeight + "px" } }, [content]) useEffect(() => { if (!isOpen) return textareaRef.current?.focus() setContent("") setImages([]) }, [isOpen]) return ( <Dialog open={isOpen} onOpenChange={handleCloseModal}> <DialogContent className="max-h-[90vh]"> <DialogTitle>포스트 작성</DialogTitle> <textarea disabled={isCreatePostPending} ref={textareaRef} value={content} onChange={(e) => setContent(e.target.value)} className="max-h-125 min-h-25 focus:outline-none" placeholder="무슨 일이 있었나요?" /> <input onChange={handleSelectImages} ref={fileInputRef} type="file" accept="image/*" multiple className="hidden" /> {images.length > 0 && <Carousel> <CarouselContent> {images.map((image) => <CarouselItem className="basis-2/5" key={image.previewUrl}> <div className="relative"> <img src={image.previewUrl} className="h-full w-full rounded-sm object-cover" /> <div onClick={() => handleDeleteImage(image)} className="absolute top-0 right-0 m-1 cursor-pointer rounded-full bg-black/30 p-1" > <XIcon className="h-4 w-4 text-white"/> </div> </div> </CarouselItem>)} </CarouselContent> </Carousel>} <Button onClick={() => { fileInputRef.current?.click() }} variant={"outline"} className="cursor=pointer" > <ImageIcon/> 이미지 추가</Button> <Button disabled={isCreatePostPending} onClick={handleCreatePostClick} className="cursor=pointer"> 저장 </Button> </DialogContent> </Dialog> ) }

  • react
  • typescript
  • react-query
  • supabase
  • zustand
rkdla666 댓글 2 좋아요 0 조회수 104

플러터 세팅 후 새폴더 생성건

해결됨

비개발자 4주만에 수익화 서비스 만들기: AI 바이브코딩 웹 + 앱 ALL IN ONE

현재 수강 진도를 함께 알려주세요! 29. 4-1. 🤳 웹에서 앱으로의 대전환 - Flutter 개발환경 세팅(15:46초 진도) 구체적인 상황과 함께 질문해주세요! 플러터 셋팅 후 새폴더를 만드는데 검색>flutter> 관련 선택지가 강의안에서 처럼 안나와요. 상관없는건지, 잘못세팅이 된건지요?

  • flutter
  • next.js
  • cursor
  • supabase
  • 바이브코딩
Moon Hole 댓글 2 좋아요 0 조회수 103

인기 태그

인프런 TOP Writers

주간 인기글