묻고 답해요
140만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
영상 보고 응용 프로젝트 하는 중에 라우터 관련 질문이 있습니다.
안녕하세요 강사님! 이번학기에 갑자기 웹 개발을 하게 되어 부랴부랴 프론트 강의 챙겨보는중인데 정말 도움이 많이 돼 우선 감사의 말씀 먼저 드립니다. ㅜㅜ 다름이 아니라 제가 본 영상 강의를 보고 학교 과제를 수행하다가 (투두 리스트를 참고하여 만들었습니다. 참고로 과제는 이슈관리 시스템입니다.) 이러한 메인 화면을 구현하였는데, 각 프로젝트 이름을 누르면 그 프로젝트의 상세 페이지로 연결 시키고 싶은데, 라우터 기능을 사용하여 링크는 제대로 바뀌는데 화면 전환이 되지 않습니다. ㅜㅜ 코드를 여러번 봐도 무엇이 문제인지 감이 안 잡혀 질문 드리게 되었습니다. 코드 첨부 하겠습니다. ! import "./App.css"; import { Routes, Route, Link, useNavigate } from "react-router-dom"; import { useRef, useState } from "react"; import Header from "./components/Header"; import List from "./components/List"; import ProjectDetail from "./pages/ProjectDetail"; //임시데이터 const mokdata = [ { p_id: 0, p_name: "회원가입 프로젝트", date: new Date().getTime(), }, { p_id: 1, p_name: "온라인 테트리스 게임 프로젝트", date: new Date().getTime(), }, { p_id: 2, p_name: "윷놀이 프로젝트", date: new Date().getTime(), }, { p_id: 3, p_name: "온라인 채팅 앱 개발 프로젝트", date: new Date().getTime(), }, { p_id: 4, p_name: "회원 관리 시스템 프로젝트", date: new Date().getTime(), }, { p_id: 5, p_name: "이슈 관리 시스템 프로젝트", date: new Date().getTime(), }, ]; function App() { const [projects, setProjects] = useState(mokdata); const onDelete = (targetId) => { //배열에서 targetId와 일치하는 id를 갖는 요소만 삭제한 새로운 배열 setProjects(projects.filter((project) => project.p_id !== targetId)); }; return ( <> <div className="App"> <Header /> <List projects={projects} onDelete={onDelete} /> </div> <Routes> <Route path="/ProjectDetail:p_id" element={<ProjectDetail projects={projects} />} /> </Routes> </> ); } export default App; 위는 App.jsx 코드 이고 아래는 ProjectDetail 코드 입니다. !import { useParams } from "react-router-dom"; const ProjectDetail = ({ projects }) => { const { p_id } = useParams(); const project = projects.find((project) => project.p_id === parseInt(p_id)); return ( <div> <h1>프로젝트 상세내용</h1> <h2>{project.p_name}</h2> </div> ); }; export default ProjectDetail;
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
yarn 설치가 되지않습니다.
node.js와 npm은 --version을 이용하니 버전이 나오는데 yarn은 버전이 나오지 않아 npm install -g yarn 이라는 명령어를 하니 이미지처럼 에러가 나옵니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
섹션11 eslint 설치
eslint 설치 시 3개 중에 마지막 3번째를 선택하라고 하는데 저는 선택지가 2개만 나옴니다. 2번째를 선택해서 설치해도 되나요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
geolocation부분에 대해 질문있습니다.
geolocation부분에const askForLocation = function () { navigator.geolocation.getCurrentPosition((position) => { console.log(position); }); }; askForLocation();이렇게 함수가 있는데 여기서 궁금한점이 askForLocation(); 함수 호출부분에 인자로 전달하는 것이 없는데 매개변수로 position에 위치정보 객체형식으로 콘솔에 나오는 이유가 뭔지 궁금합니다.
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
3000번은 잘 들어가지는데 80번은 안됩니다.
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000까지 하고 3000번 포트로 잘 들어가지는데 3000번포트를 지우고 들어가봐도 뒤에 :80을 붙여 넣어 들어가봐도 사이트에 연결할 수 없음이 뜨네요 왜 그럴까요??
-
해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
CORS 에러 질문 있습니다.
안녕하세요. 프로젝트를 배포하는 과정에서 왜인지 모를 CORS 에러가 계속 생겨서 질문 드립니다.CORS 문제를 해결하기 위해서는 응답 헤더에 Acess-Control-Allow-Origin이 필요한데, nestjs와 같은 was에서 enableCors를 설정해주거나, Nginx의 server 블럭에 add_header를 통해서 헤더를 추가 해 줄 수 있는 것으로 알고 있습니다.웹 서버가 was보다 앞에 있으니까 웹 서버에서 설정해줘야겠다는 생각에 nginx.conf에 allowed_origin은 동적으로 Access-Control-Allow-Origin 헤더의 값을 받기 위해서 설정해뒀습니다.이렇게 작성하고 reload를 해줬는데, 왜인지 응답헤더에 추가한 헤더가 생기지 않습니다...테스트 서버에 위와 같은 설정으로 올렸을 때는 잘 해결됐는데 라이브에 올리니까 이런 문제가 발생하는데 어디를 살펴봐야 할 지 모르겠습니다... access to XMLHttpRequest at '도메인 주소' from origin '서버 ip' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.이런식으로 404에러가 나옵니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
함수, 변수의 호이스팅 부분 질문있습니다.
함수, 변수의 호이스팅 강의 영상 부분에if (storageData?.complete) { newLi.classList.add("complete"); }이 코드에서 storageData 뒤에 ? 이 물으표가 없으면 매개변수를 받아오지 않게 되니 undefined라고 강사님이 말씀하시는데 이게 무슨 말인지 잘 모르겠습니다. 그리고 ToDoList에서 리스트에 추가를 하고 더블클릭 삭제, 전체 삭제까지는 어느정도 이해가 되는데 로컬스트리지 전체 부분이 조금 이해도 어려운데 어떻게 이해를 하면서 공부를 하면 좋을까요?
-
미해결[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
객체 localStorage 부분 질문있습니다.
현재 객체 localStorage저장 부분의 인강을 보다 궁금한점 있어 질문을 드립니다.const saveItemsFn = function () { const saveItems = []; for (let i = 0; i < todoList.children.length; i++) { const todoObj = { contents: todoList.children[i].querySelector("span").textContent, complete: todoList.children[i].classList.contains("complete"), }; saveItems.push(todoObj); } localStorage.setItem("saved-items", JSON.stringify(saveItems)); };현재 자바스크립트 코드 제일 마지막 부분에 saveItemsFn함수가 저장하는 부분이니 이 함수안에 localStorage.setItem을 사용해서 로컬스토리지에 저장을 하는것까지는 이해가 되었는데 저장된걸 가져오기 위해 const savedTodoList = localStorage.getItem("saved-items");localStorage.getItem을 사용하는데 여기서 첫번째로 이 코드 위치가 다시 제일 위쪽에 작성이 되었는지 궁금하고 두번째로 이 코드가 saveItemsFn 함수 안에 작성이 되지 않은 이유는 getItem이 저장하는 코드가 아니기때문에 saveItemsFn안이 아닌 따로 다시 작성이 된것인가요?
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
14강 로그아웃 안됨
logout을 send하면 해당 오류가 발생합니다. 코드가 잘못된건지 궁금해 git 도 올려드립니다. 감사합니다. https://github.com/bukwon/boiler-plate
-
해결됨대용량 채팅 TPS 처리를 위한 웹소켓 통신 만들며 학습하기
채팅 메시지 DB로 저장 하기.
안녕하세요.강의 잘 들었습니다.마지막에 메시지를 저장 하는 얘기를 하셨는데.. 보통 메신저 서비스에서는 어떤 방식의 DB를 사용하는지궁금합니다. 흔히 Oracle이나 MariaDB 같은 방식의 관계형 DB를 사용하는게 흔한지 아니면 Mongo같은 비관계형 방식의 DB를 많이 사용하는지 혹시 답변이 가능하시다면 답변 부탁 드립니다. 그리고 그걸 선택한 이유가 무엇인지. 감사합니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
graphql codegen 설치
섹션 10에서 graphql codegen 설치하려는데요강의에서는 yarn add -D @graphql-codegen/cli을 설치하라고 하는데 지금 설치하려고 사이트에 들어가니yarn add --dev typescript @graphql-codegen/cli로 되어 있는데 같은 건가요?그냥 아래 명령어 실행해도 되나요?
-
해결됨대용랑 채팅 TPS에 대한 stateful 서비스 구축하기
1탄과 2탄 사이 변경된 코드 질문
안녕하세요! 지난 1탄 강의 잘 들었습니다.다름이 아니라 1탄과 2탄에서 go로 작성된 코드가 조금 다른거 같은데 혹시 누락된 강의가 있는걸까요 ?1탄에선 network 디렉토리에 network.go와 socket.go만 작성했었는데 2탄에선 server.go와 util.go가 생기면서 코드가 조금 변경된거 같습니다.누락된 강의가 없다면, 변경된 부분이 어떤 것들인지 알고싶어서 질문드립니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
섹션4 01-02-emotion 에러가 나는데 못찾겠습니다ㅜ
설치가 잘못된 걸까요.. yarn dev하니 오류가 납니다ㅜ
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
mongoDB 데이터 확인하는 법
강사님께서 mongoDB Clusters 카테고리 들어가면 데이터 확인하실 수 있는데, 저는 따로 뜨는게 없고 이런 화면이 나오네요. 어디서 볼 수 있나요?
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
postman 에러
안녕하세요. 현재 7강 듣고 있는데요, node.js run하고 postman에 이름, 이메일, 패스워드 넣어서 요청하면 에러 뜨고 종료가 됩니다... 이유가 뭔가요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
이번 final 과제 피드백 부탁드립니다!
안녕하세요! 강의 잘 듣고 있습니다!이번 과제 코드 피드백 부탁드립니다!고맙습니다.<화면><html><!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <title>SignUp</title> <link rel="stylesheet" href="./final.css"> <script defer src="./final.js"></script> </head> <body> <div class="wrapper"> <div class="wrapper__header"> <span id="header__title">코드캠프 회원가입</span> </div> <div class="wrapper__body"> <div class="wrapper__text"> <input type="text" id="email" placeholder="이메일을 입력해 주세요."> <span class="errorMsg email">이메일이 올바르지 않습니다.</span> <input type="text" id="name" placeholder="이름을 입력해 주세요."> <span class="errorMsg name">이름이 올바르지 않습니다.</span> <input type="text" id="pw1" placeholder="비밀번호를 입력해 주세요."> <span class="errorMsg pw1">비밀번호를 입력해주세요.</span> <input type="text" id="pw2" placeholder="비밀번호를 다시 입력해 주세요."> <span class="errorMsg pw2">비밀번호를 입력해주세요.</span> </div> <div class="wrapper__phone" oninput="phone()"> <input type="text" id="num1" maxlength="3"> - <input type="text" id="num2" maxlength="4"> - <input type="text" id="num3" maxlength="4"> </div> <div class="wrapper__certification"> <div class="cert__number"> <span id="certNum">000000</span> <button class="chkBtn" disabled="true">인증번호 전송</button> </div> <div class="cert__time"> <span id="certTimer">3:00</span> <button class="chkBtn" disabled="true">인증완료</button> </div> </div> <div class="wrapper__select"> <div class="select__locale"> <select id="locale"> <option selected disabled>지역을 선택하세요</option> <option value="서울">서울</option> <option value="경기">경기</option> <option value="인천">인천</option> </select> <span class="errorMsg locale">지역을 선택해주세요.</span> </div> <div class="select__gender"> <label for="woman"> <input type="radio" name="gender" id="woman"> 여성 </label> <label for="man"> <input type="radio" name="gender" id="man"> 남성 </label> </div> <span class="errorMsg gender">성별을 선택해주세요.</span> </div> </div> <div class="divideLine"></div> <div class="wrapper__check"> <!-- <button class="submit" disabled="true">가입하기</button> --> <button class="submit">가입하기</button> </div> </div> </body> </html> <css>*{ box-sizing: border-box; margin: 0; } html, body{ width: 540px; } .chkBtn{ width: 120px; height: 40px; border: 1px solid #D2D2D2; border-radius: 7px; font-size: 16px; font-weight: 400; color: #0068FF; background-color: #FFF; cursor: pointer; } .chkBtn.active { width: 120px; height: 40px; border: 1px solid #D2D2D2; border-radius: 7px; font-size: 16px; font-weight: 400; background-color: #0068FF; color: #FFF; cursor: pointer; } .errorMsg{ width: 100%; color: red; font-size: 10px; display: flex; flex-direction: column; align-items: center; visibility: hidden; } .wrapper{ width: 100%; height: 100%; padding: 60px 80px; border: 1px solid #AACDFF; border-radius: 20px; box-shadow: 7px 7px 39px rgba(0, 104, 255, .25); } .wrapper__header{ width: 100%; font-size: 32px; font-weight: 700; color: #0068FF; padding-bottom: 60px; } .wrapper__body{ width: 100%; } .wrapper__text > input{ width: 100%; height: 60px; margin-top: 20px; font-size: 16px; font-weight: 400; border: 1px solid #D2D2D2; border-radius: 7px; padding: 18px; } .wrapper__phone{ width: 100%; display: flex; justify-content: space-between; align-items: center; padding: 20px 0; } .wrapper__phone > input{ width: 100px; height: 40px; border: 1px solid #D2D2D2; border-radius: 7px; } .wrapper__certification { width: 100%; display: flex; flex-direction: column; align-items: flex-end; justify-content: space-between; } #certNum, #certTimer{ color: #0068FF; font-size: 18px; padding-right: 20px; } .cert__time{ padding: 20px 0; } .wrapper__select{ width: 100%; display: flex; flex-direction: column; align-items: center; } .select__locale{ width: 100%; display: flex; flex-direction: column; justify-content: center; } #locale{ width: 100%; height: 60px; border: 1px solid #D2D2D2; border-radius: 7px; color: #797979; font-size: 16px; font-weight: 400; padding: 18px; } .select__gender{ width: 140px; display: flex; justify-content: space-between; padding-top: 30px; } .divideLine{ width: 100%; border: 1px solid #E6E6E6; margin: 20px 0; } .wrapper__check{ width: 100%; display: flex; justify-content: center; } .submit { width: 100%; height: 60px; font-size: 18px; font-weight: 400; color: #0068FF; background-color: #FFF; border: 1px solid #0068FF; border-radius: 7px; } <js>const submit = document.querySelector('.submit'); // 가입하기 const numberChk = document.querySelector('.cert__number .chkBtn'); // 인증번호 전송 const timeChk = document.querySelector('.cert__time .chkBtn'); // 인증완료 let time = 180; // 180초, 인증 시간 let isStarted = false; // email const emailChk = () => { let email = document.getElementById('email').value; if(email.includes('@') === true){ let isEmail = email.split('@')[1].includes('.'); if(isEmail === false){ document.querySelector('.errorMsg.email').style.visibility = 'visible'; document.querySelector('.errorMsg.email').value = ''; return false; } else { document.querySelector('.errorMsg.email').style.visibility = 'hidden'; return true; } } else { document.querySelector('.errorMsg.email').style.visibility = 'visible'; document.getElementById('email').value = ''; return false; } } // name const nameChk = () => { let name = document.getElementById('name').value; if(name.length === 0){ document.querySelector('.errorMsg.name').style.visibility = 'visible'; return false; } else { document.querySelector('.errorMsg.name').style.visibility = 'hidden'; return true; } } // pw const pwChk = () => { let pw1 = document.getElementById('pw1').value; let pw2 = document.getElementById('pw2').value; if(pw1 && pw2){ if(pw1 === pw2){ document.querySelector('.errorMsg.pw1').style.visibility = 'hidden'; document.querySelector('.errorMsg.pw2').style.visibility = 'hidden'; return true; } else { document.querySelector('.errorMsg.pw1').style.visibility = 'visible'; document.querySelector('.errorMsg.pw2').style.visibility = 'visible'; document.querySelector('.errorMsg.pw1').innerHTML = '비밀번호가 일치하지 않습니다.' document.querySelector('.errorMsg.pw2').innerHTML = '비밀번호가 일치하지 않습니다.' return false; } } else { document.querySelector('.errorMsg.pw1').style.visibility = 'visible'; document.querySelector('.errorMsg.pw2').style.visibility = 'visible'; return false; } } // phone const phone = () => { let num1 = document.getElementById('num1').value; let num2 = document.getElementById('num2').value; let num3 = document.getElementById('num3').value; if(num1.length === 3) { document.getElementById('num2').focus(); if(num2.length === 4) { document.getElementById('num3').focus(); } } if(num1.length === 3 && num2.length === 4 && num3.length === 4){ numberChk.classList.add('active'); certification(); } } const certification = () => { // 인증번호 numberChk.disabled = false; numberChk.addEventListener('click', e => { let randomNumber = String(Math.trunc(Math.random() * 1000000)).padStart(6, '0') document.getElementById('certNum').innerText = randomNumber; // 타이머 if(isStarted === false){ isStarted = true; timeChk.disabled = false; let timer = setInterval(() => { if(time >= 0){ let min = Math.trunc(time / 60); let sec = String(time % 60).padStart(2,'0'); document.getElementById('certTimer').innerText = `${min}:${sec}`; time--; } else { clearTime(timer); } }, 100) timeChk.addEventListener('click', e => { if(time >= 0){ alert('인증이 완료 되었습니다.'); clearTime(timer); submit.disabled = false; } }) } }) } const clearTime = (timer) => { timeChk.classList.remove('active'); numberChk.classList.remove('active'); document.getElementById('certNum').innerText = '000000'; document.getElementById('certTimer').innerText = '0:00'; timeChk.disabled = true; numberChk.disabled = true; isStarted = false; clearInterval(timer); } const checkValidation = () => { emailChk(); nameChk(); pwChk(); if(emailChk() && nameChk() && pwChk()) { return true; } else { return false; } } // 검증 submit.addEventListener('click', e => { checkValidation(); if(checkValidation()){ alert('코드캠프 가입을 축하합니다.'); } });
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
함수에 대해 질문있습니다.
자바스크립트 함수가 조금 어려운데 함수는 그냥 관련된 코드들을 작성할 때 사용하나요? 예를 들어 input으로 어떠한걸 한다면 input 함수를 만들어서 이 함수안에는 input과 관련된 코드들을 작성한다고 보면되는건가요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
app.js 에서 sequelize 를 가져오는 부분이 models/index.js 있는 sequelize 를 가르키는게 맞나요?
[제로초 강좌 질문 필독 사항입니다]세션 6번app.js 시퀄라이즈 싱크에 관한 문의 입니다.const { sequelize } = require('./models');app.js 에서 시퀄라이즈를 가져오는데 해당 모둘안에는 3개의 파일 있습니다 .( user, comment, index ) index 파일만 실행하면 될거 같은데 sequelize 자져오는 이유가 궁금하고 , 여기서 가르키는 sequelize 가 index에 있는 sequelize 인지 궁금합니다.
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
css 관련 질문드립니다.
안녕하세요 선생님!너무나 좋은 강의 잘 듣고 있습니다.17:28 에서 .EmotionItem 을 가운데 정렬할 때 text-align: center 를 사용하셨는데요.display: flex 와 text-align: center 중 어떤 것을 사용할지에 대한 기준이 있으실까요?리액트 강의라 크게 중요한 부분은 아니지만 수업 중 flex 를 사용하신 경우가 더 많았던 것 같아 질문을 드려봅니다! 🥺
-
미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
태그 옵션 { } 사용
🚨 아래의 가이드라인을 꼭 읽고 질문을 올려주시기 바랍니다 🚨질문 하시기 전에 꼭 확인해주세요- 질문 전 구글에 먼저 검색해보세요 (답변을 기다리는 시간을 아낄 수 있습니다)- 코드에 오타가 없는지 면밀히 체크해보세요 (Date와 Data를 많이 헷갈리십니다)- 이전에 올린 질문에 달린 답변들에 꼭 반응해주세요 (질문에 대한 답변만 받으시고 쌩 가시면 속상해요 😢)질문 하실때 꼭 확인하세요- 제목만 보고도 무슨 문제가 있는지 대충 알 수 있도록 자세한 제목을 정해주세요 (단순 단어 X)- 질문의 배경정보를 제공해주세요 (이 문제가 언제 어떻게 발생했고 어디까지 시도해보셨는지)- 문제를 재현하도록 코드샌드박스나 깃허브 링크로 전달해주세요 (프로젝트 코드에서 문제가 발생할 경우)- 답변이 달렸다면 꼭 확인하고 반응을 남겨주세요- 강의의 몇 분 몇 초 관련 질문인지 알려주세요!- 서로 예의를 지키며 존중하는 문화를 만들어가요. - 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요! DiaryList.jsx 파일에서 option이나 Button 태그의 옵션에 보면 value={"latest"}나 type={"POSITIVE"} 이런 식으로 { } 를 사용하셨던데 없이 해도 출력이 잘 되는데 꼭 써줘야 하는지 궁금합니다.