묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨Next + React Query로 SNS 서비스 만들기
tanstack query 타입 지정
"use client"; import {useQuery, useQueryClient} from "@tanstack/react-query"; import {getUserPosts} from "../_lib/getUserPosts"; import Post from "@/app/(afterLogin)/_component/Post"; import {Post as IPost} from "@/model/Post"; type Props = { username: string; } export default function UserPosts({ username }: Props) { const { data } = useQuery<IPost[], Object, IPost[], [_1: string, _2: string, _3: string]>({ queryKey: ['posts', 'users', username], queryFn: getUserPosts, staleTime: 60 * 1000, // fresh -> stale, 5분이라는 기준 gcTime: 300 * 1000, }); const queryClient = useQueryClient(); const user = queryClient.getQueryData(['users', username]); console.log('user', user); if (user) { return data?.map((post) => ( <Post key={post.postId} post={post} /> )) } return null; }import {QueryFunction} from "@tanstack/query-core"; import {Post} from "@/model/Post"; export const getUserPosts: QueryFunction<Post[], [_1: string, _2: string, string]> = async ({ queryKey }) => { const [_1, _2, username] = queryKey; const res = await fetch(`http://localhost:9090/api/users/${username}/posts`, { next: { tags: ['posts', 'users', username], }, cache: 'no-store', }); // The return value is *not* serialized // You can return Date, Map, Set, etc. if (!res.ok) { // This will activate the closest `error.js` Error Boundary throw new Error('Failed to fetch data') } return res.json() } 기존 강의에서의 코드입니다. 제 생각에는 둘 다 타입을 지정해 줘야 할 필요가 있나? 라는 생각이 들어서 getUserPosts의 타입만 설정해봤는데, useQuery부분에서도 data 타입, key에 대한 타입, fn에 타입 모두 정상적으로 적용이 되는 거 같습니다. "use client"; import Post from "@/app/(afterLogin)/_component/Post"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { getUserPosts } from "../_lib/getUserPosts"; type Props = { username: string; }; export default function UserPosts({ username }: Props) { const { data } = useQuery({ queryKey: ["posts", "users", username], queryFn: getUserPosts, staleTime: 60 * 1000, // fresh -> stale, 5분이라는 기준 gcTime: 300 * 1000, }); const queryClient = useQueryClient(); const user = queryClient.getQueryData(["users", username]); console.log("user", user); if (user) { return data?.map((post) => <Post key={post.postId} post={post} />); } return null; } import { Post } from "@/model/Post"; import { QueryFunction } from "@tanstack/query-core"; export const getUserPosts: QueryFunction< Post[], [_1: string, _2: string, username:string] > = async ({ queryKey }) => { const [_1, _2, username] = queryKey; const res = await fetch(`http://localhost:9090/api/users/${username}/posts`, { next: { tags: queryKey, }, cache: "no-store", }); // The return value is *not* serialized // You can return Date, Map, Set, etc. if (!res.ok) { // This will activate the closest `error.js` Error Boundary throw new Error("Failed to fetch data"); } return res.json(); }; 이런식으로 약간 변형을 줘봤는데 기존의 코드 타입 지정과 차이가 있을까요?바꾼 부분은 UserPost에서 타입 지정은 모두 없애줬고, getUserPosts에서 next tags에 queryKey를 그대로 할당했습니다. (간혹 tags의 규칙상 queryKey에서는 가능해도 안되는 경우도 있다고 강의에서 말씀해주셨는데, 대부분의 경우에는 가능하기 때문에 대부분은 이렇게 충분하고 그런 경우에만 별도로 바꿔주면 될 거라고 생각했습니다.)
-
미해결Next + React Query로 SNS 서비스 만들기
서버 컴포넌트 fetch와 클라이언트 컴포넌트 fetch 구분
이전 질문에서 SEO가 필요없는 경우 보통 클라이언트에서 데이터를 가져오는게 더 좋다. 라는 답변을 받았습니다. 그런데 어떤게 서버에서 데이터를 가져오는거고, 어떤게 클라이언트에서 데이터를 가져오는건지가 매우 헷갈리고 있는 상황입니다. react-query를 사용할 때 query가 있는 컴포넌트에 "use client"가 있다면 클라이언트 데이터 fetch라고 보면 될까요? 그렇다면 수업 내용 중 client 컴포넌트에서 데이터를 가져온건 PostRecommends 부분이 유일한가요? 다른 react-query 부분은 모두 "use client"가 상단에 없습니다. (거기에 signup 정도...?)기존의 서버 컴포넌트에서 데이터를 가져오려고 하는데, SEO가 필요 없어 클라이언트 컴포넌트를 선택하고 싶다면, 위에 "use client"를 일부로 적어서 클라이언트 컴포넌트로 만들면 되는게 맞을까요? (데이터 페치 이전에는 함수 같은 것들이 있어서 반드시 바꿔야 되는 경우에만 "use client"를 썼기에, 필수적인게 아닌 제가 선택적으로 바꾸면 되는것인지 헷갈리네요) 컴포넌트 함수에 async를 쓰는 경우도 안쓰는 경우도 있는데, 이건 서버/클라이언트는 무관하게 단순히 async/await를 쓰기 위해 사용하는걸까요?요즘 질문이 많이 생기네요... 항상 감사합니다.
-
미해결Next + React Query로 SNS 서비스 만들기
MSW 사용 대신에 Next에서 제공하는 라우트 핸들러 사용?
https://nextjs.org/docs/app/building-your-application/routing/route-handlers궁금한 점이 있어 의견 여쭈어 보려고 글 남깁니다!공식 문서를 읽어보니 route handlers로도 백엔드를 구현할 수 있는데 MSW 사용 이유는 배포 모드일때는 라우트 핸들러를 적용한 폴더를 삭제를 해줘야하니까 번거롭기 때문에 사용하는 이유도 있다? 라고 봐도 될까요?
-
미해결Next + React Query로 SNS 서비스 만들기
chilrdren, modal의 보여지는 원리가 제가 이해한 것이 맞을까요?
안녕하세요 제로초님.인터넷창에 직접 주소를 입력하거나 새로고침 시 뒤에 배경화면이 사라지는 것에 대하여 질문있습니다. 먼저<Link href='/i/flow/signup' className={styles.signup}>를 클릭 시에는 인터셉터 라우팅이 트리거 되어 src/app/(beforeLogin)/layout.tsx에 있는 children으로 인해 배경화면에 main컴포넌트가 보여지며 인터셉터된 @modal 은 modal부분에 보여집니다. 그런데 직접 주소창에/i/flow/signup' 를 입력하여 접근하거나 새로고침하면 배경화면에 main컴포넌트가 사라지게 되는데 이것의 이유는 직접 접근할 때 인터셉에 걸리지 않게되고, childrend에는 i/flow에 있는 폴더들이 보여지며 defalut.tsx가 배경화면으로 보여지기 때문인가요?
-
미해결Next + React Query로 SNS 서비스 만들기
클라이언드 fetch와 suspense를 이용한 fetch
CSR에서의 data fetch와 suspense 안에 있는 서버컴포넌트의 data fetch는 어떤 차이가 있을까요? SSR이 아닌 CSR을 써야 하는 상황은 위처럼 데이터가 큰 상황들인데, 어차피 suspense를 이용하면 서버에서 fetch가 끝나야 렌더링이 되는게 아니라 로딩으로 되다보니 CSR 대신 suspense를 이용하면 되는거 아닌가 싶습니다. 어떤 차이가 있는지 잘 모르겠어요. CSR을 써서 더 좋은 상황이 어떤게 있을지 모르겠습니다.
-
미해결Next + React Query로 SNS 서비스 만들기
Suspence를 이용한 useSuspence(InfiniteQuery,Query) 부분 질문있습니다.
제로초님 저는 home경로에 Suspence로 감싼 <TabDeciderSuspence/>컴포넌트 안에 <PostRecommends/>, <FollowingPosts/>이 두개의 컴포넌트를 infiniteQuery 적용했습니다. 근데 useSuspenceInfiniteQuery를 적용해보려고 했는데, 적용하지 않아도 강의내용에서 말한 Suspence의 fallback 로딩이 적용되는거 같아요. Suspence가 감싼 하위 컴포넌트는 useSuspence(Query, InfiniteQuery)적용안해도 Suspence적용되나요?const Home = async () => { return ( <main className={style.main}> <TabProvider> <Tab /> <PostForm /> <Suspense fallback={<Loading />}> <TabDeciderSuspense /> </Suspense> </TabProvider> </main> ); };
-
해결됨Next + React Query로 SNS 서비스 만들기
nextjs의 hook을 사용할 때
상위 컴포넌트에서도 useSearchParam을 사용해야 하고, 하위 컴포넌트에서도 useSearchParam을 사용해야 하는 이러한 상황에서, 해당 값을 prop으로 전달할지, 독립적으로 호출할지 고민이 됩니다. 이 정도의 요소는 굳이 prop으로 전달하지 않고 다시 호출해도 유의미한 리소스 차이는 없겠죠?
-
미해결Next + React Query로 SNS 서비스 만들기
다이나믹 라우트 안의 폴더
안녕하세요. /product/[slug]/edit 이런 파일 구조를 가지고 있는데, edit 페이지에서 어떻게 하면, 현재 slug의 dynamic route 값을 가지고 올수 있을까요?edit 에서는 params가 빈 객체로 찍힙니다.미리 감사합니다!
-
해결됨Next + React Query로 SNS 서비스 만들기
서버에서 세션은 어떻게 불러오나요?
클라이언트에서는 useSession인데, 서버에서는 어떻게 불러오나요? getSession이나 getServerSession을 쓰면 되는거 같은데, 그냥 서버 컴포넌트 페이지에서 const A=await getSession()으로 해버리면, 그 다음 console.log(A)에서 pending이 나오더라구요... 서버에서 세션을 호출해서 특정 동작을 하기 위해서는 어떻게 조작해야 할까요? api에 따로 만들어서 route handler을 써야 할까요...? 이 방법도 어려움을 겪고 있긴해서 가장 좋은 방법이 뭔지 궁금합니다.
-
해결됨Next + React Query로 SNS 서비스 만들기
서버는 어떻게 socket을 받는건가요??
좋은 강의 잘 보고 있습니다!혹시 웹소켓을 사용하면서 서버쪽은 어떻게 코드가 구성되는지 알 수 있을까요??
-
미해결Next + React Query로 SNS 서비스 만들기
로딩 페이지, 에러 페이지 질문
React뿐만 아니라 NextJS에서도 <ErrorBoundary fallback={<Error/>}> <Suspense fallback={<Loading/>}> <Page /> </Suspense> </ErrorBoundary>이렇게 컴포넌트 계층 구조를 작성해야 한다는 것인가요? 아니면 그냥 error.tsx, loading.tsx파일만 만들면 알아서 적용이 된다는 것인가요?
-
해결됨Next + React Query로 SNS 서비스 만들기
msw 서버가 작동 안되요
window환경이고 회원가입을 하려고 해도 message가 넘어오지 않아 보니위 메세지도 콘솔에 뜨지않았습니다. Mock server자체가 연결이 안되는 것 같은데 뭐가 문제인지 잘 모르겠습니다. /mocks 폴더안에 파일들은 제로초님 깃헙에서 그대로 복붙하고 signup 관련 파일도 다 복붙했습니다./_lib/signup.ts 는 ts오류가나서 함수 이름만 넣었습니다."use server"; import { redirect } from "next/navigation"; const Submit = async (prevState: any, formData: FormData) => { if (!formData.get("id") || !(formData.get("id") as string)?.trim()) { return { message: "no_id" }; } if (!formData.get("name") || !(formData.get("name") as string)?.trim()) { return { message: "no_name" }; } if ( !formData.get("password") || !(formData.get("password") as string)?.trim() ) { return { message: "no_password" }; } if (!formData.get("image")) { return { message: "no_image" }; } let shouldRedirect = false; try { const response = await fetch( `${process.env.NEXT_PUBLIC_BASE_URL}/api/users`, { method: "post", body: formData, credentials: "include", }, ); console.log(response.status); if (response.status === 403) { return { message: "user_exists" }; } console.log(await response.json()); shouldRedirect = true; } catch (err) { console.error(err); return; } if (shouldRedirect) { redirect("/home"); // try/catch문 안에서 X } }; export default Submit; 아래는 제 package.json입니다. .env.localsubmit 눌렀을 때 네트워크
-
해결됨Next + React Query로 SNS 서비스 만들기
useInifiniteQuery queryKey 타입 지정 질문
검색 결과를 인피니트 스크롤로 바꾸던중에기존에 getSearchResult에서 queryKey 타입을QueryFunction을 이용해서 지정해주셨는데pageParam의 타입도 지정하는 방법이 따로 있을까요? 아니면 위와 같이 타입 지정을 해줘도 되는지 궁금합니다!
-
해결됨Next + React Query로 SNS 서비스 만들기
target으로 받아서 쓰는 이유는 뭔가요?
나중에 props로 받은 post를 target에 할당해서 사용하는 거로 바뀌던데 target에 담아서 사용하시는 이유가 궁금합니다.
-
미해결Next + React Query로 SNS 서비스 만들기
다크모드
@media (prefers-color-scheme: dark) { html { color-scheme: dark; } }다크모드 관련 css 수정하지 않았는데, 다크모드일 경우 색이 적용안되는 경우 이유를 알 수 있을까요?
-
해결됨Next + React Query로 SNS 서비스 만들기
SSR vs CSR
강의 영상 3분에 나온 SSR이 프론트 서버에 부담이 된다 라는 얘기가 잘 이해가 안가서 질문드립니다! 오히려 SSR은 프론트에서 모두 다운받아야 할 JS를 사전에 렌더링하고, query 코드를 읽지도 않기 때문에 더 부담이 안되지 않을까요...?? 또한 말씀하신 SEO 뿐만 아니라 suspense를 사용하거나 서버 액션을 통해 DB와 api 없이도 직접 통신할 수 있는 등의 장점이 있기에 자주 fetch를 해야 하는 작업이 아니라면 SSR의 장점이 더 많은게 아닌지 궁금합니다! CSR을 사용했을때의 장점은 fetch를 자주해야 하는 상황이 아니라면 어떤게 있는지 모르겠습니다.
-
미해결Next + React Query로 SNS 서비스 만들기
url을 통한 반응과 state를 이용한 반응 차이 관련 질문
수업을 진행하다가 그 당시에도 궁금즘이 생겨 개인적으로 알아봤던 부분인데, 확신이 안가서 강사님께 여쭈어봅니다. 수업 내용에서는 정확한 위치가 기억이 나지 않아서 다른 예시로 대체하겠습니다. 흰색 배경의 button group이 있고 각각의 button은 클릭할 시 url을 변경시킵니다.또한 현재 선택된 button은 색상이 칠해집니다. 이러한 상황에서 useState를 통해서 button의 state를 관리하고 있었고, button을 클릭했을때setState를 통해 선택하는 button을 변경함router을 통해 url 경로를 변경함이렇게 두가지 액션을 취했었습니다. 그 때 생겼던 궁금중은 어차피 url과 button은 mapping 할 수 있으니까, 버튼을 클릭하면 url만 변경시키고, url을 읽어서 button에 다시 값을 주면 기능적으로 똑같지 않나? 그러면 하나의 액션으로 기존의 두가지 액션을 대체할 수 있지 않나? 라고 생각했습니다. 그래서 조금 찾아보니까 url을 바꾸고 그 값을 통해 button의 상태 관리를 다시 하는건 즉각적인 반응이 아니고, 영상에서 봤던 것 처럼 url과 button state를 각각 바꾸는게 더 인터랙티브하다 라는 글을 읽었습니다. (신빙성이 있는 글은 아닙니다.) 실제로 이러한 이유 때문에 url만 바꾸고, 그 값을 받아와 button 값을 할당하는게 아니라, 두가지를 모두 동시에 바꾸는게 더 좋은 방법이 맞는건지 궁금합니다.
-
미해결Next + React Query로 SNS 서비스 만들기
nav 버튼들 분기에 관한 질문이 있습니다.
{segment === 'home' ? <> <svg width={26} viewBox="0 0 24 24" aria-hidden="true" className="r-18jsvk2 r-4qtqp9 r-yyyyoo r-lwhw9o r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-cnnz9e"> <g> <path d="M12 1.696L.622 8.807l1.06 1.696L3 9.679V19.5C3 20.881 4.119 22 5.5 22h13c1.381 0 2.5-1.119 2.5-2.5V9.679l1.318.824 1.06-1.696L12 1.696zM12 16.5c-1.933 0-3.5-1.567-3.5-3.5s1.567-3.5 3.5-3.5 3.5 1.567 3.5 3.5-1.567 3.5-3.5 3.5z"></path> </g> </svg> <div style={{fontWeight: 'bold'}}>홈</div> </> : <> <svg width={26} viewBox="0 0 24 24" aria-hidden="true" className="r-18jsvk2 r-4qtqp9 r-yyyyoo r-lwhw9o r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-cnnz9e"> <g> <path d="M12 9c-2.209 0-4 1.791-4 4s1.791 4 4 4 4-1.791 4-4-1.791-4-4-4zm0 6c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2zm0-13.304L.622 8.807l1.06 1.696L3 9.679V19.5C3 20.881 4.119 22 5.5 22h13c1.381 0 2.5-1.119 2.5-2.5V9.679l1.318.824 1.06-1.696L12 1.696zM19 19.5c0 .276-.224.5-.5.5h-13c-.276 0-.5-.224-.5-.5V8.429l7-4.375 7 4.375V19.5z"></path> </g> </svg> <div>홈</div> </> }강사님께서는 위 코드처럼 세그먼트에 따라 삼항연산자를 이용하여 아이콘이 들어있는 전체를 렌더링하셨는데요,style={{fontWeight: segment === 'home' ? 'bold' : 'initial'}}위 처럼 똑같이 삼항 연산자를 이용하되, style, svg path 등 필요한 부분만 유동적으로 변하도록 하지 않으신 특별한 이유가 있으신지 궁금합니다.
-
해결됨Next + React Query로 SNS 서비스 만들기
next/Image와 <img>의 사용하시는 기준이 있을까요?
뒤에서 수정이 되는지는 잘 모르겠지만 현재까지 강의에서는 양쪽 다 사용하시는 것 같습니다. 혹시 따로 구분하신다면 기준을 갖고 쓰시는지 궁금합니다.
-
해결됨Next + React Query로 SNS 서비스 만들기
dayjs 플러그인 질문있습니다.
dayjs를 사용하시기전에 dayjs.locale("ko"); dayjs.extend(relativeTime); 이렇게 쓰셧는데 dayjs를 매번 쓸때마다 컴포넌트에서 위코드가 들어가야하는지 궁금합니다.