"홈탭 만들면서 Context API" 강좌를 듣고 localhost3000/home에 들어가면 localhost3000/[username] 경로로 들어가지다가(화면에 '프로필 페이지'라고 뜨는 것을 보니 이런 것 같습니다! ) 화면이 빈 화면으로 바뀝니다.. 그리고 왼쪽 섹션에 있는 프로필을 클릭하면 아래와 같은 오류가 뜹니다 ㅠ 무슨 문제일까요? 오류 내용 : ⨯ Error: Cannot find module '/Users/ryuhojun/Documents/z-com/.next/server/app/(afterLogin)/[username]/page.js' Require stack: - /Users/ryuhojun/Documents/z-com/node_modules/next/dist/server/require.js - /Users/ryuhojun/Documents/z-com/node_modules/next/dist/server/load-components.js - /Users/ryuhojun/Documents/z-com/node_modules/next/dist/build/utils.js - /Users/ryuhojun/Documents/z-com/node_modules/next/dist/server/dev/hot-middleware.js - /Users/ryuhojun/Documents/z-com/node_modules/next/dist/server/dev/hot-reloader-webpack.js - /Users/ryuhojun/Documents/z-com/node_modules/next/dist/server/lib/router-utils/setup-dev-bundler.js - /Users/ryuhojun/Documents/z-com/node_modules/next/dist/server/lib/router-server.js - /Users/ryuhojun/Documents/z-com/node_modules/next/dist/server/lib/start-server.js
깃허브에 올려놓은 소스(next-app-router-z /ch3-1)을 다운받은후에 403 에러발생을 확인하기 위해서 아래의 주석을 해제했습니다. src/mocks/handlers.ts http.post('/api/users', async ({ request }) => { console.log('회원가입'); return HttpResponse.text(JSON.stringify('user_exists'), { status: 403, }) }) }), PostMan 에서 http://localhost:9090/api/users?id=js&password=pass&name=js7777 호출을 하면 status 값이 의도한 대로 403 Forbidden 이 출력이 됩니다. 그런데, 브라우저 개발자모드 Network 에서 보면 Status 값이 200 으로 출력됩니다. 서버에서는 분명 403 상태로 보냈고, PostMan에서도 403으로 상태값이 넘어오는데, 왜? 개발자 도구(Network)에서만 상태값이 200으로 출력되는지 모르겠습니다.
csr 에서는 useQueryClient로 생성된 QueryClient를 가져와 사용하는 반면에 ssr 에서 prefetch 할 때에는 QueryClient 를 새로 생성해서 사용하시더라구요. 그럼 ssr에서 생긴 QueryClient csr에서 생긴 QueryClient 두개가 존재하게 되는데, 리액트쿼리가 hydrate 하는 과정에서 알아서 합쳐주는 건지 그 원리가 궁금합니다. 2. prefetch를 할 때마다 QueryClient를 새로 생성해야 하는지 아니면 ssr에서 사용할 QueryClient를 하나 생성해서 공유하는 방식으로 사용해야 하는 것인지, 또 공유해서 사용한다면 예제가 있을까요? 만약 prefetch 할 때마다 QueryClient를 새로 생성해야 한다면 성능상에 문제는 없을까요? prefetch를 난발하는 것을 멈추고 조심히 사용해야 할까요? 강의 덕분에 많이 배웠습니다. 좋은 강의 감사합니다.
./src/_components/Carousel.tsx 110:6 Warning: React Hook useEffect has a missing dependency: 'nextFn'. Either include it or remove the dependency array. react-hooks/exhaustive-deps (....lint warning문구 생략) info - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rules Linting and checking validity of types .Failed to compile. ./src/_components/Carousel.tsx:137:12 Type error: 'Arrow' cannot be used as a JSX component. Its type 'FC<PropsWithChildren<ArrowProps>>' is not a valid JSX element type. Type 'FunctionComponent<PropsWithChildren<ArrowProps>>' is not assignable to type '(props: any, deprecatedLegacyContext?: any) => ReactNode'. Type 'ReactElement<any, any> | null' is not assignable to type 'ReactNode'. Type 'ReactElement<any, any>' is not assignable to type 'ReactNode'. Property 'children' is missing in type 'ReactElement<any, any>' but required in type 'ReactPortal'. 135 | className={`h-full w-full ${inArrow ? 'absolute' : ''} max-w-full`}> 136 | {!!showNavButton && ( > 137 | <Arrow | ^ 138 | direction="left" 139 | executeFn={prevFn} 140 | inArrow={inArrow} error Command failed with exit code 1. 'use client'; import { FC, PropsWithChildren, useEffect, useState } from 'react'; interface ArrowProps { direction: 'left' | 'right'; executeFn: () => void; inArrow?: boolean; hoverStyle?: string; } const Arrow: FC<PropsWithChildren<ArrowProps>> = ({ direction, executeFn, inArrow, hoverStyle, children, ...props }) => { const [hoverColor, setHoverColor] = useState(hoverStyle || undefined); useEffect(() => { hoverStyle && setHoverColor(`hover:${hoverStyle}`); }, [hoverStyle]); const returnString = direction === 'left' ? '<' : '>'; return ( <div onClick={executeFn} className={`${inArrow ? 'absolute z-50' : ''} ${direction === 'left' ? 'left-0 top-0 rounded-l-lg' : 'right-0 top-0 rounded-r-lg'} center-vertical flex h-full w-[30px] cursor-pointer text-[30px] ${hoverColor && hoverColor}`} {...props}> {returnString} {children} </div> ); }; export default Arrow; next build를 했을때 해당 에러가 Arrow컴포넌트에서 발생하였습니다. Arrow컴포넌트에서 제가 정의한 FC<PropsWithChildren<ArrowProps>>타입이 유효한 JSX element type이 아니라는 메시지 인거 같습니다. 이 에러가 나는 이유가 유효한 JSX엘리먼트가 아니어서 일것같아서 return 하는 jsx문법에 오류가 있는지 확인하려 div 겉에도 fragment로 감싼다거나 returnString을 해주는 중괄호 부분도 fragment로 감싸거나 children도 감싸보았습니다. 그러나 똑같은 에러가 발생하고 있는 상황입니다. const returnString = direction === 'left' ? '<' : '>'; 혹시 위의 코드가 문제가 발생할까 싶어서 SVG파일을 만들어 조건에따라 왼쪽 오른쪽 SVG 파일 컴포넌트를 return 문 안에서 렌더링 해주었는데 여기서도 동일한 에러가 발생하였습니다. Type error: 'LeftSvg' cannot be used as a JSX component. Its type '({ className, width, height, onClick, cyAttribute, }: { className?: string | undefined; width?: number | undefined; height?: number | undefined; onClick?: (() => void) | undefined; cyAttribute?: string | undefined; }) => JSX.Element' is not a valid JSX element type. Type '({ className, width, height, onClick, cyAttribute, }: { className?: string | undefined; width?: number | undefined; height?: number | undefined; onClick?: (() => void) | undefined; cyAttribute?: string | undefined; }) => JSX.Element' is not assignable to type '(props: any, deprecatedLegacyContext?: any) => ReactNode'. Type 'Element' is not assignable to type 'ReactNode'. Property 'children' is missing in type 'Element' but required in type 'ReactPortal'. 24 | }, [hoverStyle]); 25 | > 26 | const returnString = direction === 'left' ? <LeftSvg /> : <RightSvg />; | ^ 27 | 28 | return ( 29 | <div error Command failed with exit code 1. 참고로 'DatePicker' cannot be used as a JSX component. Its instance type 'ReactDatePicker<undefined, undefined>' is not a valid JSX element. 이런 에러가 타입에러 발견 된 적이 있어서 package.json파일에 "resolutions": { "@types/react": "^18.0.0" }, resolutions로 버전을 위와 같이 맞춰주어서 해결한 적이 있습니다.
현재 X 프로젝트에서는 게시글 검색 및 필터 기능을 다른 페이지로 가게끔 설계가 되있는데요! 이와 같은 방식은 검색 데이터와 필터 데이터를 브라우저 주소에 관리하는 방식이라고 생각합니다. (맞게 생각하고 있는건지?) 현재 제가 팀 프로젝트로 여러개의 탭 중 커뮤니티 탭을 구현하고 있는데 커뮤니티 탭안에서만 검색 및 필터 기능을 구현하고 있습니다. 여기서 궁금증이 커뮤니티 굳이 브라우저 주소를 변경하지 않고 클라이언트 상태관리로 검색값 필터 값을 관리해도 되는걸까요? 정리해보자면 브라우저 주소로 검색 값 및 필터 값 관리 클라이언트 데이터로 검색 값 및 필터 값 관리 둘 중 어떤 게 더 좋은 방식인지 궁금합니다. 제가 생각했을때는 검색 및 필터 기능 사용 시 다른 페이지로 이동시키는건 전체 페이지가 리페인트되기 때문에 클라이언트 상태 관리보다 좋지 않은 방식인거 같은데 이점이 있는걸까요?
안녕하세요, 강사님 강의 덕분에 nextjs와 next-auth, msw를 프로젝트에 잘 적용할 수 있게 되었습니다. 그런데 현재 프로젝트에서 문제가 있었고 궁금한 점이 생겨 이렇게 질문을 남기게 되었습니다. 프로젝트에서 로그인 인증을 jwt 대신 쿠키를 사용하게 되었고 oauth를 통해 로그인하면 백엔드에서 set-cookie를 통해 쿠키를 set, 보내주는 상황이 되었습니다. 이 때, nextjs에서 클라이언트 api 요청을 보낼 때 쿠키에 직접적으로 접근하지 않아도 자동으로 브라우저에서 요청할 때마다 쿠키를 같이 보내준다고 이해했는데 혹시 제가 이해한게 틀렸을까요? 프로젝트를 진행하면서 쿠키가 백엔드에게 보내는 요청에 담기지 않아 결국 서버액션을 사용해서 쿠키를 헤더에 담아서 보내는 방식으로 변경되었습니다. 클라이언트 요청에서 쿠키를 직접 (상수 값으로) 헤더에 담아서 요청을 보내도 서버에서 아무 값을 받지 못한다고 하는데 백엔드쪽을 잘 모르니 프론트 쪽에서 수정하는 방향으로 틀어서 프로젝트는 완료한 상황입니다. next-auth도 결국 걷어낸 상황이 되었는데, next-auth와 함께 쿠키를 사용하려면 백엔드에서 set 해 준 쿠키를 직접 한번 더 브라우저에 set-cookie를 해줘야 하는것인지도 궁금합니다. 질문의 요지는 이렇습니다! 1. 클라이언트 요청의 헤더에 쿠키를 직접 담아서 보내더라도 백엔드에서 받을 수 없는 상황이 있는지? -> 있다면 그 이유는? / 없다면 백엔드 문제인지? 2. next-auth를 사용하는 경우 서버와 서버간의 요청이기 때문에 브라우저에 set-cookie를 해줄 수 없는게 맞는지?
안녕하세요 강사님! 이 강의 덕분에 Next를 기반으로 다양한 프로젝트들을 진행할 수 있게 됐습니다! 그러던 도중, 문득 강사님에게 배운 일부 내용에 대해 궁금한것이 추가적으로 생겨서 질문드립니다. prefetchQuery를 하게 될 경우 그 원리가 궁금합니다 export default async function TabDeciderSuspense() { const queryClient = new QueryClient(); await queryClient.prefetchInfiniteQuery({ queryKey: ['posts', 'recommends'], queryFn: getPostRecommends, initialPageParam: 0, }); const dehydreatedState = dehydrate(queryClient); return ( <HydrationBoundary state={dehydreatedState}> <TabDecider /> </HydrationBoundary> ); } 위 코드에서 HydrationBoundary 로 dehydreatedState를 넘겨주는 원리가 queryFn: getPostRecommends 를 통해 반환받은 값이 캐싱된 QueryClient인스턴스 자체 를 클라이언트 컴포넌트로 넘겨주고 클라이언트 컴포넌트에서는 넘겨받은 QueryClient인스턴스에서 queryKey를 통해 캐싱 데이터를 바로 사용하는 것인가요? 아니면 QueryClient 인스턴스 자체를 전송하는 것이 아니라, 인스턴스에 저장된 데이터와 상태 정보만 (queryFn: getPostRecommends 반환값)클라이언트 사이드에서 사용할 수 있는 형태로 만든 뒤(=직렬화) 클라이언트 사이드에서 이 정보만 QueryClient(RQProvider.tsx에서 만든)에 적용하는 것인가요? 다른 글을 보면 강사님께서 prefetchQuery를 사용한 이유가 해당 페이지에 왔을 때 미리 데이터를 불러와서 SEO 측면에서 유리함을 가져가기 위해서라고 하셨는데, prefetchQuery없이 서버 컴포넌트에서 fetch → 하위 클라이언트 컴포넌트에 props로 전달 하는 형태도 동일한 효과를 가져가는게 맞는것일까요? 이 강의에서 진행했던, 서버 컴포넌트의 Suspense + 클라이언트 컴포넌트의 useSuspenseQuery 의 패턴을 적용할 때 발생하는 문제가 있습니다. (이 부분은 강사님의 코드가 아니라 저 혼자 이 강의를 토대로 직접 실습을 해보면서 맞닥뜨린 문제입니다.) 현재 클라이언트 컴포넌트에서는 CORS대비 프록시를 사용하고 있습니다 // next.config.js async rewrites() { return [ { source: '/api/:path*', // 외부 백엔드 api로 프록시 destination: `${process.env.NEXT_PUBLIC_BASE_URL_DEV}/api/:path*`, }, ]; }, 서버 컴포넌트에 Suspense를 걸어줍니다 // page.tsx const page = ({ params }: PageProps) => { const slug = params.id; return ( <div> <Suspense fallback={<Spinner />}> <EditPresentation slug={Number(slug)} /> </Suspense> </div> ); }; 클라이언트 컴포넌트에서 useSuspenseQuery를 사용합니다 const EditPresentation = ({ slug }: EditPresentationProps) => { const { data: value } = useSuspenseQuery({ queryKey: ['upload', slug], queryFn: async (presentationId: number) => { // 프록시 api const response = await fetch(`/api/presentations/${presentationId}`, { method: 'GET', }); if (response.ok) return await response.json(); }, }); return <>...</>; }; export default EditPresentation; 원래 이론대로라면 서버 컴포넌트의 <Suspense />에 useSuspenseQuery의 queryFn이 걸려야 하는데, 브라우저 새로고침을 하게 되면 실행은 잘 되면서 동시에 아래의 에러가 발생합니다… (제 생각은) 클라이언트 컴포넌트도 어쨌든 처음에 서버를 거치게 되는데, 아마 서버에서는 프록시를 사용한 api를 읽어내지 못해서 발생하는 문제 같긴 한데,,, 혹시 이런 경우에는 어떻게 처리하는게 좋을까요...ㅠ
[userName]으로 home, compose 이런것들을 사용하면 home이 최우선시 된다고 하셨는데 실제 서비스 환경에서 home이라는 user가 있을 수도 있자나요? 이 경우는 따로 예외처리를 어떻게 하나요? 제 생각은 [userName]으로 바로 접속 못하고 상위 구조가 하나 있으면 해결될거 같은데 추천하시는 방법이 있으신가요?
[강의 위치] 2:43~ [질문] StrictResponse<any> 로 타입을 지정하여 타입 오류를 해결하셨는데 any를 지정하지 않으려면 유저가 존재하지 않을 경우에도 아래와 같이 응답 데이터 구조를 맞춰야 할 것 같은데, 일반적으로 found 또는 not found에 대해서 응답 데이터 구조를 맞추는 것이 좋은 방법인가요? const body = { id: "", nickname: "", image: "" }; return HttpResponse.json(body, { status: 404 });
안녕하세요. 강의 잘 보고 있습니다. msw 2버젼때문에 type window를 먼저 체킹하시라고 하셨는데요. MSWComponent 는 최초 "use client"를 선언하였고, 또 useEffect 안에서 실행했기 때문에 브라우져에서 실행되는 로직으로 보장된걸로 이해하고 있는데요, 그렇다 보니 해당 코드가 불필요하지 않을까 싶어서요. 제가 못찾았을수도 있는데 msw측에서 useEffect 안에서도 필요하다고 한걸까요? [제로초 강좌 질문 필독 사항입니다] 질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다. 도움이 되는 질문을 하는 방법을 알려드립니다. https://www.youtube.com/watch?v=PUKOWrOuC0c 0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다. 1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다. 2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다. 3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요. 4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요. 5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다. 6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다.
먼저 강의와 상관없는 질문 죄송합니다. Next 13 Page Router + React Query v3 사용해서 프로젝트 진행했었고, 이후에 강사님 강의를 수강하고 있습니다. 이전 프로젝트 진행 시 문제를 해결은 했지만 찝찝함이 남아있어 궁금증을 해소하기 위해 질문 남깁니다. getServerSideProps 사용해서 서버사이드에서 데이터를 불러오려고 했습니다. 서버(Spring)에서 쿠키 읽기에 실패해서 클라이언트에서 accessToken을 전달해야만 했습니다. 로그인시 accessToken을 클라이언트에서 쿠키에 직접 저장하고 axios 통신시 쿠키에 저장한 토큰을 꺼내서 header에 추가하여 요청하는 방식으로 구현하였는데, 서버 사이드에서는 브라우저 스토리지에 접근하지 못하므로 토큰을 읽지 못하는 문제가 발생했습니다. 모든 통신에서 토큰이 필요했던 프로젝트였어서 SSR을 포기해야하는건가? 하던 중에 React Query 의 Dehydration 방식을 적용하였더니 getServerSideProps 에서도 토큰을 읽고 전달하는것이 가능해졌습니다. 이러한 경우에도 SSR이 제대로 적용된 것이 맞는지, 그렇다면 React Query는 어떻게 브라우저 스토리지에 저장된 값을 읽을 수 있게 된건지 궁금합니다.
Next 프로젝트는 클라이언트에서도 동작하고 서버에서도 동작한다. 그래서 MSW가 클라이언트, 서버에서 동작해야한다. 그러나 아직 서버에서 MSX를 실행하는 방식이 아직 나오지 않았다. 그래서 우리는 임시로 노드 서버를 사용한다. browser.ts - 클라이언트에서 API 요청 모킹 처리해주는 파일 -> 클라이언트 컴포넌트에서 API 요청 시 처리? http.ts - 서버에서 API 요청 모킹 처리해주는 파일 (노드 서버 사용) -> 서버 컴포넌트에서 API 요청시 처리? handlers.ts - 실제 API 모킹 코드