묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
강의 ver1, ver2 뭘듣고 있는지 어떻게 알수있나요?
강의 ver1, ver2 뭘듣고 있는지 어떻게 알수있나요? ver1, ver2 표시가 안되어있어서요!html, css, javascript 는 노션 링크 따로있나요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
onChangePasswordCheck [password] 인자 문의
안녕하세요 zerocho 님아래 코드에서 const onChangePasswordCheck = useCallback( (e) => { console.log("onChangePasswordCheck1 :" + e.target.value); console.log("onChangePasswordCheck2:" + passwordCheck); //전 값을 참조함 setPasswordError(e.target.value !== password); setPasswordCheck(e.target.value); }, [password] //passwordCheck 로 바꾸어도 전 값을 참조함 ); 1.[password] 부분을 [] 바꾸어도 정상 작동 하는 것 같구요 [] 의미는 최초 render 시에만 함수를 생성한다는 의미로 알고 있습니다만...2.[passwordCheck]로 바꾸면... [웹 게임을 만들며 배우는 React/6-5. useMemo와 useCallback] 강의에 의하면 onChangePasswordCheck 안에서 passwordCheck 가 정상 참조 되어야 할 것 같은데.. 이전 값으로 참조 되는 것 같습니다. 2번째 인자 작동 방식이 정확히 이해 되지 않습니다.다시 한번 설명 부탁 드려도 될까요? (참고자료나, zerocho님, 다른 강의 부분 알려 주시면 직접 찾아 보겠습니다.)감사합니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
깃주소
깃주소 알려주세요, 뭐 다 들어야 깃 주소를 아는건지 왜 찾을수가 없나요
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
중고마켓 게시물 Pick
혹시 중고마켓에서 게시글들어갈때 해당 게시글을 찜했는지 알 수 있는 API가 있을까여?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
이미지 못찾겠네요
강력한 css 섹션 5 단위심화 강의에서 고슴도치 이미지 파일을 자료에 올려놨다고 하는데 못찾겠어요 ㅡㅡ...뭔 자료를 이렇게 찾기 힘들게 올려논건지?장난하나.. 이미지 찾다가 시간 다갔네
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
serverState undefine 출력
import { configureStore } from "@reduxjs/toolkit"; import { createWrapper } from "next-redux-wrapper"; import reducer from "../reducers"; function getServerState() { return typeof document !== "undefined" ? JSON.parse(document.querySelector("#__NEXT_DATA__").textContent)?.props .pageProps.initialState : undefined; } const serverState = getServerState(); console.log("serverState", serverState); const makeStore = () => configureStore({ reducer, devTools: true, middleware: (getDefaultMiddleware) => getDefaultMiddleware(), preloadedState: serverState, // SSR }); const wrapper = createWrapper(makeStore); export default wrapper;ssr 문제를 계속 해결해보고 있는데 지금 보니 console.log()에 serverState가 undefined가 나옵니다 이게 혹시 문제의 원인인가 싶어서 그런데 serverState는 무었이고 왜 undefined가 나오나요?
-
해결됨따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
DB만 도커 컨테이너로 올리는 이유?
안녕하세요 선생님, 좋은 강의 항상 감사드립니다^^현재 이 강의에서 DB를 Docker Container 안에 올렸는데, 이 이유가 궁금합니다. 구글링 했을 때는 DB가 안전하게 관리되는 것이 최우선이기 때문에, 현업에서는 On-premise 환경에서 구축한다는데,현재 저희는 빠르게 배포하는 것이 목적이기 때문에 docker 환경에 구성하는 것일까요?
-
해결됨Next.js 시작하기(feat. 지도 서비스 개발)
시작 할때 0-2 branch 에서 시작 하는게 맞나요?
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.빈 폴더에서 npx create-next-app@latest --typescript 로 시작 해야 하는지 아니면 받은 소스의 0-2 브랜치 에서 npx create-next-app@latest --typescript 로 시작 하는게 맞는지 어떤건가요?
-
해결됨Next.js 시작하기(feat. 지도 서비스 개발)
useEffect의 clean up 함수를 실행해야 하는 이유가 무엇일까요??
안녕하세요 강사님! 유익한 강의 아주 잘 듣고 있습니다.혹시 컴포넌트 unmount 시 맵 객체를 destroy 해야 하는 이유를 알 수 있을까요?destroy를 하지 않아도 코드 동작에는 큰 문제가 없는 것 같습니다. 혹시 메모리 상의 문제나 다른 문제가 있어서 이 코드를 작성해야 하는걸까요??next/script로 네이버 지도 불러오기 강의 (8:40)useEffect(() => { return () => { mapRef.current?.destroy(); } }) 예를 들면, setInterval의 경우 Unmount시 clearInterval을 하지 않을 경우 계속 백그라운드에서 실행되기 때문에 clearInterval을 해줘야한다고 바로 이해가 됐습니다. 하지만 위의 경우 꼭 맵 객체를 destroy 해야하는걸까요??
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
redux toolkit ssr 질문
계속 똑같은 부분을 질문하고있는데 혹시 똑같은 오류가 발생하고 이 부분 코드는 양이 적고 코드 양이 적어서 오류의 원인을 아는데 용이 할꺼 같아 질문드립니다pages/about.js import React from "react"; import { useSelector } from "react-redux"; import Head from "next/head"; import { Avatar, Card } from "antd"; import AppLayout from "../components/AppLayout"; import wrapper from "../store/configureStore"; import { loadUserInfo } from "../reducers/user"; const Profile = () => { const { userInfo } = useSelector((state) => state.user); return ( <AppLayout> <Head> <title>ZeroCho | NodeBird</title> </Head> {userInfo ? ( <Card actions={[ <div key="twit"> 짹짹 <br /> {userInfo.Posts.length} </div>, <div key="following"> 팔로잉 <br /> {userInfo.Followings.length} </div>, <div key="follower"> 팔로워 <br /> {userInfo.Followers.length} </div>, ]} > <Card.Meta avatar={<Avatar>{userInfo.nickname[0]}</Avatar>} title={userInfo.nickname} description="노드버드 매니아" /> </Card> ) : null} </AppLayout> ); }; export const getStaticProps = wrapper.getStaticProps( (store) => async ({ req }) => { console.log("getStaticProps"); await store.dispatch(loadUserInfo(1)); } ); export default Profile; reducers/user.js export const loadUserInfo = createAsyncThunk( "/user/LoadUserInfo", async (data) => { const response = await axios.get(`/user/${data}`, data); return response.data; } ); const userSlice = createSlice({ name: "user", initialState, reducers: { addPostToMe(draft, action) { // 값을 하나만 전달해서 값이 바로 payload에 저장이된다 // 내가 만든 포스트를 me state에 저장하는 reducer draft.me.Posts.unshift({ id: action.payload }); }, removePostOfMe(draft, action) { draft.me.Posts = draft.me.Posts.filter((v) => v.id !== action.payload); }, }, // 외부에서 action을 만든것은 extraReducers로 가져와서 사용한다 주로 createAsyncThunk로 action을 만들 때 사용한다 extraReducers: (builder) => builder .addCase([HYDRATE], (state, action) => ({ ...state, ...action.payload.user, })) // 다른유저정보 가져오는 리듀서 .addCase(loadUserInfo.pending, (state, action) => { state.loadUserInfoLoading = true; state.loadUserInfoError = null; state.loadUserInfoDone = false; }) .addCase(loadUserInfo.fulfilled, (state, action) => { state.loadUserInfoLoading = false; state.me = action.payload; state.loadUserInfoDone = true; }) .addCase(loadUserInfo.rejected, (state, action) => { state.loadUserInfoLoading = false; state.loadUserInfoError = action.error; }) .addDefaultCase((state) => state), });이런 코드인데 // 다른유저정보 가져오는 리듀서 .addCase(loadUserInfo.pending, (state, action) => { state.loadUserInfoLoading = true; state.loadUserInfoError = null; state.loadUserInfoDone = false; }) .addCase(loadUserInfo.fulfilled, (state, action) => { state.loadUserInfoLoading = false; state.me = action.payload; state.loadUserInfoDone = true; }) .addCase(loadUserInfo.rejected, (state, action) => { state.loadUserInfoLoading = false; state.loadUserInfoError = action.error; })제가 이것저것 하다가 알게된거 action에 이부분을 전부 주석처리하게 되면 에러가 안난다는 겁니다 그래서 결정적으로 initalstate에 있는 변수들을 변경하는 과정이 브라우저의 정보와 서버의 정보를 다르게만드는 일을 하는것 같은데 혹시 의심가시는거 있으신가요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
노션 강의자료
노션에 있는 자료들이랑 실제 강의에서 쓰이는 자료들이랑 차이가 좀 있네요. 강의에 들어있는 내용이 다 들어있는 것도 아니고요... 혹시 추후에 보강되거나 강의에 나오는 자료가 제공되진 않을까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
Section 50 퀴즈 관련 질문입니다.
backend playground를 보고 작업하고 있으나 추가로 질문 드려야만 해결할 수 있는 부분이 있어 여쭤봅니다.loading 페이지에서 createPointTransactionOfLoading을 사용하여 이것을 complete 페이지에서 fetch해서 가져와야할 거 같은데 fetch 할 때 필요한 api를 모르겠어서 임시로 fetchPointTransactionsOfSelling로 했습니다. createPointTransactionOfLoading 부분에서 id는 사용자 아이디인데 impUid는 뭘 의미하나요? 회원가입 하면 id가 발급되는 것처럼 해당 api에서 자체적으로 발급되는 걸까요?amount가 포인트 양인 것 같아서 기존의 포인트에 포인트를 중첩하려면 loading과 complete에 동일한 api를 fetch해서 Selected를 더하는 게 맞나요?createPoint와 fetchPoint할 때 필요한 요소는 뭐가 더 있는지 궁금합니다.complete 페이지에서 'IPointTransaction[]' 형식에 'amount' 속성이 없습니다. 라고 뜨는데 어떻게 해결하나요? 작성한 코드입니다.complete ({data?.fetchPointTransactionsOfSelling.amount}에 amount 속성이 없다는 빨간 줄) import { gql, useQuery } from "@apollo/client" import type { IQuery, IQueryFetchPointTransactionsOfSellingArgs } from "../../../../src/commons/types/generated/types" const FETCH_POINT = gql` query { fetchPointTransactionsOfSelling { _id impUid amount } } ` export default function CompletePage():JSX.Element { const { data } = useQuery<Pick<IQuery,"fetchPointTransactionsOfSelling">,IQueryFetchPointTransactionsOfSellingArgs>(FETCH_POINT) return <>충전한 포인트는 {data?.fetchPointTransactionsOfSelling.amount}원</> }loading (Number(amount)에 이름 찾을 수 없다는 빨간 줄)import { gql, useQuery, useMutation } from "@apollo/client" import type { IQuery } from "../../../../src/commons/types/generated/types" import { loginCheck } from "../../../../src/components/commons/hocs/withAuth" import { useRouter } from "next/router" import type { ChangeEvent } from "react" import { useState } from "react" const FETCH_USER_LOGGED_IN = gql` query { fetchUserLoggedIn { email name } } ` const CREATE_POINT = gql` mutation createPointTransactionOfLoading($impUid:ID!){ createPointTransactionOfLoading(impUid:$impUid){ _id impUid amount } } ` declare const window: typeof globalThis & { IMP: any } function LoadingPage():JSX.Element { const router = useRouter() const { data } = useQuery<Pick<IQuery,"fetchUserLoggedIn">>(FETCH_USER_LOGGED_IN) const [ myFunction ] = useMutation(CREATE_POINT) const selectList = [0,500,1000,2000,5000]; const [Selected, setSelected] = useState(0); const handleSelect = (e:ChangeEvent<HTMLSelectElement>):void => {setSelected(Number(e.target.value));}; const onClickPayment = ():void => { if (Selected === 0) { alert("금액을 선택해주세요."); return; } const IMP = window.IMP; IMP.init("imp27255777"); IMP.request_pay({ // param pg: "kakaopay", pay_method: "card", // merchant_uid: "ORD20180131-0000011", name: `Section 50-${Selected}원 결제`, amount: Selected, buyer_email: data?.fetchUserLoggedIn.email, buyer_name: data?.fetchUserLoggedIn.name, buyer_tel: "", buyer_addr: "", buyer_postcode: "", m_redirect_url:"" }, async (rsp:any) => { if (rsp.success === true) { await myFunction({ variables:{ impUid : data?.fetchUserLoggedIn._id, amount: Number(amount) + Selected } }) const {Modal} = await import("antd") Modal.success({content:"등록 성공"}) void router.push("/z_quiz/section50/complete") } else { alert("결제 실패") } }); } return (<> <div>{data?.fetchUserLoggedIn.name}님 환영합니다.</div> <select onChange={handleSelect} value={Selected}> {selectList.map((item) => ( <option value={item} key={item}>{item}</option> ))} </select> <script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.min.js" /> <script src="https://cdn.iamport.kr/v1/iamport.js" /> <button onClick={onClickPayment}>충전하기</button> </>) } export default loginCheck(LoadingPage);loginimport { gql, useMutation } from "@apollo/client" import { type ChangeEvent, useState } from "react" import type { IMutation, IMutationLoginUserArgs } from "../../../../src/commons/types/generated/types" import { useRecoilState } from "recoil" import { accessTokenState } from "../../../../src/commons/stores" import { useRouter } from "next/router" import { wrapFormAsync } from "../../../../src/commons/libraries/asyncFunc" const LOGIN_USER =gql` mutation loginUser($email:String!, $password:String!){ loginUser(email:$email,password:$password){ accessToken } } ` export default function LoginPage():JSX.Element { const router = useRouter() const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [loginUser] = useMutation<Pick<IMutation,"loginUser">,IMutationLoginUserArgs>(LOGIN_USER) const [, setAccessToken] = useRecoilState(accessTokenState) const onChangeEmail = (event: ChangeEvent<HTMLInputElement>):void => { setEmail(event.currentTarget.value) } const onChangePassword = (event: ChangeEvent<HTMLInputElement>):void => { setPassword(event.currentTarget.value) } const onClickLogin = async ():Promise<void> => { try { const result = await loginUser({variables: { email, password }}) const accessToken = result.data?.loginUser.accessToken if (accessToken=== undefined) { alert("로그인 실패") return ;} setAccessToken(accessToken) localStorage.setItem("accessToken", accessToken) void router.push("/z_quiz/section50/loading") } catch(error) { if (error instanceof Error ) alert(error.message) } } return ( <form onSubmit={wrapFormAsync(onClickLogin)}> 이메일: <input type="text" onChange={onChangeEmail} /> 비밀번호: <input type="password" onChange={onChangePassword} /> <button>로그인</button> </form> ) }
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
[라이브러리 아이콘 실습] 강사님께는 보이지 않는 ts에러 빨간 줄이 보입니다.
MyIcon으로 이모션을 통해 만들어도, 그냥 Antd에서 복사붙여넣기해서 프레그먼트안에 넣어도 같은 오류가 발생해요.구글에 검색해도 해결방법이 나오지 않네요ㅠ
-
해결됨Next.js 시작하기(feat. 지도 서비스 개발)
<div id="__next"> 질문
제가 따로 하고 있는 next.js 프로젝트에는 이런 div가 없는데 혹시 없다면 문제가 있는건가요?
-
해결됨Next.js 시작하기(feat. 지도 서비스 개발)
강의파일 열면 왜 전부 다 빨간줄이 뜰까요???
강의 파일을 열면 에러가 뜨는데 어떻게 해결하나요? ㅠㅠ
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
toolkit을 사용 ssr설정 질문입니다
https://github.com/ZeroCho/react-nodebird/blob/master/toolkit/front/pages/index.js여기 코드를 가져와서 ssr을 설정했습니다front 코드 에러로 Error: Hydration failed because the initial UI does not match what was rendered on the server.Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.이렇게 두개가 나오는데 이걸 어떻게 해결할지 잘 모르겠습니다 initaial UI 에러라길레initialState: { user: { ...userInitialState, me: myInfo, }, post: { ...postInitialState, mainPosts: posts, hasMorePosts: posts.length === 10, }, },주석 처리 되어있는 이부분을 어떻게 해야되는거 같은데 잘 모르겠습니다
-
미해결
Next.js GCP App Engine 배포 시 환경변수 분기
Next.js로 Google Cloud Platform에 App Engine 서비스 배포를 진행하고 있습니다.문제는 production ( 실 서비스 )와 development ( 개발용 )으로 나누어서.env.development, .env.production의 두개의 환경변수를 가지고있습니다.배포 시 실서비스 에서는 .env.production을 사용하도록개발용 에서는 .env.development를 사용하도록 설정하려는데 이것저것 만져보아도 production만 사용하는 문제가 발생해버리네요. 현재 프로젝트구조와 설정코드는 이렇습니다.project ├── local └── Dockerfile └── docker-compose.yml ├── resource └── .next └── ... (Next.js 빌드 파일) └── node_modules └── package.json └── dev_app.yaml └── prd_app.yaml └── .env.development └── .env.production └── next.config.js └── ... (기타 Next.js 프로젝트 파일) 여기서 package.json의 script설정은 다음과 같습니다.{ dev: "next dev", start: "next start", lint: "next lint", deploy: "npm run build && gcloud app deploy --project='production' -q --appyaml=prd_app.yaml", deploy:dev: "npm run build:dev && gcloud app deploy --project='development' -q --appyaml=dev_app.yaml", build: "dotenv -e .env.production next build", build:dev: "dotenv -e .env.development next build" } next.config.js는 특별히 건드리지 않았습니다.dev_app.yaml, prd_app.yaml파일은 서비스명만 각각 설정해 주었습니다.runtime: nodejs20 # or another supported version service: development 질문 1.현재 app engine 업로드된 용량, 로직을 보니 빌드파일이 아닌 프로젝트 그대로 들어가는 것 같습니다.빌드는 환경변수파일도 정상적으로 분기되는데 앱엔진에서 해당문제가 발생하는 것으로보아혹시 Next.js에서 빌드된 파일로 app engine에 배포할 수 있는지 궁금합니다.질문 2.빌드파일만 올릴수 없다 라고 하더라도 프로젝트 그대로 올리면서 환경변수를 분기할 방법이 있는지 궁금합니다.정말 문서건 블로그건 구글서칭, 깃허브검색, GPT 모두 끈질기게 시도해봤지만능력부족 탓인지 성공하지 못했습니다..능력자분들께서 도움주시면 잊지않겠습니다!!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
중고마켓 이메일 찾기부분
중고마켓 피그마에서 로그인부분에 이메일 찾기가 있는데, 플레이그라운드에 없는 것 같아서 문의 드립니다. 비밀번호는 resetUserPassword를 사용하면 될 것은데, 이메일찾기는 제가보기엔 보이지 않아서요!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
useMutation에러
Server ErrorInvariant Violation: Argument of undefined passed to parser was not a valid GraphQL DocumentNode. You may need to use 'graphql-tag' or another method to convert your operation into a documentThis error happened while generating the page. Any console logs will be displayed in the terminal window. 이러한 에러가 뜨는데 왜 발생하는 걸까요.const [contents, setContents] = useState(""); 18 | > 19 | const [나의함수] = useMutation(나의그래프큐엘셋팅) | ^ 20 | 21 | const onClickSubmit = async () => { 22 | const result = await 나의함수({ import { useState } from "react" import {나의그래프큐엘셋팅} from './BoardWrite.queries' // export는 골라서 가져오기 import BoardWriterUI from "./BoardWrite.presenter"; // export-default로 한 개만 가져오기 import { useMutation } from "@apollo/client"; // import BoardWriterUI from "./BoardWrite.presenter"; // export-default로 한 개만 가져오기 // import BoardWriterUI, {apple} from "./BoardWrite.presenter"; // export-default와 export 함께 가져오기 // import * as S from './BoardWrite.styles' // 모든 export를 가져와줘 // S.BlueButton // S.RedInput 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 : { // variables 이게 $ 역활을 함 writer : writer, title : title, contents : contents } }) console.log(result) } const onChangeWriter = (event) => { setWriter(event.target.value) } const onChangeTitle = (event) => { setTitle(event.target.value) } const coChangeContents = (event) => { setContents(event.target.value) } return ( <BoardWriterUI aaa={onClickSubmit} bbb={onChangeWriter} ccc={onChangeTitle} ddd={coChangeContents}/> ) }-컨테이너import { gql } from "@apollo/client" const 나의그래프큐엘셋팅 = gql` mutation createBoard($writer : String, $title : String, $contents: String) { createBoard(writer : $writer, title : $title, contents : $contents) { _id number message } } ` -쿼리
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
섹션 27번은 문제가 저만 있는건가요?
라우팅을 넘어갈수가 없습니다Application error: a client-side exception has occurred (see the browser console for more information). 이런 오류가 뜨네요