묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
백엔드 질문
1.사용자가 웹에 접속을 할 때, 브라우저 -> 프론트서버 로 요청을 보내게 되고프론트 -> 브라우저 로 html css js 파일을 보내서 뷰를 표시하게 되는데그러면 특정 기능을 사용할 때, 예를 들어 로그인 버튼을 누른다고 하면그 요청은 브라우저 -> 백엔드 인가요 프론트 -> 백엔드 인가요?만약 브라우저 -> 백엔드 이면백엔드 cors 설정에서는 프론트서버 도메인만 허용하도록 해놓는데 어떻게 브라우저에서백엔드로 접근이 가능한건가요? 2.강좌에서는 me값으로 로그인 유지를 위한 로직을 작성했고모든 페이지 접속 때마다 백엔드로 요청을 보내서 세션인증을 하는방식으로 로직을 작성했는데제가 알기로 세션인증방식은 세션id를 프론트에 보내서 쿠키에 있는 세션id를 이용해 로그인 유지를 하는것으로 알고있습니다. 제가 알고 있는 방식과 강좌에서의 세션인증이 좀 다른것 같은데 어떻게 이해해야 하나요?강좌는 ssr 적용 전 백엔드 부분까지만 들은 상태입니다.
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
개인 블로그 정리
안녕하세요 선생님혹시 강의를 듣고 정리한 내용을 개인 블로그에 게시해도 될까요??
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
8:24분경 코드 오류나서 수정하셨는데!
8분 20초경 오류나서 코드를 수정하셨는데,case ADD_POST_TO_ME: return { ...state, me: { ...state.me, // 이부분 왜 추가한건가요? Posts: [{ id: action.data }, ...state.me.Posts], }, };코드 주석부분 왜 추가하신건가요..?const dummyUser = (data) => ({ ...data, nickname: "wewewe", id: 1, Posts: [{ id: 1 }], Followings: [{ nickname: "we1" }, { nickname: "we2" }, { nickname: "we3" }], Followers: [{ nickname: "we1" }, { nickname: "we2" }, { nickname: "we3" }], });dummy데이터 구조를 보면Posts를 제외한 nickname, id, Followings 등 변하지 않는 데이터들의 불변성을 유지하기 위해서 추가한것이 맞는건가요?!
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
우분투에서 작업시 윈도우로 mysql 설치하는 것에 관해서
제로초쌤 제가 우분투에서 Nodebird를 진행하고 있는데 더북에 써져있는 거처럼 리눅스(우분투)에서 설치하는 방법 그대로 설치하다가 Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (13) 소켓 에러가 계속 나서 해결하려고 인터넷에 찾아보면서 따라하고 있는데 해결이 안되서 혹시 윈도우로 mysql설치해서 진행해도 크게 차이가 없을까요?
-
미해결프로젝트로 배우는 React.js
편집
72번째 강의 초반부 편집오류 있습니다.
-
미해결프로젝트로 배우는 React.js
비동기문제
강의에서는 toast가 비동기적으로 실행되는것을 해결하기 위해 useRef를 활용했는데 혹시 async나 promise로도 해결이 가능한건가요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
DB 연결 성공 후 테이블 까지 만들었습니다.
그런데 테이블을 선택해서 코드를 보려면 자꾸 workbench가 팅겨서 꺼집니다 ㅠㅠ코드를 깃허브에 있는 class형 함수를 긁어서 사용해서 문제가 되는걸까요..?ㅠㅠ 아래는 오류창입니다..
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
사가 모든 설정 후 로그인시 오류
강사님 모든 코드를 수정한 후 로그인하려고 하는데아이디, 비밀번호 입력 후 누르면 로그인이 되지 않습니다.콘솔창에 에러도 나타나지 않아서 어디가 틀렸는지 모르겠네요.몇개파일의 코드 같이 올려드립니다.아래는 로그인 안되는 화면캡처본입니다.LoginForm.jsimport React, { useCallback, useMemo } from "react"; import Link from "next/link"; import { Form, Input, Button } from "antd"; import styled from "styled-components"; import useInput from "../hooks/useInput"; import { useDispatch, useSelector } from "react-redux"; import { loginRequestAction } from "../reducers/user"; const FormWrapper = styled(Form)` padding: 15px; `; const LoginForm = () => { const dispatch = useDispatch(); const { isLoggingIn } = useSelector((state) => state.user); const [id, onChangeId] = useInput(""); const [password, onChangePassword] = useInput(""); const style = useMemo(() => ({ marginTop: 10 }), []); const onSubmitForm = useCallback(() => { console.log(id, password); dispatch(loginRequestAction({ id, password })); }, [id, password]); return ( <FormWrapper onFinish={onSubmitForm}> <div> <label htmlFor="user-id">아이디</label> <Input name="user-id" value={id} onChange={onChangeId} required></Input> </div> <div> <label htmlFor="user-password">비밀번호</label> <Input name="user-password" value={password} onChange={onChangePassword} required ></Input> </div> <div style={style}> <Button type="primary" htmlType="submit" loading={isLoggingIn}> 로그인 </Button> <Link href="/signup"> <a>회원가입</a> </Link> </div> </FormWrapper> ); }; export default LoginForm; reducers-user.jsexport const initailState = { isLoggingIn: false, // 로그인 시도중 - 로딩창을 띄우기위해 isLoggedIn: false, isLoggingOut: false, // 로그아웃 시도중 me: null, signUpDate: {}, loginData: {}, }; // 로그인 액션 create export const loginRequestAction = (data) => { return { type: "LOG_IN", data, }; }; export const logoutRequestAction = () => { return { type: "LOG_OUT", }; }; const reducer = (state = initailState, action) => { switch (action.type) { case "LOG_IN_REQUEST": console.log("reducers login"); return { ...state, isLoggingIn: true, }; case "LOG_IN_SUCCESS": return { ...state, isLoggingIn: false, isLoggedIn: true, me: { ...action.data, nickname: "가나다" }, }; case "LOG_IN_FAILURE": return { ...state, isLoggingIn: false, isLoggedIn: false, }; case "LOG_OUT_REQUEST": return { ...state, isLoggingOut: true, }; case "LOG_OUT_SUCCESS": return { ...state, isLoggingOut: false, isLoggedIn: false, me: null, }; case "LOG_OUT_FAILURE": return { ...state, isLoggingOut: false, }; default: return state; } }; export default reducer; sagas-user.jsimport { all, fork, delay, put, takeLatest } from "redux-saga/effects"; import axios from "axios"; function loginAPI(data) { return axios.post("/api/login", data); // 서버에 요청 } function* login(action) { try { console.log("saga login"); yield delay(1000); // 비동기 요청 대신수행 // const result = yield call(loginAPI, action.data); yield put({ type: "LOG_IN_SUCCESS", data: action.data, }); } catch (err) { yield put({ type: "LOG_IN_FAILURE", data: err.response.data, }); } } function logoutAPI() { return axios.post("/api/logout"); // 서버에 요청 } function* logout() { try { yield delay(1000); // const result = yield call(logoutAPI); yield put({ type: "LOG_OUT_SUCCESS", }); } catch (err) { yield put({ type: "LOG_OUT_FAILURE", data: err.response.data, }); } } function* watchLogIn() { yield takeLatest("LOG_IN_REQUEST", login); } function* watchLogOut() { yield takeLatest("LOG_OUT_REQUEST", logout); } export default function* userSaga() { yield all([fork(watchLogIn), fork(watchLogOut)]); } configureStore.jsimport { applyMiddleware, createStore, compose } from "redux"; import createSagaMiddleware from "redux-saga"; import { createWrapper } from "next-redux-wrapper"; import { composeWithDevTools } from "redux-devtools-extension"; import reducer from "../reducers"; import rootSaga from "../sagas/index"; const configureStore = () => { const sagaMiddleware = createSagaMiddleware(); const middlewares = [sagaMiddleware]; const enhancer = process.env.NODE_ENV === "production" ? compose(applyMiddleware(...middlewares)) : composeWithDevTools(applyMiddleware(...middlewares)); const store = createStore(reducer, enhancer); store.sagaTask = sagaMiddleware.run(rootSaga); return store; }; const wrapper = createWrapper(configureStore, { debug: process.env.NODE_ENV === "development", }); export default wrapper;
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
동영상이 흐릿하게 나옵니다
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 넷플릭스 실습을 하면서 iframe을 사용해 유튜브에서 동영상이 나오게 하는거 까지는 완료가 되었습니다.그런데 재생버튼을 누르고 영상이 시작되면 그림처럼 흐릿하게 나오는데 왜 그런걸까요?
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
16분경 onChangeText에 useInput을 사용해도 되지 않나요?
[text, setText]와 onChangeText를 만들어놓은 훅 useInput을 사용해서 코딩해도 되지 않나요? 그렇게 하지 않은 이유가 긍금합니다!
-
미해결(2024 최신 업데이트)리액트 : 프론트엔드 개발자로 가는 마지막 단계
openweather api 호출 했는데 401가 나요!
const getCurrentLocation = () => { navigator.geolocation.getCurrentPosition((position)=>{ console.log('위치', position.coords.latitude, position.coords.longitude); // 위치 37.4838677 126.902839 getWeatherByCurrentLocation(position.coords.latitude, position.coords.longitude); }); } const getWeatherByCurrentLocation = async(latitude, longitude) => { let apiKey = '0619cf6a981bec8d01375e5576139e86'; let apiUrl = `https://api.openweathermap.org/data/3.0/onecall?lat=${latitude}&lon=${longitude}&appid=${apiKey}`; let response = await fetch(apiUrl); let data = await response.json(); console.log('data', data); } useEffect(()=>{getCurrentLocation()}, []);이렇게 작성해서 돌려보니이런식으로 401에러가 납니다....원인을 잘 모르겠어요!ㅠㅠ
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
post 로 id, password 전송시 => 크롬 개발자 도구, 네트워크, Request 에 보면 id, password 가 그대로 노출되는데 숨길순 없나요?
post 로 id, password 전송시 => 크롬 개발자 도구, 네트워크, Request 에 보면 id, password 가 그대로 노출되는데 숨길순 없나요?브라우저를 사용하는 유저가 보낸 거기 때문에 보안을 안해도 상관없을까요?
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
getByTestId
tdd 앱 개발 초입 강의에서 질문 있습니다.App.test.js에서는 screen.getByTestId("counter")를 했고, App.js 에서는 <h3> 내부에 data-testid="counter" 라고 되어 있는데요.어떻게 App.js 내부의 <h3> 태그의 data-testid가 getByTestId로 불릴 수 있는지 궁금합니다..!그리고 넘어간 정보가 왜 0이 아니라 TextContent가 맞는걸까요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
useSelector 두번(중복)실행해도 괜찮은가요?
const id = useSelector((state) => state.user.user?.id); const { addCommentDone } = useSelector( (state) => state.post );위에 코드처럼 state 단계에서 갈리게되면 2번 실행하게되는데 성능엔 문제 없나요?
-
미해결프로젝트로 배우는 React.js
useParams
useParams hook을 사용할때 import를 react-router 에서 하시는데 react-router-dom에서 하든 react-router에서 하든 별 상관 없는건가요?강의에서는 react-router-dom을 사용하고 있는걸로 있는데 react-router와의 차이와 import할 때 이 둘을 구분하지 않아도 되는지 궁금합니다.
-
해결됨따라하며 배우는 리액트 A-Z[19버전 반영]
에러 질문드립니다
next13 학습을 진행하고 있는데 오류가 발생해서 질문드립니다.기본적으로이 상태에서는이런 오류가 발생하고<Link>를 사용을 하게 되면이런 오류가 발생합니다..어떻게 해야하나요?
-
미해결프로젝트로 배우는 React.js
새로고침을 해야하는 기준
안녕하세요 코지코더님 강의 수강중인 수강생입니다.가끔 보면 새로고침을 하지 않아도 local 에 바로 업데이트가 되는게 있고 이번 강의처럼 새로고침을 한번 누르시는게 있는데 그 기준이 있을까요?
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
에러 문의 react hook useEffect
src/components/Row.js Line 14:7: React Hook useEffect has a missing dependency: 'fetchMovieData'. Either include it or remove the dependency array react-hooks/exhaustive-deps쌤 그리고 fetchMovieData 가 있습니다. 그것을 포함하거나 종속성 배열 React-hooks/exhausitve deps를 제거하라는게 무슨말인가요??
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]
3일동안 삽질하다 결국 여기로 왔습니다. 꼭좀 상세히 알려주세요.
todoapp 클라이언트(리액트), 서버(몽구스) 로 작업중입니다. (글읽기, 리스트보여주기, 삭제 까지는 구현을 했는대요. 글리스트에서 특정리스트를 클릭시 해당상세페이지로 넘어가는 방법이 잘안됩니다. 구체적으로 어떻게 해야되는지 꼭좀 알려주세요. -----------리액트-------------------------- import React, { useEffect } from 'react' import axios from 'axios' import { useParams } from 'react-router-dom' const ShowPage = () => { const {id} = useParams() const getPost = (id) => { axios.get(`users/board/${id}`).then((res)=>{ console.log(res.data.user); }) } useEffect(()=>{ getPost(id); },[]) return ( <div>ShowPage</div> ) } -----------server-------------------------- userRouter.get('/board/:userId',async(req,res)=>{ try{ const {userId} = req.params; const user = await User.findOne({id:userId}); return res.status(200).json({success:true, user}) }catch(err){ console.log(err); return res.status(500).send({err: err.message}) } })
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
useInput 했을때, 배열의 첫번째 요소가 func으로 나와요
id와 nickname에 마우스를 올리면 useState를 이용한 password(string), passwordCheck(boolean)과 다르게, 함수라고 나오는데 이렇게 되어도 괜찮은건가요?? 그리고 이것과 관련된 오류인지는 모르겠는데, 약관동의 버튼을 누르고 아이디와 비밀번호를 수정해도 값이 변경되지않습니다. 강의랑 똑같이 작성한것같은데 어디가 잘못된건지 모르겠네요 ㅠㅠ.. 어떻게 해결해야 할까요?? ```signup.jsimport React, { useCallback, useState } from 'react'; import AppLayout from '../components/AppLayout'; import Head from 'next/head'; import styled from 'styled-components'; import { Button, Checkbox, Form, Input } from 'antd'; import useInput from '../components/hooks/useInput'; const ErrorMessage = styled.div` color: red; `; const Signup = () => { const [id, onChangeId] = useInput(''); const [nickname, onChangeNickname] = useInput(''); const [password, onChangePassword] = useInput(''); const [passwordCheck, setPasswordCheck] = useState(''); const [passwordError, setPasswordError] = useState(false); const onChangePasswordCheck = useCallback( (e) => { setPasswordCheck(e.target.value); setPasswordError(e.target.value !== password); }, [password] ); console.log(id); const [term, setTerm] = useState(false); const [termError, setTermError] = useState(false); const onChangeTerm = useCallback((e) => { setTerm(e.target.checked); setTermError(false); }, []); const onSubmit = useCallback(() => { if (password !== passwordCheck) { return setPasswordError(true); } if (!term) { return setTermError(true); } console.log(id, nickname, password); }, [password, passwordCheck, term]); return ( <> <AppLayout> <Head> <title>회원가입 | NodeBird</title> </Head> <Form onFinish={onSubmit}> <div> <label htmlFor="user-id">아이디</label> <br /> <Input name="user-id" value={id} required onChange={onChangeId} /> </div> <div> <label htmlFor="user-nick">닉네임</label> <br /> <Input name="user-nick" value={nickname} required onChange={onChangeNickname} /> </div> <div> <label htmlFor="user-password">패스워드</label> <br /> <Input name="user-password" value={password} required onChange={onChangePassword} /> </div> <div> <label htmlFor="user-password-check">비밀번호체크</label> <br /> <Input name="user-password-check" value={passwordCheck} required onChange={onChangePasswordCheck} /> {passwordError && ( <ErrorMessage>비밀번호가 일치하지 않습니다</ErrorMessage> )} </div> <div> <Checkbox name="user-term" checked={term} onChange={onChangeTerm}> 약관에 동의합니다. </Checkbox> {termError && <ErrorMessage>약관에 동의하지 않습니다</ErrorMessage>} </div> <div style={{ marginTop: '10px' }}> <Button type="primary" htmlType="submit"> 가입하기 </Button> </div> </Form> </AppLayout> </> ); }; export default Signup;import { useState, useCallback } from 'react'; export default (initialValue = null) => { const [value, setValue] = useState(initialValue); const handler = useCallback((e) => { setValue(e.target.value); }, []); return [value, handler]; };