묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 (장고 4.2 기준)
cover_image_tag(self) 부분 질문이 있습니다.
안녕하세요 강사님.인자로 받는 self는 그 c++의 this 포인터 같은 개념으로 보면 될까요, 그리고 list_display 안에 cover_image를 cover_image_tag로 바꿨는데 처음에 cover_image는 같은 클래스(SongAdmin)에 있는 함수라 list_display에서 사용가능한거고, cover_image_tag는 models 파일 안에 Song 클래스 안에 있는 함수라 list_display에서 사용이 가능한걸까요? 감사합니다.
-
해결됨파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 (장고 4.2 기준)
[11-30] 강의 crispy form 적용에서 오류가 발생해서 관련 문의 드립니다.
강사님 안녕하세요,HTMX와 모달을 활용한 댓글 기능을 구현하는 코드 작성 중에 crispy form이 적용이 되지 않고 오류가 발생해서 문의드립니다.작성하고 있던 코드는 _comment_form.html 파일의 코드입니다아래 이미지는 발생한 에러 내용입니다. comment_form.html 파일의 코드를 구현하고 로컬호스트에 띄운 개별 Note 페이지의 하단에 '댓글 쓰기' 버튼을 클릭했을 때, crispy form이 렌더링 되지 않고 위와 같은 에러가 발생하는 케이스입니다. 제가 추측하는 것은 context 변수에 담긴 데이터에 문제가 있어서, flatten() 메서드가 동작하지 않아 발생하는 에러 같다고 생각하는데요. 해결하는 방법에 대해 알려주시면 감사하겠습니다! 감사합니다 🙂
-
미해결Slack 클론 코딩[실시간 채팅 with React]
CORS - Access-Control-Allow-Origin 누락 문제
강좌보면서 proxy 설정하고 back 폴더 npm run dev, alecture 폴더 npm run build 했는데 회원가입 버튼을 누르니 콘솔창에 시간차로 계속 Access to XMLHttpRequest at 'https://sleact.nodebird.com/api/users' from origin 'http://localhost:3095' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.app.js:2 GET https://sleact.nodebird.com/api/users net::ERR_FAILED 200 (OK)(익명) @ app.js:2e.exports @ app.js:2e.exports @ app.js:2l.request @ app.js:2r.forEach.l.<computed> @ app.js:2(익명) @ app.js:2r.Z @ 678.js:1(익명) @ app.js:2(익명) @ app.js:2(익명) @ app.js:2(익명) @ app.js:2o @ app.js:2(익명) @ app.js:2(익명) @ app.js:2D @ app.js:2[신규] Edge에서 Copilot을 사용하여 콘솔 오류 설명: 클릭 오류를 설명합니다. 자세한 정보 다시 표시 안 함signup:1 Access to XMLHttpRequest at 'https://sleact.nodebird.com/api/users' from origin 'http://localhost:3095' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.app.js:2 GET https://sleact.nodebird.com/api/users net::ERR_FAILED 200 (OK)(익명) @ app.js:2e.exports @ app.js:2e.exports @ app.js:2l.request @ app.js:2r.forEach.l.<computed> @ app.js:2(익명) @ app.js:2r.Z @ 678.js:1(익명) @ app.js:2(익명) @ app.js:2(익명) @ app.js:2(익명) @ app.js:2o @ app.js:2(익명) @ app.js:2setTimeoutonErrorRetry @ app.js:2(익명) @ app.js:2(익명) @ app.js:2(익명) @ app.js:2u @ app.js:2Promise.thenc @ app.js:2(익명) @ app.js:2o @ app.js:2(익명) @ app.js:2(익명) @ app.js:2D @ app.js:2signup:1 Access to XMLHttpRequest at 'https://sleact.nodebird.com/api/users' from origin 'http://localhost:3095' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.319.js:1 undefinedapp.js:2 POST https://sleact.nodebird.com/api/users net::ERR_FAILED라는 오류가 발생합니다. copilot을 실행시켜보니 Access-Control-Allow-Origin과 Origin이 같아야하는데 Access-Control-Allow-Origin 부분이 누락되었다고 나옵니다. 네트워크 200번대는 실행에는 성공한거라고 들었는데... 도움주시면 감사하겠습니다!제 webpack.config.ts 첨부하겠습니다. import path from 'path'; //import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin'; import webpack, { Configuration as WebpackConfiguration } from "webpack"; import { Configuration as WebpackDevServerConfiguration } from "webpack-dev-server"; //import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; interface Configuration extends WebpackConfiguration { devServer?: WebpackDevServerConfiguration; } import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; const isDevelopment = process.env.NODE_ENV !== 'production'; const config: Configuration = { name: 'sleact', mode: isDevelopment ? 'development' : 'production', devtool: !isDevelopment ? 'hidden-source-map' : 'eval', resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], alias: { '@hooks': path.resolve(__dirname, 'hooks'), '@components': path.resolve(__dirname, 'components'), '@layouts': path.resolve(__dirname, 'layouts'), '@pages': path.resolve(__dirname, 'pages'), '@utils': path.resolve(__dirname, 'utils'), '@typings': path.resolve(__dirname, 'typings'), }, }, entry: { app: './client', }, module: { rules: [ { test: /\.tsx?$/, loader: 'babel-loader', options: { presets: [ [ '@babel/preset-env', { targets: { browsers: ['IE 10'] }, debug: isDevelopment, }, ], '@babel/preset-react', '@babel/preset-typescript', ], env: { development: { plugins: [require.resolve('react-refresh/babel')], }, }, }, exclude: path.join(__dirname, 'node_modules'), }, { test: /\.css?$/, use: ['style-loader', 'css-loader'], }, ], }, plugins: [ // new ForkTsCheckerWebpackPlugin({ // async: false, // // eslint: { // // files: "./src/**/*", // // }, // }), new webpack.EnvironmentPlugin({ NODE_ENV: isDevelopment ? 'development' : 'production' }), ], output: { path: path.join(__dirname, 'dist'), filename: '[name].js', publicPath: '/dist/', }, devServer: { historyApiFallback: true, // react router port: 3090, devMiddleware: { publicPath: '/dist/' }, static: { directory: path.resolve(__dirname) }, proxy: { '/api/': { target: 'http://localhost:3095', changeOrigin: true, }, }, }, }; if (isDevelopment && config.plugins) { // config.plugins.push(new webpack.HotModuleReplacementPlugin()); // // config.plugins.push(new ReactRefreshWebpackPlugin()); // // config.plugins.push(new BundleAnalyzerPlugin({ analyzerMode: 'server', openAnalyzer: true })); } if (!isDevelopment && config.plugins) { // config.plugins.push(new webpack.LoaderOptionsPlugin({ minimize: true })); // // config.plugins.push(new BundleAnalyzerPlugin({ analyzerMode: 'static' })); } export default config;
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
12.11 invalid Date 오류
따라서 하고 있었는데 다음 그림과 같이 invalid Date 라는 값이 떠서 관련 질문 드립니다. 강의 몇번 돌려보면서 오타가 있나 봤는데 도저히 모르겠어서 질문 드립니다...// App.jsx import "./App.css"; import { Routes, Route, Link, useNavigate } from "react-router-dom"; import Home from "./pages/Home"; import Diary from "./pages/Diary"; import New from "./pages/New"; import Edit from "./pages/Edit"; import Notfound from "./pages/Notfound"; import { useReducer, useRef, createContext } from "react"; const mockData = [ { id: 1, createdDate: new Date("2024-11-13").getTime(), emotionId: 1, content: "1번 일기 내용", }, { id: 2, createdDate: new Date("2024-11-10").getTime(), emotionId: 2, content: "2번 일기 내용", }, { id: 3, createdDate: new Date("2024-10-11").getTime(), emotionId: 3, content: "3번 일기 내용", }, ]; function reducer(state, action) { switch (action.type) { case "CREATE": return [action.data, ...state]; case "UPDATE": return state.map((item) => String(item.id) === String(action.data.id) ? action.date : item ); case "DELETE": return state.filter((item) => String(item.id) !== String(action.id)); default: return state; } } export const DiaryStateContext = createContext(); export const DiaryDispatchContext = createContext(); function App() { const [data, dispatch] = useReducer(reducer, mockData); const idRef = useRef(3); const onCreate = (createdDate, emotionId, content) => { dispatch({ type: "CREATE", data: { id: idRef.current++, createdDate, emotionId, content, }, }); }; const onUpdate = (id, createdDate, emotionId, content) => { dispatch({ type: "UPDATE", data: { id, createdDate, emotionId, content, }, }); }; const onDelete = (id) => { dispatch({ type: "DELETE", id, }); }; return ( <> <DiaryStateContext.Provider value={data}> <DiaryDispatchContext.Provider value={{ onCreate, onDelete, onUpdate }}> <Routes> <Route path="/" element={<Home />} /> <Route path="/new" element={<New />} /> <Route path="/diary/:id" element={<Diary />} /> <Route path="/edit/:id" element={<Edit />} /> <Route path="*" element={<Notfound />} /> </Routes> </DiaryDispatchContext.Provider> </DiaryStateContext.Provider> </> ); } export default App; //Home.jsx import { useState, useContext } from "react"; import { DiaryStateContext } from "../App"; import DiaryList from "../components/DiaryList"; import Header from "../components/Header"; import Button from "../components/button"; const getMonthlyData = (pivotDate, data) => { const beginTime = new Date( pivotDate.getFullYear(), pivotDate.getMonth(), 1, 0, 0, 0 ).getTime(); const endTime = new Date( pivotDate.getFullYear(), pivotDate.getMonth() + 1, 0, 23, 59, 59 ).getTime(); return data.filter( (item) => beginTime <= item.createdDate && item.createdDate <= endTime ); }; const Home = () => { const data = useContext(DiaryStateContext); const [pivotDate, setPivotDate] = useState(new Date()); const monthlyData = getMonthlyData(pivotDate, data); console.log(monthlyData); const onIncreaseMonth = () => { setPivotDate(new Date(pivotDate.getFullYear(), pivotDate.getMonth() + 1)); }; const onDecreaseMonth = () => { setPivotDate(new Date(pivotDate.getFullYear(), pivotDate.getMonth() - 1)); }; return ( <div> <Header title={`${pivotDate.getFullYear()}년 ${pivotDate.getMonth() + 1}월`} leftChild={<Button onClick={onDecreaseMonth} text={"<"} />} rightChild={<Button onClick={onIncreaseMonth} text={">"} />} /> <DiaryList data={monthlyData} /> </div> ); }; export default Home; //diaryList.jsx import Button from "./button"; import "./DiaryList.css"; import DiaryItem from "./DiaryItem"; const DiaryList = ({ data }) => { return ( <div className="DiaryList"> <div className="menu_bar"> <select> <option value={"latest"}>최신순</option> <option value={"oldest"}>오래된 순</option> </select> <Button text={"새 일기 쓰기"} type={"POSITIVE"} /> </div> <div className="list_wrapper"> {data.map((item) => ( <DiaryItem key={item.id} {...item} /> ))} </div> </div> ); }; export default DiaryList; //DiaryItem.jsx import { getEmotionImage } from "../util/get-emotion-image"; import Button from "./button"; import "./DiaryItem.css"; const DiaryItem = (id, emotionId, createdDate, content) => { return ( <div className="DiaryItem"> <div className={`img_section img_section_${emotionId}`}> <img src={getEmotionImage(1)} /> </div> <div className="info_seciton"> <div className="created_date"> {new Date(createdDate).toLocaleDateString()} </div> <div className="content">{content}</div> </div> <div className="button_section"> <Button text={"수정하기"} /> </div> </div> ); }; export default DiaryItem;
-
미해결(2024 최신 업데이트)리액트 : 프론트엔드 개발자로 가는 마지막 단계
전체 소스코드는 어디서 받을 수 있나요?
전체 소스코드는 어디서 받을 수 있나요?
-
해결됨따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
overload 에러
import {Router, Request, Response} from "express"; import {User} from "../entities/User"; import { validate, Validate } from "class-validator"; const register = async (req: Request, res: Response) => { const {email, username, password} = req.body; try{ let errors: any = {}; //이메일/유저이름 단일성 확인 const emailUser = await User.findOneBy({email}); const usernameUser = await User.findOneBy({username}); //이미 있으면 erros 객체에 넣음 if(emailUser) errors.email = "이미 해당 이메일 주소가 사용되었습니다." if(usernameUser) errors.username = "이미 사용자 이름이 사용되었습니다." //에러가 있으면 return으로 에러를 response 보내줌 if(Object.keys(errors).length > 0){ return res.status(400).json(errors) } const user = new User(); user.email = email; user.username = username; user.password = password; //엔터티에 정해 놓은 조건으로 user 데이터 유호성 검사를 해줌 errors = await validate(user); //유저 정보를 user table에 저장 await user.save() return res.json(user); } catch(error){ console.error(error); return res.status(500).json({error}) } } const router = Router(); router.post("/register", register); export default router맨 위 코드(auth.ts)에서 사진과 같이 overload 에러가 뜹니다.유저이름/이메일 중복 및 에러 처리하는 코드 중 return으로 응답을 반환하는 중 타입이 맞지 않아서 생기는 오류 같은데 어떻게 해결할 수 있을까요??
-
미해결이미지 관리 풀스택(feat. Node.js, React, MongoDB, AWS)
소스코드 요청
혹시 강의 소스코드 받아 올 수 있을까요?제가 백엔드는 다 작성 했는데 프론트 쪽 하시는 분이 외국 분이라 설명하기에는 어렵고 해서 요청드립니다.
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
vercel 배포
배포는 잘 된 것 같은데요...? 계속 데이터 로딩중 페이지만 떠서 여쭤봅니다. 제 생각에는 받아올 데이터가 없어서 빈배열이라서 문제가 되는걸까 싶었지만, 선생님 강의에서도 동일하게 빈배열이지만 Header가 잘 나오는거보면 랜더링이 정상적으로 되는 것 같아서 받아올 데이터가 없는건 문제가 아닌듯하여 질문하게되었습니다. 혹시나 권한 오류일까 싶어 질문답변 글 참고하여 적용해봤으나 아닌 것 같습니다.
-
미해결[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
검색 결과 페이지네이션 1페이지(일단해결)
결론부터 말하면 검색할 때 페이지네이션 현재 페이지가 1로 안 바뀌어서 바꿔봤습니다.예를 들어 ‘철’이라는 검색어를 입력했더니 페이지가 2페이지까지 있음. 2페이지를 클릭해 2페이지가 보이는 상태에서 검색어를 ‘철수’로 바꾸니 게시글 수가 1페이지까지밖에 없었는데, 1페이지가 현재 activedPage가 아니게 됨(없어진 2페이지 그대로).검색한 게시글 목록 refetch는 제대로 이루어지기에 1페이지의 내용이 보이는 것은 맞지만 현재 페이지 숫자가 제대로 표시되지 않음. 또한 ‘안녕하세요’의 12페이지를 보고 있었는데 ‘안녕’으로 검색어를 바꾸니 당연히 refetch를 통해 1페이지 게시글 목록을 보여주지만, 페이지네이션은 그대로 11, 12, ..., 20임검색어가 바뀌면 페이지네이션의 activedPage와 startPage를 1로 변경해주도록 Paginations01.container에서 useEffect 실행시켜 해결 useEffect(() => { setStartPage(1); setActivedPage(1); }, [props.count]);검색어를 바꾸면 검색된 총 게시글 수도 보통 달라질 거라는 생각에 props.count를 의존성으로 써본건데 검색어를 바꿔도 우연히 검색된 총 게시글 수가 똑같을 경우 useEffect 실행 안 되니정말로 검색어가 달라질 때를 기준으로 하려고BoardList에 있는 keyword를 pagination 컴포넌트에 props로 넘겨줘서 사용// BoardList.presenter.tsx <Paginations01 refetch={props.refetch} count={props.count} keyword={props.keyword} /> // keyword 전달 // Paginations01.container.tsx useEffect(() => { setStartPage(1); setActivedPage(1); }, [props.keyword]); // Paginations01.types.ts export interface IPaginations01Props { ... keyword?: string; ... } 고쳐지긴 했는데 일단 useEffect에서 setState를 하고 있다는 점(여기선 크게 상관이 없는건지?)과페이지네이션 컴포넌트인데 keyword라는 걸 받아온다는 것 자체가 검색 컴포넌트의 영향을 받는다는 뜻 아닌가 싶어서(keyword는 검색 기능이 있을 때만 존재하니까) 제대로 된 컴포넌트 분리에 대한 고민(keyword?로 하면 페이지네이션 컴포넌트 쓸 때 keyword 써도 되고 안 써도 되니까 이대로 해도 괜찮을지...?)다른 방법은 있는지?의견 있으시면 알려주시면 감사하겠습니다. 그외 궁금한 점저는 이거 하는 과정에서 yarn dev 해놓은 상태에서 코드들을 저장 계속 하면서 고쳤는데 그럼 원래 바로바로 반영이 되잖아요. 코드에는 문제가 없어서 제대로 작동해야 했는데 페이지네이션 컴포넌트에서 props.keyword가 자꾸 undefined인 바람에 useEffect도 작동 안해서코드가 문젠줄 알고 한참 삽질 후 그냥 vscode와 크롬 등등 다 끄고 좀 나중에 그대로 다시 켜보니까 잘 작동하게 됐는데 (yarn dev를 끊었다 다시 하는 거로는 아마 해결 안됐음)이게 처음이 아니고 저번에도 한 번 포기하고 결국 다음날 켜보니까 코드는 그대로인데 갑자기 잘 되었는데정확히 무엇때문에 이런 문제가 생기는건지 모르겠네요!!! (캐시? .next? 뭐 그런 거 때문인가요?)
-
해결됨파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 (장고 4.2 기준)
models.py와 _song.html의 연결에 대해서 질문있습니다.
안녕하세요 강사님.보면 _song.html에서 models.py의 class song:을 가져다 쓰는것같습니다. {{ song.like_count }}html 파일안에서 이런식으로 쓰이는것같은데, 어떻게 연결을 시켰는지 알수있을까요?감사합니다.
-
해결됨[리액트 1부] 만들고 비교하며 학습하는 리액트 (React)
class와 constructor를 이용한 객체 지향 프로그래밍
안녕하세요 강사님 바닐라 자바스크립트로 프로젝트를 진행할때 class를 이용해서 이를테면, export default class SearchFormView extends View { constructor(){ super(qs("#search-form-view")) this.resetElement = qs("[type=reset]", this.element) this.showResetButton(false) console.log(this.element, "111") } showResetButton(visible = true){ this.resetElement.style.display = visible ? "block" : "none" } }와 같이 필요한 속성을 객체의 형태로 저장하고class를 통해 만들어낸 객체에서 필요한 속성을 꺼내는 방식으로 프로그래밍을 진행하셨는데이렇게 코딩을 해야하는 이유가 무엇인가요?직관적으로 와닿지가 않아서 그렇습니다 ㅠㅠ
-
해결됨한 입 크기로 잘라먹는 Next.js(15+)
클라이언트 컴포넌트에서 서버 컴포넌트 임포트
수업에서 Next.js에서는 클라이언트에 import 되는 서버 컴포넌트를 자동으로 클라이언트 컴포넌트로 변경해주는 동작을 한다. 라고 하셨는데요. 공식문서나 구글 문서를 아무리 찾아봐도 관련 언급이 없던데요. 혹시 출처를 알수 있을까요? 언제 업데이트 된건지 확인해보고 싶어서요
-
미해결한 입 크기로 잘라먹는 Next.js(15+)
6.5 에러핸들링 24:04 (with-searchbar) 레이아웃이 살아나지 않음
6.5 에러핸들링 24:04 (with-searchbar) 레이아웃을 살리기위해 error.tsx를 app/book/[id] 로 옮겨도 <Searchbar />가 보이지 않는 현상이 있습니다. 그리고 영상에서도 app/book/[id] 가 에러인 상황임에도 검색바 레이아웃이 보이는 장면이 없어서 헷갈리는 것 같습니다!
-
해결됨[리액트 1부] 만들고 비교하며 학습하는 리액트 (React)
mvc 패턴 질문
안녕하세요 강사님 강의는 단일 페이지에 대해서 mvc 패턴을 잡을 때하나의 페이지를 대상으로 controller views helpers.js, main.js, storage.js, Store.js를 만드셨는데 여러개의 페이지가 연결된 상황에서 여러 페이지를 동시에 작업하는 경우.. 폴더 구조가 어떻게 되는 건지 궁금합니다. 그러니깐.. 하나의 helpers, 하나의 storage, 하나의 Store.js를 만들고 거기 안에 여러 페이지에서 쓰는 로직들을 다 때려박는건지 아니면 각각의 페이지에 대해서 폴더를 만들고 helpers, storage, Store 같은 것을 각각 다 따로 만드는건지 현업에서 프로젝트는 어떻게 진행하는건지 궁금합니다!
-
미해결한 입 크기로 잘라먹는 Next.js(15+)
app-router route handler 에러 처리방법
import { type NextRequest, NextResponse } from 'next/server'; import { fetchData } from '@/shared/apis/fetch-data'; import type { IAcademyCreateDTO, IPostEnrollAcademyResponse } from '@/shared/types/acadmy'; export async function POST(req: NextRequest) { const body = (await req.json()) as Promise<IAcademyCreateDTO>; const data = await fetchData<IPostEnrollAcademyResponse>('/api/v1/academies', 'POST', body); if (!data.isSuccess) { return NextResponse.json( {}, { status: 500, statusText: data.message, }, ); } return NextResponse.json(data); }서버에, 에러시 아래와 같은 데이터 구조를 준다고 했을떄 위의 방식처럼, 에러 핸들링을 하는 것이 맞는지 궁금합니다... Route Handler의 보편적인 에러처리 방식이 너무 궁금합니다!! (직접 에러 메시지를 작성하는것이 아닌 서버에서 내려주는 에러메시지를 화면에 표기하고 싶습니다.)export type CommonResponse<T = unknown> = { code: string; isSuccess: boolean; message: string; result: T; };
-
미해결Next + React Query로 SNS 서비스 만들기
next-auth의 refresh token rotation에 관한 질문입니다.
안녕하세요 next-auth로 토큰 갱신 로직을 개발하는 중에 해결되지 않는 문제가 발생하여 질문 드립니다.현재 클라이언트에서 api 요청을 하면 middleware에서 const token = await auth(); 이런식으로 세션 정보를 가져와 accessToken을 헤더에 삽입하는 방식을 구현하였습니다. if (request.nextUrl.pathname.startsWith("/gateway")) { const session = await auth(); const accessToken = session?.accessToken; const { device } = userAgent(request); const localeFromCookie = cookieStore.get("dp_lang")?.value as string; const defaultLocale = getLanguageCodeFromLocale(localeFromCookie); request.headers.set("Accept", "*/*"); request.headers.set("Authorization", `Bearer ${accessToken}`); request.headers.set("Access-Control-Allow-Origin", "*"); request.headers.set("deviceType", "1"); request.headers.set("deviceId", getDeviceIdFromCookie(cookieStore)); request.headers.set("osType", getOsTypeFromCookie(cookieStore)); request.headers.set("User-Agent", device.model ?? ""); request.headers.set("locale", localeFromCookie); request.headers.set("language", defaultLocale); const response = NextResponse.next({ request: { headers: request.headers, }, }); return response; } 따라서 미들웨어에서 세션에 접근하는 순간에 jwt콜백이 실행되어 jwt 토큰에 저장되어 있는 토큰 expire 시간을 비교하여 만료여부를 판단 한 뒤에 토큰 갱신이 되도록 구현을 하였습니다. async jwt({ token, account, user }) { // Initial sign in if (account && user) { return { accessToken: user.accessToken, expiresAt: new Date( Date.now() + (user?.expiresIn ?? 0) ).toISOString(), refreshToken: user.refreshToken, serviceAvailable: true, }; } // Return previous token if the access token has not expired yet if ( new Date() < new Date(new Date(token.expiresAt as string).getTime() - 5000) ) { console.log("@@@@@@valid"); return token; } else { if (token.error === "RefreshTokenInvalid") { return token; } // Access token has expired, try tㄴo update it try { console.log("@@@@@@expired"); const refreshedTokens = await authApi.refreshAuthToken({ refreshToken: token.refreshToken as string, accessToken: token.accessToken as string, }); console.log("==========token refreshed========"); // reissue token return { ...token, accessToken: refreshedTokens.accessToken, expiresAt: new Date( Date.now() + (refreshedTokens.expiresIn ?? 18000) ).toISOString(), refreshToken: refreshedTokens.refreshToken ?? token.refreshToken, error: null, }; } catch (error) { console.error("Token refresh failed", error); if (error.status === RestApiErrorType.invalidTokenException) { return { ...token, error: "RefreshTokenInvalid", }; } return { ...token, error: "RefreshAccessTokenError" }; } } }, 기존에는 세션에 접근을 할때 next-auth의 jwt 콜백이 돌고 값이 리턴되면 쿠키의 session-token값에 암호화된 값들이 업데이트 되는 걸로 알고 있었는데 찾아보니 현재 세션에 접근하고 갱신하는 부분이 서버단에 있어서 쿠키가 업데이트 되지 않는다고 합니다. 따라서 현재 토큰이 만료된 후 한번에 3가지의 api 콜을 요청했을때 첫번째 api요청에서는 정상적으로 토큰 refresh가 요청이 되며 middleware에서 세션에 접근해 갱신된 토큰이 가져와져 요청이 성공되나 그 뒤 요청부터는 쿠키에 업데이트가 되지 않아서인지 세션에서 갱신 전 토큰이 가져와지는 현상이 발생하고 있습니다.클라이언트에서 세션 업데이트 후 세션에 접근을 해야 쿠키값이 갱신이 된다고 하는데 다른 방법이 있는지 문의드립니다.
-
미해결따라하며 배우는 리액트 네이티브 기초
Check the render method of `SceneView`. 오류
선생님 expo로 Aos 실행했을때 Check the render method of SceneView. 오류가 납니다.React Navigation 기능을 안쓰고 했을때는 오류가 안나는데 어떻게 해결하나요?
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
React.memo 메서드관련 질문드립니다.
10.3) 해당 강의에서 TodoItem 컴퍼넌트 리렌더링 실행 조건을 memo 메서드를 이용하여 커스터마이징할 때,if (prevProps.isDone !== nextProps.isDone) return false;이 문구에서 prevProps.isDone 값은 기존값이니 이해가 되었는데 nextProps.isDone 값은 해당 TodoItem 함수 내에 onCangeCheckbox 함수가 선행으로 실행이 되어야 알 수 있는 값 아닌가요? 그 전에 실행이 안 되도록 memo 메서드로 TodoItem의 리렌더링을 막고 있는데 어떻게 isDone 값이 바꼈다고 판단해서 리렌더링이 되는건지 모르겠습니다.
-
미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
react app 생성하기에서 npm i 오류
안녕하세요 section04 폴더로 react 앱 만들기 실습에서 라이브러리들을 다운받기 위해 npm i 를 하려고 했는데, 아래 이미지와 같은 오류들이 발생합니다. 인터넷을 찾아보니 권한 문제때문이라고 하던데 단순하게 sudo npm i를 하면 되는 걸까요?
-
미해결만들면서 배우는 리액트 : 기초
js파일 업로드 요청
학습하는 환경이 내부망이라<script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script> <script src="">https://unpkg.com/babel-standalone@6/babel.min.js"></script>위 js들을 직접 다운로드 받아 반입해야 하는데요..리액트 사이트에서 리액트 라이브러리는 다운로드가 되는데babel은 다운로드가 안되네요;;js파일을 직접 다운로드할 수 있도록 학습용 코드 올려진 곳에 업로드 해주시면 감사하겠습니다.