묻고 답해요
130만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
newaccessToken 질문드립니다
만약에 지금 발급된 accessToken 이 만료되지 않은 상황이라면 해당 강의에서의 aaa.toPromise().then((newAccessToekn) =>{}) 함수 실행시에 newAccessToken 이 발급되지 않는 걸까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
수업 정답코드좀 알려주세요
이부분 이거 말고도 소과제 있는 부분 전부 다 정답코드 어디에 있나요? 아무리 찾아도 안나와요 자세한 경로좀 알려주세요
-
미해결[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
댓글 삭제 시 애니메이션 추가하고싶습니다.
안녕하세요. 현재 댓글 수정, 삭제 구현중에 있습니다.강의 과정에는 없지만 추가적으로 궁금한 부분이 있어 질문 드립니다. 댓글을 삭제하는 경우, 바로 반영되어 댓글이 삭제되기는 하나애니메이션을 적용시켜 천천히 사라지며 삭제되는 코드를 짜고싶습니다.현재 TransitionGroup, CSSTransition, keyframes 컴포넌트를 사용해애니메이션은 적용이 되고 있으나, 삭제시 삭제되는 해상 댓글에만 적용하기는 너무 어렵네요생각하기로는, 해당 댓글의 id 값을 스타일시트로 받아와서 스타일시트에서 해당 _id의 댓글만 애니메이션을 적용하면 될 것 같은데 생각대로 되지 않는 것 같습니다.어떻게 하면 좋을지 힌트라도 얻을 수 있을까요? import { getDateTime } from '../../../../commons/libraries/utils'; import * as S from './BoardCommentDetail.styles'; import { TransitionGroup, CSSTransition } from 'react-transition-group'; import { useEffect } from 'react'; export default function BoardCommentDetailUI(props) { useEffect(() => { // 댓글이 변경될 때 추가적인 정리 또는 부작용을 수행할 수 있습니다. }, [props.data?.fetchBoardComments]); return ( <div> <TransitionGroup> {props.data?.fetchBoardComments.map((el) => ( <CSSTransition> <S.CommentWrapper> <S.Comment> <S.ProfileImg> <img src={`/img/profileIcon.svg`} width={48} height={48} /> </S.ProfileImg> <S.CommentContentsArea> <S.CommentContentsWriter> <S.ContentsWriter>{el.writer}</S.ContentsWriter> <S.ContentsRate value={el.rating} disabled /> </S.CommentContentsWriter> <S.CommentContents>{el.contents}</S.CommentContents> <S.CommentDate>{getDateTime(el.createdAt)}</S.CommentDate> </S.CommentContentsArea> <S.WriterIconWrapper> <img src={`/img/mode-24px.svg`} /> </S.WriterIconWrapper> <S.WriterIconWrapper id={el._id} onClick={() => props.onClickDeleteComment(el._id)} > <img src={`/img/clear-24px.svg`} /> </S.WriterIconWrapper> </S.Comment> </S.CommentWrapper> </CSSTransition> ))} </TransitionGroup> </div> ); }import { useMutation, useQuery } from '@apollo/client'; import { FETCH_BOARD_COMMENTS, DELETE_BOARD_COMMENT, } from './BoardCommentDetail.queries'; import { useRouter } from 'next/router'; import BoardCommentDetailUI from './BoardCommentDetail.presenter'; import { useState } from 'react'; export default function BoardCommentDetail() { const router = useRouter(); const [commentIdToDelete, setCommentIdToDelete] = useState(null); const { data, refetch } = useQuery(FETCH_BOARD_COMMENTS, { variables: { boardId: router.query.boardId }, }); const [deleteBoardComment] = useMutation(DELETE_BOARD_COMMENT); const onClickDeleteComment = async (commentId) => { setCommentIdToDelete(commentId); const isConfirmed = window.confirm('댓글을 삭제하시겠습니까?'); if (isConfirmed) { try { const passwordConfirmation = prompt('비밀번호를 입력하세요'); await deleteBoardComment({ variables: { boardCommentId: commentId, password: passwordConfirmation, }, }); alert('댓글이 삭제되었습니다.'); refetch(); } catch (error) { console.error('댓글 삭제 중 오류 발생', error); } } }; return ( <BoardCommentDetailUI data={data} onClickDeleteComment={onClickDeleteComment} /> ); }
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
15:24 초에 createBoard 값으로 받은 result 값
15:24 초에 createBoard 값으로 받은 result 값을콘솔에 찍어보면data.createBoard 값에 저장된 값이_typename , _id 값 두개만 보이는데백엔드 API 설계 당시에 뮤테이션의 리턴값으로 저 2개의 ㄱ값만 리턴하도록 설정되어 있는 건가요? 아님 요약 정보만 추려서 보여주는 건가요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
route 53 질문드립니다
s3 를 다음과 같이 만들었는데 다음과 같이 별칭에서 나오지 않는데 어떻게 해야되나요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
도메인을 구입하지 않으면 해당 실습은 못하는 건가요?
실습을 위한 아무 도메인을 구매하면 되는지 궁금해서 질문드립니다
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
로그인시 hocs 질문
안녕하세요. hocs 관련해서 질문하나 남깁니다. 강사님께서 새롭게 진행해주신 refreshtoken이후의 로그인 체크를 통해, 진행하던 중 질문이 생겨 여쭙습니다. 문제점 : loginUser를 통해 로그인을 진행한 후 logoutUser을 통해 로그아웃을 한 뒤 로그인 창으로 돌아와 새로고침을 누르고 로그인을 하려고 하면 hocs에서 막히게 됩니다.로그인 > 로그아웃 > 새로고침 > 재로그인(hocs 오류) 로그를 찍으며 확인을 해보니첫 로그인 당시 로그첫 로그인 성공 후 로그로그아웃 후 새로고침 시 로그여기서 문제가 발생합니다. recoil store에서 공유하고 있는 restoreAccessTokenLoadable 함수가 로그아웃 후 새로고침을 하면 undefined을 반환을 합니다. 이후 withauth에서도 promise가 반환되지 않아서 로그인권한 오류가 발생하고 있습니다. 현재 restoreAccessTokenLoadable 코드입니다export const restoreAccessTokenLoadable = selector({ key: "restoreAccessTokenLoadable", get: async () => { const newAccessToken = await getAccessToken(); console.log(newAccessToken, "restoreaccess 결과입니다"); return newAccessToken; }, });해결 방법이 있을까요?? 혹시 몰라 다른 부분 코드도 첨부합니다withauth (로그인체크권한)useEffect(() => { console.log("withauth가 실행되었습니다"); void aaa.toPromise().then((newAccessToken) => { console.log(newAccessToken, "withauth결과입니다"); console.log(aaa); if (newAccessToken === undefined) { alert("로그인 후 이용가능합니다."); void router.push("/section30/30-01-login-refreshtoken"); } }); }, []);apollo에서 useEffect부분 const [accessToken, setAccessToken] = useRecoilState(accessTokenState); const aaa = useRecoilValueLoadable(restoreAccessTokenLoadable); useEffect(() => { void aaa.toPromise().then((newAccessToken) => { setAccessToken(newAccessToken ?? ""); }); }, []);입니다 감사합니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
섹션별 과제 정답코드
섹션별 과제 정답코드는 어디에 있나요? 포트폴리오 말고요
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
포트폴리오 관련 질문 - 오늘 본 상품
안녕하세요. 포트폴리오 작성 중 여러 방법을 시도해 보다 도저히 해결방법을 잘 모르겠어서 질문드립니다.구현하고 싶은 것 : 오늘 본 상품 목록을 다른 페이지에서 구현 하는 것이 아닌 여러 페이지의 본문 영역 옆에 상시 뜨도록 설계 하는 것, recoil을 이용하지 않고 localStorage 를 이용하여 구현하는 것 입니다. 아래 사진은 현재 진행 과정 입니다.아래는 현재 코드입니다sidebar.tsx import { useEffect, useState } from "react"; import * as S from "./sidebar.style"; import type { IUseditem } from "../../../../commons/types/generated/types"; import { LikeFilled } from "@ant-design/icons"; import { getPrice } from "../../../../commons/libraries/price"; export default function SideBar(): JSX.Element { const [items, setItems] = useState<IUseditem[]>([]); useEffect(() => { const storedItems = localStorage.getItem("todaylist"); if (!storedItems) return; setItems(JSON.parse(storedItems)); }, []); return ( <S.SideBarWrapper> <S.SideBarTitle>오늘 본 상품</S.SideBarTitle> {items .filter((el) => el) .map((el) => ( <S.SideBarContents key={el._id}> <S.SideBarP> <LikeFilled style={{ color: "#ffd903" }} /> {el.pickedCount} </S.SideBarP> {el.images && ( <S.SidaBarImg src={`https://storage.googleapis.com/${el.images[0]}`} /> )} <S.SidebarDetail> <S.SideBarName>{el.name}</S.SideBarName> <S.SideBarRemarks>{el.remarks}</S.SideBarRemarks> <S.SideBarPrice>{getPrice(el.price)}</S.SideBarPrice> </S.SidebarDetail> </S.SideBarContents> ))} </S.SideBarWrapper> ); } 문제점useEffect 부분에서 storedItems 가 업데이트 될 때마다, 리렌더링을 해주고 싶어, 종속성 배열에 items state를 넣으니 ⚠ Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.관련 오류가 뜹니다. 여러 방법을 시도해도 옳은 방법을 잘 모르겠어서 질문 남깁니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
타입스크립트 설치파트에서 에러가 납니다.
타입스크립트 설치하고 yarn dev 한 이후, yarn add --dev @types/react @types/node 을 통해추가 설치 ? 를 진행하려고 보니 강사님은 아무 에러 없이 잘 진행 되는 반면에 저는 이러한 에러가 뜹니다... ㅠ
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
.indexOf 메소드 사용 질문
안녕하세요, indexOf 메소드를 사용하다가 -1 값이 변환되었습니다. 파이썬에서는 인덱스가 -1이라면 맨마지막에 있는 인덱스 순서를 의미하는데 자바스크립트는 의미가 다른가요?자바스크립트에서 가지는 '-1'의 의미가 궁금합니다. 코드를 보시면 제가 indexOf 메소드 값 안에 오타를 넣었습니다.오류가 날 줄 알았는데 오타의 인덱스 값이 -1이 반환되어서 -1 값이 나온 이유에 대해 설명 부탁드립니다. 감사합니다. 수업 잘 듣고 있습니다. :)
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
next export 질문있습니다
next 14 버전부터 next export 가 없어지고 next.config.js 파일에서 output: "export" 로 대체되었다는데 이대로 진행해도 문제 없을까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
퀴즈5 비밀번호 유효성 검증
비밀번호와 비밀번호 확인이 서로 일치하는지 검증하는 코드를 어떻게 짜야할 지 모르겠어요.. 현재 코드로 하면 에러가 납니다..! 봐주시면 감사하겠습니다ㅠㅠ 해당코드 //문제부분!!!!!!!!!!!!!!!!!!!!********* 으로 해놓았습니다!! import { useState } from 'react'; export default function signUpPage() { //이메일, 비밀번호 담기 const [ email, setEmail ] = useState(""); const [ password, setPassWord ] = useState(""); const [ Repassword, setRePassWord ] = useState(""); //이메일 에러 const [ emailError, setEmailError ] = useState(""); //비밀번호 에러 const [ passWordError, setPassWordError ] = useState(""); //비밀번호확인 에러 const [ RepassWordError, setRePassWordError ] = useState(""); //이메일 const onChangeEmail = (event) =>{ //이벤트 핸들러 console.log(event); console.log(event.target); //작동된 태그 console.log(event.target.value); //작동된 태그에 입력된 값 //변경된 이메일 값을 넣음 setEmail(event.target.value); if(event.target.value !== ''){ //내용 입력시 에러 없애주는거 setEmailError(""); } } const onChangePassWord = (event) => { setPassWord(event.target.value); if(event.target.value !== ''){ setPassWordError(""); } } //문제부분!!!!!!!!!!!!!!!!!!!!********* const onChangeRePassWord = (event) => { // const currentPassWord = event.target.value; // setRePassWord(currentPassWord); // if(password === currentPassWord){ // setRePassWordError(""); // } setRePassWord(event.target.value); if((password === Repassword()) || (event.target.value !== '')){ setRePassWordError(""); } } //등록하기 버튼 에러검증 const onClickSign = () => { //이메일 @ 검증 //includes("") 해당 문자가 있냐 없냐 if(email.includes("@") === false) { setEmailError("이메일이 올바르지 않습니다. @ 형태로 입력해주세요!") } if(!password){ setPassWordError("비밀번호를 입력해주세요") } //문제부분!!!!!!!!!!!!!!!!!!!!********* if((password !== Repassword) || (!Repassword)){ setRePassWordError("비밀번호를 확인해주세요") } //회원가입 완료 if(email && password === Repassword) { alert("회원가입이 완료되었습니다") } } return( <> 이메일: <input type="text" onChange={onChangeEmail} /> <div>{emailError}</div> 비밀번호 :<input type="text" onChange={onChangePassWord} /> <div>{passWordError}</div> 비밀번호확인 :<input type="text" onChange={onChangeRePassWord} /> <div>{RepassWordError}</div> <button id="submit" onClick={onClickSign}>회원가입</button> </> ) }
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
jest 오류 'Assertion' 형식에 'toBe' 속성이 없습니다.
'Assertion' 형식에 'toBe' 속성이 없습니다. 이 오류가 jest관련 toBe, toEqual, toBeInTheDocument등에 다 뜹니다
-
미해결[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
ApolloError: request to http://mock.com/graphql failed, reason: response3.headers.all is not a function
33-05 강의에서 test에서 자꾸 이 오류가 뜹니다apis.jsimport { graphql } from "msw"; const gql = graphql.link("http://mock.com/graphql") export const apis = [ gql.mutation("createBoard", (req, res, ctx) => { const { writer, title, contents } = req.variables.createBoardInput return res( ctx.data({ createBoard: { _id: "qqq", writer, title, contents, __typepname: "Board", }, }) ); }), // gql.query("fetchBoards", () => {}) ]; jest.setup.jsimport { server } from "./src/commons/mocks/index" beforeAll(() => server.listen()); afterAll(() => server.close()); index.test.tsx import { fireEvent, render, screen, waitFor } from "@testing-library/react"; import StaticRoutingMovedPage from "../../pages/section33/33-05-jest-unit-test-mocking"; import { ApolloClient, ApolloProvider, HttpLink, InMemoryCache, } from "@apollo/client"; import fetch from "cross-fetch"; import mockRouter from "next-router-mock"; jest.mock("next/router", () => require("next-router-mock")); it("게시글이 잘 등록되는지 테스트 하자!", async () => { const client = new ApolloClient({ link: new HttpLink({ uri: "http://mock.com/graphql", fetch, }), cache: new InMemoryCache(), }); render( <ApolloProvider client={client}> <StaticRoutingMovedPage /> </ApolloProvider> ); fireEvent.change(screen.getByRole("input-writer"), { target: { value: "맹구" }, }); fireEvent.change(screen.getByRole("input-title"), { target: { value: "안녕하세요" }, }); fireEvent.change(screen.getByRole("input-contents"), { target: { value: "방가방가" }, }); fireEvent.click(screen.getByRole("submit-button")); await waitFor(() => { expect(mockRouter.asPath).toEqual("/boards/qqq"); }); }); 도와주십쇼 ㅠㅠ
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
06-01-container-presenter 에러
강의를 잘 따라가면서 작성하고 있었는데 화면을 최종적으로 확인할 때 이런 에러가 뜹니다. 코드를 두번확인했는데 틀린 부분이 보이지않습니다 ..! index.js 코드 입니다import BoardWrite from '../../../src/components/units/board/write/BoardWrite.container' export default function GraphqlMutationPage(){ return ( <> <div>###### 여기는 페이지 입니다 ######</div> {/* //로직을 가져옴 */} <BoardWrite /> <div>###### 여기는 페이지 입니다 ######</div> </> ) }BoardWrite.container.js 코드 입니다import { useMutation } from '@apollo/client' import {useState} from 'react' //UI를 가져옴(파일을 합침) import BoardWriterUI from './BoardWrite.presenter' //gql 가져옴(파일을 합침) import {나의그래프큐엘셋팅} from './BoardWrite.queries' //로직만 사용 export default function BoardWrite() { const [writer, setWriter] = useState() const [title, setTitle] = useState() const [contents, setContents] = useState() const [나의함수] = useMutation(나의그래프큐엘셋팅); const onClickSubmit = async () => { const result = await 나의함수({ variables: { writer: writer, title: title, contents: contents } }) console.log(result) }; const onChangeWriter = (event) => { setWriter(event.target.value) // => state에 저장 } const onChangeTitle = (event) => { setTitle(event.target.value) } const onChangeContents = (event) => { setContents(event.target.value) } return( <> <div>$$$$$$$ 여기는 컨테이너 입니다 $$$$$$</div> {/* UI를 가져옴(파일을 합침) */} <BoardWriterUI aaa={onClickSubmit} bbb={onChangeWriter} ccc={onChangeTitle} ddd={onChangeContents} /> <div>$$$$$$$ 여기는 컨테이너 입니다 $$$$$$</div> </> ) } BoardWrite.presenter.js 코드 입니다import {BlueButton, RedInput } from './BoardWrite.style' //UI만 사용 export default function BoardWriterUI(props){ return( <> <div>@@@@@@@@ 여기는 프리젠터 입니다 @@@@@@@</div> <div> 작성자: <RedInput type="text" onChange={props.bbb} /> 제목: <input type="text" onChange={props.ccc} /> 내용: <input type="text" onChange={props.ddd} /> <BlueButton onClick={props.aaa}>GRAPHQL-API 요청하기</BlueButton> </div> <div>@@@@@@@@ 여기는 프리젠터 입니다 @@@@@@@</div> </> ) }BoardWrite.queries.js 코드 입니다import { gql } from '@apollo/client' export const 나의그래프큐엘셋팅 = gql` mutation createBoard($writer: String, $title: String, $contents: String){ createBoard(writer : $writer , title: $title , contents: $contents) { _id number message } } BoardWrite.style.js 코드 입니다import styled from '@emotion/styled' export const RedInput = styled.input` border-color: red; ` export const BlueButton = styled.button` background-color: blue; ` app.js 코드 입니다// 모든 페이지의 공통설정들 여기서 진행 import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client' export default function App({ Component, pageProps }) { const client = new ApolloClient({ uri:"http://backend-example.codebootcamp.co.kr/graphql", cache: new InMemoryCache() //컴퓨터의 메모리에다가 백엔드에서 받아온 데이터 임시로 저장해 놓기 => 나중에 더 자세히 알아보기 }) return ( <div> <div> ========== 여기는 _app.js 컴포넌트 시작부분 입니다. ==========</div> {/* //그래프큐엘 셋팅 => 앞으로 아래 컴포넌트에서 client를 쓸 수 있다는 의미 */} <ApolloProvider client={client}> <Component /> {/* 내가 들어간 페이지들의 html이 여기로 다 들어오게 됨 */} </ApolloProvider> <div> ========== 여기는 _app.js 컴포넌트 마지막부분 입니다. ==========</div> </div> ) } 마지막으로 폴더 구조입니다
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
section8 포폴 리뷰 에러가 납니다.
boards/new/index.js 에서 항목 기입 후 등록하기 버튼을 누를 시 등록된 상세페이지로 넘어가지 않고 alert 알림창으로 "Response not successful: Received status code 400" 이렇게 뜹니다.오타는 혹시 있나 해서 올려주신 깃허브랑 하나하나 꼼꼼히 비교 했는데 없었어요..오류코드를 개발자도구로 뜯어보니 그래서 해당 부분 확인해봐도 모두 강사님과 동일하게 작성되있는데 뭐가 문제일까요
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
블로그 학습일지 저작권 관련 문의
안녕하세요 저작권 관련 질문드립니다! 본 학습 자료의 저작권은 코드캠프에 있어 무단 도용, 배포, 복제를 금지한다고 적혀있는데 그럼 혹시 개인 블로그에 내용을 공부한 내용을 정리한 것을 공개 처리해두어도 문제가 되지 않을지 문의드립니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
포트폴리오 깃허브
포트폴리오를 깃허브에 올리려고 하는데 git허브강좌 보면서 따라하고 있었는데 git add . 후 git status 하면은 해당 오류가 떠요 .. admin@DESKTOP-8KF9PK5 MINGW64 ~/Desktop/portfolio (master)$ git add .admin@DESKTOP-8KF9PK5 MINGW64 ~/Desktop/portfolio (master)$ git statusOn branch masterNo commits yetChanges to be committed:(use "git rm --cached <file>..." to unstage)new file: freeboard_frontendChanges not staged for commit:(use "git add <file>..." to update what will be committed)(use "git restore <file>..." to discard changes in working directory)(commit or discard the untracked or modified content in submodules)modified: freeboard_frontend (modified content, untracked content) 해당 폴더 구조는 이렇습니다 보니까 .git이 이중으로 설치되어 있는데 어디 부분을 어떤 명령어로 삭제해야하는지 알려주시면 감사하겠습니다..!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
콘솔로그가 2번 찍히는데 이유를 잘 모르겠습니다.
05-05-dynamic-routing-board-mutation강의에 있는 내용을 구현했습니다이상은 없게 정상 작동하는데콘솔로그가 2번 찍히는데 이해가 가지 않습니다===========================================폴더구조================================================05-05-dynamic-routing-board-mutation/index.jsimport {gql, useMutation} from "@apollo/client"; import {useRouter} from "next/router"; const 나의그래프큐엘세팅 = gql` mutation createBoard($writer: String, $title: String, $contents: String){ createBoard(writer: $writer, title: $title, contents: $contents){ _id number message } } ` export default function GraphqlMutationPage() { const router = useRouter() const [나의함수] = useMutation(나의그래프큐엘세팅) const onClickSubmit = async () => { try{ // try에 있는 내용을 시도하다가 실패하면, 다음에 있는 모든 줄들을 모두 무시하고, catch에 있는 내용이 실행됨. const result = await 나의함수({ variables: { writer: "호날두", title: "모두다 외쳐", contents: "Siuuuu~~~~~~" } }) //console.log("result 값은 다음과 같습니다", result) //console.log("동적라우팅 주소는 number라고 지칭했고 다음과 같아요", result.data.createBoard.number) // router.push('/section05/05-05-dynamic-routing-board-mutation-moved' + result.data.createBoard.number) router.push(`/section05/05-05-dynamic-routing-board-mutation-moved/${result.data.createBoard.number}`) }catch (error){ alert(error.message) } } return <button onClick={onClickSubmit}>GRAPHQL-API 요청하기</button> // 한줄일 때는 괄호 ( ) 가 필요없다. }===========================================================05-05-dynamic-routing-board-mutation-moved/[number]/index.jsimport {gql, useQuery} from "@apollo/client"; import {useRouter} from 'next/router' const FETCH_BOARD = gql` query fetchBoard($number: Int){ fetchBoard(number:$number){ # 1번 게시글 내용에 생략된 내용이 많아서 19047을 1번 게시글로 가정 number writer title contents } } ` export default function StaticRoutingMovedPage(){ const router = useRouter() console.log("라우터에 뭐가 들어있는지 알아보기",router) const { data } = useQuery(FETCH_BOARD, { variables: { number: Number(router.query.number) } }) console.log("데이터에 뭐가 들어있는지 알아보기",data) return( <> <div>{router.query.number}번 게시글 이동이 완료됐어요!!😀😀</div> <div>작성자: {data && data.fetchBoard?.writer}</div> <div>제목: {data?.fetchBoard?.title}</div> <div>내용: {data? data.fetchBoard?.contents : "로딩중입니다."}</div> </> ) }==================================================================브라우저 콘솔창-> 여기서 GraphQL요청 후 콘솔 찍어놓은게 2번 반복됩니다.위의 내용 확대 ==================================================================네트워크 탭여기에 GraphQl 요청이 두번 나간 것 같은데 그것 때문에 그런 건가요?아니면 data 내용을 콘솔 찍었을때 한번 undefined 처리가 되어서 데이터를 받아오는 과정에서 한번 더콘솔이 찍힌건가요?