묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결Next + React Query로 SNS 서비스 만들기
트렌드섹션 질문
회원가입 후 바로 로그인 된 상태에서 home으로 가면 트렌드를 가져올 수 없다고 뜨는데 혹시 로그인 후 로그아웃버튼이 뜨지 않았던 상황과 비슷한 상황인가요 ? 로그아웃 버튼처럼 prop으로 session정보를 넘겨줘야 하는건지 궁금합니다
-
미해결Next + React Query로 SNS 서비스 만들기
middleware 관련 질문입니다
해당 코드를 수정했던 강의가 어디였는지 기억이 안나 여기에 글 남깁니다.아래는 auth.ts의 코드이고 callbacks 부분을 작성하셨다가 나중에 없애는 걸로 수정하셨는데 이 코드의 역할을 middleware에서 대신한다고 생각하면 될까요 ? export async function middleware() { const session = await auth(); if (!session) { return NextResponse.redirect('http://localhost:3000/i/flow/login'); } } // callbacks: { // async authorized({ request, auth }) { // if (!auth) { // return NextResponse.redirect('http://localhost:3000/i/flow/login'); // } // return true; // }, // },
-
미해결Next + React Query로 SNS 서비스 만들기
서버 액션에서 msw의 핸들러를 호출하는 이유?
제가 알기로는 서버 액션은 현재 url, 강의 기준 /i/flow/signup으로 네트워크 요청이 일어나는거로 알고 있는데 msw의 핸들러로 fetch를 하신 이유가 궁금합니다. 작동하는 코드인가요?const onSubmit = async (formData: FormData) => { "use server"; let shouldRedirect = false; try { const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/users`, { method: "post", credentials: "include", body: formData, }); console.log(res.status); console.log(await res.json()); shouldRedirect = true; } catch (error) { console.error(error); } if (shouldRedirect) { redirect("/home"); } console.log("실행됨"); };위 코드는 SignupModal에서 msw의 핸들러로 form 제출 요청을 보내는 코드이고,http.post(`${baseUrl}/api/users`, () => { console.log("로그인 성공"); return HttpResponse.json({ message: "msw 성공", }); }),이 코드는 핸들러 코드입니다. 요청 url인 http://localhost:3000/api/users로 폼 제출이 정상적으로 이루어지는지 궁금합니다.
-
미해결Next + React Query로 SNS 서비스 만들기
SessionProvider을 사용해도 하위 컴포넌트가 서버 컴포넌트로 유지되는 것 같은데 이유가 궁금합니다.
SessoinProvider을 사용할 경우 SessionProvider로 감싼 하위 컴포넌트는 모두 클라이언트 컴포넌트가 되는 걸로 알고 있고 클라이너트 컴포넌트의 자식으로써는 서버 컴포넌트가 올 수 없다고 본 것 같은데 코드를 보니까 SessionProvider의 하위 컴포넌트도 서버 컴포넌트로 잘 작동 되는 컴포넌트가 있는 것 같아요.혹시 제가 잘못알고 있는지 궁금합니다.
-
미해결Next + React Query로 SNS 서비스 만들기
next auth 질문
1.next auth core를 설치하는 이유가 있을까요 ?prisma를 사용중인데 beta 버전을 설치하면 prisma adapter와 호환성이 안된다고 하는데 4버전을 사용해도 될까요?4버전 사용시 export const {auth} 와 같은 코드가 호환될까요?그리고 middleware 에서 session이 아닌 getToken 으로 토큰을 불러와도 상관 없을까요 ?
-
해결됨Next + React Query로 SNS 서비스 만들기
hydration 오류 (Fragment key값)
강사님 안녕하세요, 백엔드 서버 연결하고 게시물(PostForm.tsx) 올리는 부분에서 오류가 발생하여 질문드립니다. (섹션5 - 게시글 업로드 완성)hydration 이슈를 찾아봤는데 (https://velog.io/@jhplus13/NextJS-React-Hydration-Error-%ED%95%B4%EA%B2%B0%EA%B8%B0) typeof window과 관련있는거 같은데 혼자 해결하기 어려워 링크 첨부드립니다..!오류해결을 위해 (hydration / PostRecommends.tsx) 해당 부분을 수정하였습니다..!변수입력확인(Date.now(),Math.random(), new Date()) + faker 해당부분은 주석처리 했습니다.태그 중첩 확인, layout.tsx font 연결 확인 [콘솔 에러]intercept-console-error.js:56 A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used: - A server/client branch `if (typeof window !== 'undefined')`. - Variable input such as `Date.now()` or `Math.random()` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch ... <HotReload assetPrefix=""> <ReactDevOverlay state={{nextId:1, ...}} dispatcher={{...}}> <DevRootNotFoundBoundary> <NotFoundBoundary notFound={<NotAllowedRootNotFoundError>}> <NotFoundErrorBoundary pathname="/home" notFound={<NotAllowedRootNotFoundError>} notFoundStyles={undefined} ...> <RedirectBoundary> <RedirectErrorBoundary router={{...}}> <Head> <link> <RootLayout> <html lang="ko" className="__variable..."> <body className="__className_fde3a9" - cz-shortcut-listen="true" > ... ...[Fragment key값 오류내용]// package.json { "name": "zcom", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@auth/core": "^0.27.0", "@fortawesome/fontawesome-svg-core": "^6.7.1", "@fortawesome/free-solid-svg-icons": "^6.7.1", "@fortawesome/react-fontawesome": "^0.2.2", "@tanstack/react-query": "^5.62.11", "@vanilla-extract/css": "^1.16.1", "@vanilla-extract/recipes": "^0.5.5", "@vanilla-extract/sprinkles": "^1.6.3", "classnames": "^2.5.1", "clsx": "^2.1.1", "dayjs": "^1.11.13", "next": "^15.0.4", "next-auth": "^5.0.0-beta.25", "react": "^19.0.0", "react-dom": "^19.0.0", "react-intersection-observer": "^9.14.1", "react-textarea-autosize": "^8.5.6", "zustand": "^5.0.2" }, "devDependencies": { "@faker-js/faker": "^9.3.0", "@tanstack/react-query-devtools": "^5.62.11", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "@vanilla-extract/next-plugin": "^2.4.7", "@vanilla-extract/webpack-plugin": "^2.3.15", "msw": "^2.6.8", "typescript": "^5" }, "msw": { "workerDirectory": [ "public" ] } }
-
해결됨Next + React Query로 SNS 서비스 만들기
next-auth 로그인/회원가입 에러(middleware)
강사님 안녕하세요, 로그인/회원가입 시 middleware export 되지않는 이슈로 질문남깁니다..!터미널에서 middleware가 export가 되지않는다고 뜨는데 import하는 방식이 잘못된건지 여쭙니다.// middleware.ts import { auth as middleware } from "./auth" export const config = { matcher: ['/compose/tweet', '/home', '/explore', '/messages', '/search'], }//auth.ts import NextAuth, {CredentialsSignin} from "next-auth" import CredentialsProvider from "next-auth/providers/credentials"; export const { handlers: { GET, POST }, auth, signIn, } = NextAuth({ pages: { signIn: "/i/flow/login", newUser: "/i/flow/signup", }, providers: [ CredentialsProvider({ async authorize(credentials) { const authResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: credentials.username, password: credentials.password, }), }) if (!authResponse.ok) { return null } const user = await authResponse.json(); return { email: user.id, name: user.nickname, image: user.image, ...user, }; }, }), ] });// package.json { "name": "x-com", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@auth/core": "^0.27.0", "@vanilla-extract/css": "^1.16.1", "@vanilla-extract/recipes": "^0.5.5", "@vanilla-extract/sprinkles": "^1.6.3", "classnames": "^2.5.1", "clsx": "^2.1.1", "dayjs": "^1.11.13", "next": "^15.0.4", "next-auth": "^5.0.0-beta.25", "react": "^19.0.0", "react-dom": "^19.0.0", "react-textarea-autosize": "^8.5.6", }, "devDependencies": { "@faker-js/faker": "^9.3.0", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "@vanilla-extract/next-plugin": "^2.4.7", "@vanilla-extract/webpack-plugin": "^2.3.15", "msw": "^2.6.8", "typescript": "^5" }, "msw": { "workerDirectory": [ "public" ] } } <터미널 오류내용> ⨯ Error: The Middleware "/src/middleware" must export a `middleware` or a `default` function at <unknown> (webpack-internal:\(middleware)\node_modules\next\dist\build\webpack\loaders\next-middleware-loader.js:12) at eval (webpack-internal:\(middleware)\node_modules\next\dist\build\webpack\loaders\next-middleware-loader.js?absolutePagePath=C%3A%5CUsers%5Calsdu%5CDocuments%5CGitHub%5Canimals_forest%5Csrc%5Cmiddleware.ts&page=%2Fsrc%2Fmiddleware&rootDir=C%3A%5CUsers%5Calsdu%5CDocuments%5CGitHub%5Canimals_forest&matchers=&preferredRegion=&middlewareConfig=e30%3D!:12:0) at (middleware)/./node_modules/next/dist/build/webpack/loaders/next-middleware-loader.js?absolutePagePath=C%3A%5CUsers%5Calsdu%5CDocuments%5CGitHub%5Canimals_forest%5Csrc%5Cmiddleware.ts&page=%2Fsrc%2Fmiddleware&rootDir=C%3A%5CUsers%5Calsdu%5CDocuments%5CGitHub%5Canimals_forest&matchers=&preferredRegion=&middlewareConfig=e30%3D! (.next\server\src\middleware.js:642:1) at __webpack_require__ (.next\server\edge-runtime-webpack.js:37:33) at __webpack_exec__ (.next\server\src\middleware.js:681:48) at <unknown> (.next\server\src\middleware.js:682:37) at webpackJsonpCallback (.next\server\edge-runtime-webpack.js:1219:39) at <unknown> (.next\server\src\middleware.js:9:61) at evaluateInContext (node_modules\next\dist\server\web\sandbox\context.js:420:38) GET /home 404 in 4ms Failed to get source map: Error: Failed to read file contents of C:\Users\alsdu\Documents\GitHub\animals_forest\webpack-internal:\(middleware)\node_modules\next\dist\build\webpack\loaders\next-middleware-loader.js. at getSourceMapFromFile (node_modules\next\src\client\components\react-dev-overlay\internal\helpers\get-source-map-from-file.ts:20:10) at async getSource (node_modules\next\src\client\components\react-dev-overlay\server\middleware.ts:228:22) at async (node_modules\next\src\client\components\react-dev-overlay\server\middleware.ts:319:17) at async HotReloaderWebpack.run (node_modules\next\src\server\dev\hot-reloader-webpack.ts:392:6) at async handleRequest (node_modules\next\src\server\lib\router-server.ts:319:34) at async requestHandlerImpl (node_modules\next\src\server\lib\router-server.ts:576:6) at async Server.requestListener (node_modules\next\src\server\lib\start-server.ts:146:6) { [cause]: Error: ENOENT: no such file or directory, open 'C:\Users\alsdu\Documents\GitHub\animals_forest\webpack-internal:\(middleware)\node_modules\next\dist\build\webpack\loaders\next-middleware-loader.js' at async getSourceMapFromFile (node_modules\next\src\client\components\react-dev-overlay\internal\helpers\get-source-map-from-file.ts:18:19) at async getSource (node_modules\next\src\client\components\react-dev-overlay\server\middleware.ts:228:22) at async (node_modules\next\src\client\components\react-dev-overlay\server\middleware.ts:319:17) at async HotReloaderWebpack.run (node_modules\next\src\server\dev\hot-reloader-webpack.ts:392:6) at async handleRequest (node_modules\next\src\server\lib\router-server.ts:319:34) at async requestHandlerImpl (node_modules\next\src\server\lib\router-s at async handleRequest (node_modules\next\src\server\lib\router-server.ts:319:34) at async requestHandlerImpl (node_modules\next\src\server\lib\router-server.ts:576:6) at async Server.requestListener (node_modules\next\src\server\lib\start-server.ts:146:6) { [cause]: Error: ENOENT: no such file or directory, open 'C:\Users\alsdu\Documents\GitHub\animals_forest\webpack-internal:\(middleware)\node_modules\next\dist\build\webpack\loaders\next-middleware-loader.js' at async getSourceMapFromFile (node_modules\next\src\client\components\react-dev-overlay\internal\helpers\get-source-map-from-file.ts:18:19) at async getSource (node_modules\next\src\client\components\react-dev-overlay\server\middleware.ts:228:22) at async (node_modules\next\src\client\components\react-dev-overlay\server\middleware.ts:319:17) at async HotReloaderWebpack.run (node_modules\next\src\server\dev\hot-reloader-webpack.ts:392:6) at async handleRequest (node_modules\next\src\server\lib\router-server.ts:319:34) at async requestHandlerImpl (node_modules\next\src\server\lib\router-sserver.ts:146:6) { [cause]: Error: ENOENT: no such file or directory, open 'C:\Users\alsdu\Documents\GitHub\animals_forest\webpack-internal:\(middleware)\node_modules\next\dist\build\webpack\loaders\next-middleware-loader.js' at async getSourceMapFromFile (node_modules\next\src\client\components\react-dev-overlay\internal\helpers\get-source-map-from-file.ts:18:19) at async getSource (node_modules\next\src\client\components\react-dev-overlay\server\middleware.ts:228:22) at async (node_modules\next\src\client\components\react-dev-overlay\server\middleware.ts:319:17) at async HotReloaderWebpack.run (node_modules\next\src\server\dev\hot-reloader-webpack.ts:392:6) at async handleRequest (node_modules\next\src\server\lib\router-server.ts:319:34) at async requestHandlerImpl (node_modules\next\src\server\lib\router-soverlay\server\middleware.ts:228:22) at async (node_modules\next\src\client\components\react-dev-overlay\server\middleware.ts:319:17) at async HotReloaderWebpack.run (node_modules\next\src\server\dev\hot-reloader-webpack.ts:392:6) at async handleRequest (node_modules\next\src\server\lib\router-server.ts:319:34) at async requestHandlerImpl (node_modules\next\src\server\lib\router-sreloader-webpack.ts:392:6) at async handleRequest (node_modules\next\src\server\lib\router-server.ts:319:34) at async requestHandlerImpl (node_modules\next\src\server\lib\router-s.ts:319:34) at async requestHandlerImpl (node_modules\next\src\server\lib\router-server.ts:576:6) at async Server.requestListener (node_modules\next\src\server\lib\start-server.ts:146:6) { errno: -4058, code: 'ENOENT', syscall: 'open', path: 'C:\\Users\\alss\\Documents\\GitHub\\x-com\\webpack-internal:\\(middleware)\\node_modules\\next\\dist\\build\\webpack\\loaders\\next-middleware-loader.js' } }
-
미해결Next + React Query로 SNS 서비스 만들기
vanilla extract는 UI 기능들이 없는거같은데
예를들어 부트스트랩처럼 모달이나 반응형 디자인 같은거를 편리하게 해주는 기능들이요 그냥 다 직접 만들어야 하나요?같이 쓸수있는게 있나요?
-
미해결Next + React Query로 SNS 서비스 만들기
next-auth 사용이유
안녕하세요 섹션4의 next-auth 를 수강하고있습니다. next-auth를 사용하는 이유가 무엇인가요?보통 백엔드에서 로그인 기능을 구현하는 것이 일반적이라고 알고 있습니다.next-auth는 백엔드가 로그인 기능을 구현하지 않았을 때 사용하는 것인가요? 아니면 이미 백엔드에서 구현한 로그인 API를 사용하기 위해서도 next-auth를 사용하는 경우가 있나요?
-
미해결Next + React Query로 SNS 서비스 만들기
Next15의 서버사이드 렌더링과 서버 컴포넌트
안녕하세요! Next 강좌를 보던 중 헷갈리는게 있어 질문을 올리게 되었습니다!다름이아니라, 현재 next15에서 getServerSideProps 등이 사라진걸로 알고있는데 그럼 서버사이드 렌더링을 서버 컴포넌트로 대체하는건지 여쭤보려고 합니다!서버사이드 렌더링과 서버 컴포넌트는 다른 개념이라고 알고있는데 결국 서버사이드 렌더링을 서버 컴포넌트를 이용해서 구현하는 것인지,, 그게 궁금합니다!
-
미해결Next + React Query로 SNS 서비스 만들기
회원가입시 왜 리다이렉트 안되죠?
회원가입후 회원가입완료되면 자동으로 메인페이지 이동해야 하는데, 라이디렉트가 안되고 있습니다.db는 확인해보니 제대로 전송되고 있고요.데이터 또한 정상적으로 200 떠서 넘김 처리한거 같은데 뭐가 말썽인지 모르겠습니다.기존꺼 듣다가 15로 업데이트 해서 패키지로 기존에 싹다 날리고, npm i로 다시 설치 했습니다. 그래도 안되서 문의드려요.1. env, 2.handler, 3.browser, 4.https, 5.auth 6.기타 컴포넌트 그대로 복사해서 붙여놨는데도 문제가있네요.그리고 추가로 가입하기 버튼후 새로고침 안하면 계속 대기중으로 표시되는것 같습니다.회원가입 시 프론트서버 회원가입 시 백엔드 서버(npm run start:dev) 회원가입시 브라우저콘솔( 이부분은 확인해보니 매우느리게 status가 200으로 처리가 되었네요) 확인사항: 방금 https://github.com/ZeroCho/next-app-router-15 으로 그대로 zip파일열어서 그대로 실행시켜 봤는데 제 코드랑 같은 현상이 일어나는걸로 봐서는 백엔드 혹은 백엔드와 상호작용에서 뭔가 문제가 있는것 같은데 혹시 문제해결을 알수있을까요? *추가로 새로보시는 분들은 상관없는데,기존에 보시다가 변경되신 분들은 지금 강의 너무 혼란스럽습니다. 진행자 입장에서는 크게 변한게 없다고 하겠지만, 시청하는 입장에서는 패키지 버전부터, 기타 등등 이 바꼈고, 이해안가는 부분만 해당 강의를 시청할려고 다시 듣는데 기존꺼랑 새로운거랑 그냥 아예 섞여버려서 강의가 가독성이 지금 너무 떨어지고있습니다. 인트로부분에 15버전수정은 15버전이라고 기재한다고 했는데, 그것도 일부분만 하고 나머지도 슬쩍 변경이 됬는데, 아예 기존것처럼 해놔서 더 혼동이 오네요. 차라리 업데이트를 한번에 하시지 왜 진행도중에 하시는지 ..조금 불편합니다.. 나중에 참고해주시면 감사하겠습니다.
-
미해결Next + React Query로 SNS 서비스 만들기
antd 적용
antd 편해서 적용하려는데 문제없나요?styled component 문제있다하셔서 css module로 커스텀하려는데 인라인 스타일로 커스텀하면되나요?
-
해결됨Next + React Query로 SNS 서비스 만들기
리액트 쿼리를 활용한 SSR으로 데이터 조회하기
안녕하세요!제가 강의를 모두 수강하고 프로젝트에서 리액트 쿼리를 통해 SSR을 적용하려고 하고 있습니다. 아래 코드는 fetchAPISever 함수를 통해 백엔드 api로부터 데이터를 요청하는 함수입니다. 이때fetchAPIsever 함수는 next/header의 cookies()를 통해 사용자의 토큰이 있으면 토큰을 넣어서 api를 요청하는 함수입니다.export const getBestAndPendingReviews = async (): Promise<ReviewePageResponse> => { const res = await fetchAPIServer('/api/review', 'GET'); if (res.code === 'SUCCESS') { return res.result; } throw new Error( `리뷰 페이지 데이터 불러오기 실패 ${res.code}-${res.message}`, ); }; 아래 코드는 리뷰 페이지에서 서버 사이드 렌더링으로 보여주기 위해 리액트 쿼리로 Hydration을 적용한 코드입니다.// src\app\reviews\page.tsx import { HydrationBoundary, QueryClient, dehydrate, } from '@tanstack/react-query'; import ReviewDashboard from './_components/ReviewDashboard'; import { getBestAndPendingReviews } from './_lib/getBestAndPendingReviews'; export default async function ReviewsPage() { const queryClient = new QueryClient(); await queryClient.prefetchQuery({ queryKey: ['reviews', 'best'], queryFn: getBestAndPendingReviews, }); const dehydrateState = dehydrate(queryClient); return ( <HydrationBoundary state={dehydrateState}> <ReviewDashboard /> </HydrationBoundary> ); } ' <ReviewDashboard/> 컴포넌트에서 UserInfo 컴포넌트를 반환하도록 설정하고 useQuery 훅을 사용하려 했으나, fetchAPIServer 함수에서 next/headers 를 import하고 있어서 클라이언트 컴포넌트에서 사용할 수 없다는 에러가 발생했습니다. 그러면 SSR을 적용하기 위해서는 getQueryData를 사용해야하는 걸까요..?import { QueryClient } from '@tanstack/react-query'; import { ReviewePageResponse } from '../_lib/getBestAndPendingReviews'; export default function UserInfo() { const queryClient = new QueryClient(); const reviews = queryClient.getQueryData<ReviewePageResponse>([ 'reviews', 'best', ]); const { total } = reviews!; if (!reviews) return <p>리뷰가 없습니다.</p>; console.log('reviews', reviews); return <p>작성한 리뷰 {total || 0}</p>; } 또는 useQuery를 쓰되 쿼리 함수를 Promise.Resolve()로 서버에서 전달 받은 데이터를 받는게 나은가 요? 'use client'; import { useQuery } from '@tanstack/react-query'; export default function UserInfo() { const { data: reviews, isLoading } = useQuery({ queryKey: ['reviews', 'best'], queryFn: () => Promise.resolve(), // 서버 데이터 재활용 }); if (isLoading) return <p>Loading...</p>; if (!reviews) return <p>리뷰가 없습니다.</p>; const { total } = reviews!; console.log('reviews', reviews); return <p>작성한 리뷰 {total || 0}</p>; }
-
미해결Next + React Query로 SNS 서비스 만들기
페러렐 라우트(default.tsx)
강사님 안녕하세요! 강의 수강 후 개인 프로젝트 진행중인데 페러렐 라우트 부분에서 막혀 질문남깁니다ㅜㅠ..default.tsx는 강의에서 진행해주신대로 return null;을 넣었습니다. (.next 캐쉬도 지웠습니다)// 폴더구조 app/ ├──(afterLogin) │ ├── _component │ │ ├── Header.tsx // header 컴포넌트 │ ├── @message │ │ ├── page.tsx │ │ ├── default.tsx │ ├── @modal │ │ ├── //...compose/[username] 등 폴더 │ │ ├── default.tsx │ ├── home │ │ ├── page.tsx // home 컴포넌트 │ ├── default.tsx │ ├── layout.tsx │ │ ├──(beforeLogin) │ ├── page.tsx │ ├── layout.tsx ├── layout.tsx // (afterLogin)/layout.tsx import { ReactNode } from "react"; import Header from '@/app/(afterLogin)/_component/Header'; type Props = {children: ReactNode, modal: ReactNode, message: ReactNode;}; export default function AfterLoginLayout({children,modal,message,}: Props) { return ( <div className="wrap"> <Header /> <div className="container">{children}</div> <div className="chatting">{message}</div> {modal} </div> ); }해당 이미지와 같이 layout에서 header/{children}/{message}/{modal}을 띄우고 싶은데 message부분이 나오고 있지 않습니다..! (그래서 afterLogin의 layout.tsx와 같은 상위요소에 default를 만들어도 똑같더라구요..)<질문>1. 제가 폴더구조를 잘못 짠 걸까요..?2. (afterLogin)/@message/default.tsx(default.tsx에서 @message/page.tsx를 import해서 진행해도 될까요? 요런식으로 하면 잘 노출이 됩니다..!)import Message from './page'; export default function Default() { return <Message /> }3. 아니면 header처럼 컴포넌트 형식으로 메시지창만 만든다음 onClick되면 -> 인터셉팅으로 가로채는것(/message/page.tsx)이 좋을까요?조언 부탁드리겠습니다..!! ĭ˄ĭ
-
미해결Next + React Query로 SNS 서비스 만들기
RequestMemoization 관련해서 질문드립니당
데이터 캐시 설정을 force-cache 로 했을 때 이걸 갱신하기 위한 방법으로 revalidate 옵션을 주거나 revalidateTag, revalidatePath 등이 있다고 하셨는데요.그러면 RequestMemoization에 의해서 캐싱된 데이터는 브라우저 새로고침 등을 하면 다시 fetch 하면서 갱신이 되는건가요?RequestMemoization 에 의해서 캐싱된 데이터는 언제 갱신되는지 궁금합니다. 그런데 제가 이해한 바로는 유저가 처음 브라우저를 통해 애플리케이션에 접근해서 해당 url 에서 요청을 보냈을 때 특정 데이터를 페칭하는 함수가 여러 컴포넌트에 있어서 그 데이터를 불러오기 위한 요청을 한 번만 함으로써 서버에 요청이 가는 것을 줄여주는것이 RequestMemoization 이라고 저는 이해를 했는데요. 어차피 처음에 같은 데이터를 보여주기 위해 여러 번의 요청을 하는 것은 불필요한 네트워크를 타게 되고 성능상에 좋지 않으니까요.이런 경우라면 사실 RequestMemoization 은 캐싱된 데이터를 갱신할 필요가 없을 수도 있겠다는 생각이 듭니다.그래서 제로초님이 별다른 언급이 없으셨나? 하는 생각도 드네요. 감사합니다.
-
미해결Next + React Query로 SNS 서비스 만들기
next.js 15 로 진행 중인데 리액트 쿼리 설치 관련 질문입니다.
next.js 15 로 따라가면서 진행 중인데 리액트 쿼리를 설치하려고 하니 리액트19 가 아직 안정적이지 않아서 npm 설치할 때 충돌이 생긴다고 에러가 뜨는 것 같습니다.npm ERR! code ERESOLVEnpm ERR! ERESOLVE unable to resolve dependency treenpm ERR!npm ERR! While resolving: z-com@0.1.0npm ERR! Found: react@19.0.0-rc-66855b96-20241106npm ERR! node_modules/reactnpm ERR! react@"19.0.0-rc-66855b96-20241106" from the root projectnpm ERR!npm ERR! Could not resolve dependency:npm ERR! peer react@"^18 || ^19" from @tanstack/react-query@5.62.7npm ERR! node_modules/@tanstack/react-querynpm ERR! @tanstack/react-query@"*" from the root projectnpm ERR!npm ERR! Fix the upstream dependency conflict, or retrynpm ERR! this command with --force or --legacy-peer-depsnpm ERR! to accept an incorrect (and potentially broken) dependency resolution.-------리액트 19 안정화 버전으로 업데이트 진행했습니다! 그랬더니 next 와 리액트19 사이에 에러가 발생해서 next 도 latest 로 업데이트 해주고 리액트 쿼리를 설치하니까 되네요!이 방법이 맞는지는 모르겠지만 일단 이렇게도 되긴 합니다!
-
미해결Next + React Query로 SNS 서비스 만들기
Next-Auth 관련해서 질문이 있습니다.
백엔드 취준생인데 프론트를 좀 할 일이 있어서 강의 듣고 있는데 Next-Auth 부분이 이해가 쉽지 않네요... 몇 가지 질문 드리고자 합니다.1. session 객체에 어떤게 담기는건지 잘 모르겠습니다.export default async function Home() { const session = await auth() if (session?.user) { redirect('/home') return null } return ( <Main/> ); }export const { handlers: { GET, POST }, auth, signIn, } = NextAuth({ // 개발자가 직접 만든 화면에서 로그인 하도록 진행 pages: { signIn: '/i/flow/login', // 로그인 newUser: '/i/flow/signup' // 회원가입 }, providers: [ CredentialsProvider({ async authorize(credentials) { const authResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, { method: 'POST', headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: credentials.usename, password: credentials.password, }) }) if (!authResponse.ok) { return null } const user = await authResponse.json() return { email: user.id, name: user.nickname, image: user.image, ...user } } }) ], })Home 에서 auth() 를 통해 불러온 session 객체에 CredentialsProvider 가 리턴한 객체가 담기는건가요?그런데 그렇다고 하기엔 객체에 user 라는 속성이 없어서 아닌 것 같기도 해서 아닌 거 같다는 생각도 듭니다. export default function Login() { const router = useRouter() const { data: session } = useSession(); if (session?.user) { router.replace('/home') return null } router.replace("/i/flow/login") return ( <Main /> ) }마찬가지로 여기서도 session 에 어떤게 담기는지 잘 모르겠습니다 ㅠㅠ auth() 로 리턴한 세션과 같은 객체가 담기는 것 같긴 한데 도대체 session 에 뭐가 담기는지 파악이 쉽지 않네요 ㅋㅋㅋ그래서 session 객체의 user 를 클릭해서 들어가보니 다음과 같은 interface 가 나오네요.export interface DefaultSession { user?: User expires: ISODateString }auth/core 에 있는 인터페이스인 것 같은데 이 인터페이스가 어느 시점에 등장(?) 하는 건지 잘 모르겠습니다.2. 지금 진행하는 로그인 방식은 백엔드에 로그인 관련 API 가 있다고 가정하고 진행하는 것으로 저는 이해를 했는데요export const handlers = [ http.post(`${baseUrl}/api/login`, () => { console.log('로그인'); return HttpResponse.json(User[1], { headers: { 'Set-Cookie': 'connect.sid=msw-cookie;HttpOnly;Path=/' }, }) }), http.post(`${baseUrl}/api/logout`, () => { console.log('로그아웃'); return new HttpResponse(null, { headers: { 'Set-Cookie': 'connect.sid=;HttpOnly;Path=/;Max-Age=0' } }) }), http.post(`${baseUrl}/api/users`, async ({ request }) => { console.log('회원가입'); // return HttpResponse.text(JSON.stringify('user_exists'), { // status: 403 // }) return HttpResponse.text(JSON.stringify('ok'), { headers: { 'Set-Cookie': 'connect.sid=msw-cookie;HttpOnly;Path=/' }, }); }) ];이게 지금 api 를 mocking 한 건데 여기에 요청을 보내고 있으니까요.그러면 이 API 에서 리턴한 유저(User[1]) 가 세션에 담기는 것인지 궁금하네요. (이것도 1번 질문하고 좀 연관이 되네요) 그러면 만약에 백엔드 API 가 로그인 성공했을 때 http body 에 별도의 객체를 리턴하지 않으면 어떻게 되나? 이런 궁금증도 생깁니다.3. 그리고 로그아웃을 할 때는 왜 로그아웃 API 에 따로 요청을 보내지 않고 signOut 함수만 사용하는지 궁금합니다. 이것만 사용해도 쿠키가 삭제가 돼서 그런 것인가요? 그러면 백엔드 서버에 별도의 로그아웃 API 를 만들지 않아도 되는 것인지 궁금합니다. 장문의 질문글이 된 거 같은데, 뭔가 Next-Auth 를 처음 접하다보니 사용법이 좀 익숙치가 않네요. AI 에 물어보거나 구글링을 해 봐도 좀 파악이 쉽지 않아 여기에 질문 남겨봅니다.감사합니다.
-
미해결Next + React Query로 SNS 서비스 만들기
안녕하세요! next-auth 로그인하기 부분 질문입니다.
지금 강의에서 보여주신게 아직 업데이트가 안 된 것인지 궁금합니다!Auth.js 홈페이지에 있는 문서와 코드가 조금 다른 것 같아서요. next.js 15 버전으로 강의 따라가고 있고 auth.js 설치할 때 auth@5 하니까 설치가 안 돼서 auth@beta 이렇게 설치하고 진행 중 입니다! 제가 본 페이지는 다음과 같습니다.https://authjs.dev/getting-started/authentication/credentials 추가일단 제로초님이 하신 방법으로 CredentialsProvider 직접 import 하니까 되는 것 같습니다!
-
미해결Next + React Query로 SNS 서비스 만들기
로그인 방식 관련해서 질문드립니다!!
로그인 방식을 구현하면서, 쿠키로만 개발할 경우 완전히 백엔드에 의존하게 되어 로컬로, 동시에 키고 개발을 하지 않는이상, 도메인간 불일치를 해결 할 방법이 없어, msw를 사용해야 한다고, 이전에 말씀해주셨습니다!!보통, 회사나, 개인 소프트웨어를 만들 때 어떤 방식으로 로그인을 주로 만드시는지 조금 알고 싶어 궁금하여 질문을 남깁니다!!로그인 방식 고찰로그인 성공시, accessToken을 body로 받고, refreshToken은, httpOnly 쿠키로 받는 경우 (서버에서, DB or Redis를 통해 refreshToken 관리) → 인증 필요 요청 (Bearer accessToken), 리프레시 필요 요청 (refreshToken 심긴 쿠키를 바탕으로 요청)- DB에서 관리하는 것 보다, redis를 통해 관리했을 떄 읽기 속도가 빠름을 확인!응답: accessToken과 refreshToken 모두 body로 클라이언트에게 전달.인증 필요 요청과, 리프레시 토큰 재발급 요청 모두 헤더의 Bearer에 accessToken이나, refreshToken을 넣어서 전달.)현재 방식: accessToken, refreshToken 모두 쿠키로 응답받고, 요청또한, 쿠키를 포함하여 전달.제로초님은, Next.js를 활용하여, 웹 사이트를 만드실 떄, 어떠한 방식으로 로그인을 구현하시는지 궁금하고, 많은 회사에서 사용하는 방식은 보통 어떤 방식인지도 알고싶습니다!
-
해결됨Next + React Query로 SNS 서비스 만들기
MSW 오류
먼저 next와 react의 버전은 각각 15버전과 19버전입니다 next 15 부터는 http.ts 의 코드가 간결하게 바뀌어서 적용해보던 중 세팅 단계에서 해당 오류가 발생하였습니다 TypeError: Cannot read properties of undefined (reading 'url' 구글에 검색해보니 최신버전에서도 발생하는 것 같습니다 ㅠㅠ