묻고 답해요
130만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
@types/cors설치
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 22:03 초 부분 에 cors 설치하시는데 요거는 안하셨는데 해야되는거 맞나요??저는 안하니까 오류나서 설치하라고 뜨더라구요..영상에서는 설치안했는데도 오류 안뜨는 거같아서..아님 제가 잘 못본걸 수도 있어서 알려주시면 감사드립니다!
-
미해결따라하며 배우는 리액트 A-Z
압축파일 말고, git이나 코드 복사할 수 있는 링크는 없나요?
생각보다 파일의 용량이 커서 압축이 안 풀립니다..ㅎㅎ복사해도 되는 부분들은 복사해서 쓰고 싶은데 있으면 공유 부탁드릴게요
-
해결됨따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
노드 아예 모르는 상태로 들어도 괜찮을까요?
리액트는 어느정도 프로젝트도 해보고 웬만한건 구현이 가능한 정도인데 노드에 관해서 전혀 모르는데 수강해도 괜찮을까요?혹시 노드 지식이 필요하다면 어떤 강의를 듣고 와서 수강을 해야할까요?
-
해결됨[리뉴얼] 타입스크립트 올인원 : Part1. 기본 문법편
선생님 제네릭에 관해서 질문 사항이 있습니다.
문자열 또는 숫자를 인자로 받아서 문자열 인자인 경우는 문자열 결합을 숫자 인자인 경우에는 숫자 덧셈을 구현하는 함수를 구현하려고 했습니다. 그런데 아래와 같은 에러가 뜨는데 제 짧은 지식으로는 도대체 이해가 안되서 질문을 남깁니다. 또한, 제네릭 타입의 변수는 type guard를 해줄 방법이 없는건가요?n1과 n2의 타입은 T & 'string' 또는 T & 'number'으로 추론합니다.
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
회원 가입 페이지 기능 생성(3) Error: DataSource is not set for this entity.
client 쪽에서는 에러가 안나지만server 쪽에서 데이터는 잘 받지만Error: DataSource is not set for this entity.나네요.백엔드쪽은 익숙하지가 않아 구글링을 해봐도 어디서 에러가 나는지 잘 모르겠습니다. 게시판에 유사한 글이 있긴 하지만 해결책을 안되어 문의 드려요.AppDataSource는 이렇게 되어있습니다. 제 깃 주소는 https://github.com/ssinking91/Reddit입니다. 이 버그 너무 해결하고 싶습니다.감사합니다. 임시방편으로 모든 entity를 불러와 AppDataSource의 entities경로로 넣어 줬습니다.혹시 에러나시는 분들 임시방편으로 이렇게 해주시면 잘 됩니다.import "reflect-metadata"; import { DataSource } from "typeorm"; import User from "./entities/User"; import Post from "./entities/Post"; import Sub from "./entities/Sub"; import Comment from "./entities/Comment"; import Vote from "./entities/Vote"; export const AppDataSource = new DataSource({ type: "postgres", host: "localhost", port: 5432, username: "postgres", password: "password", database: "postgres", synchronize: true, logging: false, // entities: ["src/entities/**/*.ts"], entities: [User, Post, Sub, Comment, Vote], migrations: [], subscribers: [], });
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
로그아웃 후에도 계속 쿠키가 존재합니다.
안녕하세요! 로그아웃 후 계속 auth/me후 계속 req에서 쿠키가 존재해서 문의 남깁니다! application탭에서 쿠키는 잘 삭제가 되고 네트워크 탭에서도 logout이 성공적으로 이루어지는데 reload하면 바로 auth/me가 계속 200코드와 함께 user가 전달됩니다. 콘솔에도 찍어봤는데 계속 req에 쿠키가 같이 전달되고 있어서 요. 서버도 껐다 켜보고 했는데도 계속 그래서 문의드립니다!client/src/context/auth.tsxclient/src/components/NavBar.tsxserver/src/middlewares/auth.tsserver/src/routes/auth.ts
-
미해결따라하며 배우는 리액트 A-Z
개인 블로그 정리
안녕하세요 선생님혹시 강의를 듣고 정리한 내용을 개인 블로그에 게시해도 될까요??
-
해결됨Slack 클론 코딩[실시간 채팅 with React]
안녕하세요.
안녕하세요. 질문 있습니다.강의에서는 SWR을 쓰시는데 공부할때는 react-query를 쓰려고 합니다. 이유는 생태계가 더 큰 라이브러리를 사용할 목적이었는데 알려주신 npm trends에 검색해보니 둘 다 비슷비슷하더라고요.SWR도 아직 많이 쓰이는 추세인가요??? 궁금한 이유는 react-query 외에도 추가로 하나의 라이브러리를 동시에 더 써볼 생각이라 추천해주시면 감사합니다. 추가로 수업 외 질문으로 유틸리티 라이브러리?를 하나 써보려고 합니다. 기존에는 fxjs를 사용 중이었습니다. npm trends를 보니 가장 많이 사용하는 라이브러리는 lodash, rxjs인 것 같고 lamda도 많이 쓰는거 같고 타입스크립트로 된 fp-ts도 있는거 같은데 fp-ts를 제외한 것들 중 추천해주시는게 있을까요? 감사합니다!!
-
미해결타입스크립트 입문 - 기초부터 실전까지
age도 같이 속성에 뜹니다 ㅠㅠ
위처럼 저는 age가 같이 뜨는데... 뭔가 잘못한걸까요?
-
미해결React 기반 Gatsby로 기술 블로그 개발하기
타입스크립트를 설정할 때 jsxPragma 옵션을 뺀 이유는 무엇인가요?
gatsby-plugin-typescript 공식 문서를 보면 jsxPragma 옵션이 들어가던데 여기선 뺀 이유가 궁금해요!추가로 혹시 이 jsxPragma가 어떤 역할을 하는지 알 수 있을까요? 검색해도 잘 이해가 안되서요!
-
미해결Slack 클론 코딩[실시간 채팅 with React]
Cannot read properties of undefined (reading 'map')
제로초님, 코드를 따라친 후에 로그아웃을 하고 다시 로그인 하면 이런 에러메세지가 뜹니다.그런데 네트워크 탭을 보면 로그인이 정상적으로 된거 같아서 새로고침을 하면 에러 메세지가 사라지고 슬랙에서 로그인된 화면이 제대로 뜹니다.근데 또 여기서 워크스페이스를 생성하려고 하면 콘솔에 axioserror메세지가 떠서 어떻게 해야될지 모르겠습니다..Workspace/index.tsximport axios from "axios"; import React, { FC, useCallback, useState } from "react"; import useSWR from 'swr'; import fetcher from "@utils/fetcher"; import { Navigate, Routes, Route } from "react-router-dom"; import { AddButton, Channels, Chats, Header, LogOutButton, MenuScroll, ProfileImg, ProfileModal, RightMenu, WorkspaceButton, WorkspaceName, Workspaces, WorkspaceWrapper } from "@layouts/Workspace/style"; import gravatar from 'gravatar'; import loadable from '@loadable/component'; import Menu from "../../components/Menu"; import Modal from "../../components/Modal"; import { Link } from "react-router-dom"; import { IUser } from "@typings/db"; import { Button, Input, Label } from "@pages/SignUp/styles"; import useInput from "@hooks/useInput"; import {toast} from 'react-toastify'; const Channel = loadable(() => import('@pages/Channel')); const DirectMessage = loadable(() => import('@pages/DirectMessage')); const Workspace: FC<React.PropsWithChildren<{}>> = ({children}) => { const [showUserMenu, setShowUserMenu] = useState(false); const [showCreateWorkspaceModal, setShowCreateWorkspaceModal] = useState(false); const [newWorkspace, onChangeNewWorkspace, setNewWorkspace] = useInput(''); const [newUrl, onChangeNewUrl, setNewUrl] = useInput(''); // revalidate = 서버로 요청 다시 보내서 데이터를 다시 가져옴 // mutate = 서버에 요청 안보내고 데이터를 수정 const {data: userData, error, mutate} = useSWR<IUser | false>('/api/users', fetcher, { dedupingInterval: 2000, }); const onLogout = useCallback(() => { axios.post('/api/users/logout', null , { withCredentials: true, }) .then(() => { mutate(false, false); }) }, []); const onClickUserProfile = useCallback((e: any) => { e.stopPropagation(); setShowUserMenu((prev) => !prev); }, []) const onClickCreateWorkspace = useCallback(() => { setShowCreateWorkspaceModal(true); }, []) const onCreateWorkspace = useCallback((e: any) => { e.preventDefault(); // 띄어쓰기도 검사해줘야됨 if(!newWorkspace || !newWorkspace.trim()) return; if(!newUrl || !newUrl.trim()) return; axios.post('http://localhost:3095/api/workspaces', { workspace: newWorkspace, url: newUrl, }, { withCredentials: true, }) .then(() => { mutate(); setShowCreateWorkspaceModal(false); setNewWorkspace(''); setNewUrl(''); }) .catch((error) => { console.dir(error); // 에러가 나면 사용자가 인지하게 해줌 toast.error(error.response?.data, { position: 'bottom-center' }) }) }, [newWorkspace, newUrl]) const onCloseModal = useCallback(() => { setShowCreateWorkspaceModal(false); }, []) if(!userData) { return <Navigate to="/login" /> } if(!userData) return null; return( <div> <Header> <RightMenu> <span onClick={onClickUserProfile}> <ProfileImg src={gravatar.url(userData.email, { s: '28px', d: 'retro' })} alt={userData.nickname} /> {showUserMenu && <Menu style={{ right: 0, top: 38 }} show={showUserMenu} onCloseModal={onClickUserProfile}> <ProfileModal> <img src={gravatar.url(userData.nickname, { s: '36px', d: 'retro' })} alt={userData.nickname} /> <div> <span id="profile-name">{userData.nickname}</span> <span id="profile-active">Active</span> </div> </ProfileModal> <LogOutButton onClick={onLogout}>로그아웃</LogOutButton> </Menu>} </span> </RightMenu> </Header> <WorkspaceWrapper> <Workspaces> {userData?.Workspaces.map((ws) => { return ( <Link key={ws.id} to={`/workspace/${123}/channel/일반`}> <WorkspaceButton>{ws.name.slice(0, 1).toUpperCase()}</WorkspaceButton> </Link> ); })} <AddButton onClick={onClickCreateWorkspace}>+</AddButton> </Workspaces> <Channels> <WorkspaceName>Sleact</WorkspaceName> <MenuScroll>menu scroll</MenuScroll> </Channels> <Chats> <Routes> <Route path="/channel" element={<Channel />} /> <Route path="/dm" element={<DirectMessage />} /> </Routes> </Chats> {/* Input이 들어있으면 별도의 컴포넌트로 빼는 것을 추천(input에 글자를 입력할 때마다 여기 있는 함수들이 다 리렌더링 되기 때문에 비효율적) */} </WorkspaceWrapper> <Modal show={showCreateWorkspaceModal} onCloseModal={onCloseModal}> <form onSubmit={onCreateWorkspace}> <Label id="workspace-label"> <span>워크스페이스 이름</span> <Input id="workspace" value={newWorkspace} onChange={onChangeNewWorkspace} /> </Label> <Label id="workspace-url-label"> <span>워크스페이스 이름</span> <Input id="workspace" value={newUrl} onChange={onChangeNewUrl} /> </Label> <Button type="submit">생성하기</Button> </form> </Modal> </div> ) } export default Workspace;Modal/index.tsximport React, { useCallback, FC } from "react"; import { CloseModalButton, CreateModal } from "./style"; interface Props { show: boolean; onCloseModal: () => void; children: React.ReactNode; } const Modal: FC<Props> = ({show, children, onCloseModal}) => { const stopPropagation = useCallback((e: any) => { e.stopPropagation() }, []); if(!show){ return null; } return( <CreateModal onClick={onCloseModal}> <div onClick={stopPropagation}> <CloseModalButton onClick={onCloseModal}>×</CloseModalButton> {children} </div> </CreateModal> ); }; export default Modal;swr2.0 버전, react v18, typescript v18swr을 최신버전 사용해서 revalidate대신 mutate를 사용했는데 제가 잘못 사용한건지 모르겠습니다.
-
미해결[리뉴얼] 타입스크립트 올인원 : Part2. 실전 분석편
함수를 매개변수로 전달시
jQuery 타입 분석 Q&A 3분대에서,(this : TElement , index : number , oldhtml : JQuery.htmlString)=> JQuery.htmlString이라는 매개변수 자리에function () {return '<div>hello</div>'}를 전달하셨는데, 인수로 쓰이는 함수는 매개변수 개수가 똑같을 필요가 없다고 하셨습니다.개인적인 추측으로는 반공변성과 관련이 있다고 생각이 드는데 , 질문에서 첫번째 함수가 두번째 함수의 서브타입이기 때문에, 첫번째 함수 자리에 두번째 함수를 대입할 수 있다고 이해해도 될까요?그렇다면 이 예제에서 만약 전달하고 싶은 함수의 매개변수가 4개라면, 반공변성에 의해 어긋나서, 전달하지 못한다고 생각해도 될까요?
-
미해결따라하며 배우는 리액트 A-Z
동영상이 흐릿하게 나옵니다
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 넷플릭스 실습을 하면서 iframe을 사용해 유튜브에서 동영상이 나오게 하는거 까지는 완료가 되었습니다.그런데 재생버튼을 누르고 영상이 시작되면 그림처럼 흐릿하게 나오는데 왜 그런걸까요?
-
미해결[리뉴얼] 타입스크립트 올인원 : Part1. 기본 문법편
number 타입 -> string 타입으로 변경할때, `as unknow` 을 사용해야 에러가 안나는 이유가 무엇인가요?
number 타입 -> string 타입으로 변경할때, as unknow 을 사용해야 에러가 안나는 이유가 무엇인가요?문법적인 이유일까요?
-
해결됨타입스크립트 입문 - 기초부터 실전까지
함수 반환 타입에서 유니온 타입에 대한 질문이 있습니다
타입을 유니온 타입으로 선언할 경우,해당 타입은 A, B 타입의 교차 속성에만 접근 가능한 것으로 이해하고 있습니다그래서function fn(): string | number { // do something } const val = fn(); val.toFixed(2) // type error에서val 의 타입이 string과 number의 교차 속성만을 가진 타입이라서 toFixed가 타입 오류를 내는 것으로 이해하고 있습니다.질문 드리고 싶은 것은,특정 함수가 A 타입인 값이나 또는 B 타입인 값을 반환할 수 있다고 가정할 경우,반환된 값을 변수에 할당하여 사용할 때 A 타입의 모든 속성 또는 B 타입의 모든 속성에 접근 할 수 있도록 하고자 한다면반환 타입을 어떻게 선언해야 하는지 궁금합니다.단순히 or 로 생각해서 유니온타입을 설정하면 교차 속성에만 접근이 되니 타입 오류가 발생하게 되어 어떻게 해야 할지 모르겠습니다.
-
미해결타입스크립트 입문 - 기초부터 실전까지
repository 의 app.js 소스 수정 요망
app.js 의 소스 2행의 코드가, 최초로 clone 후 받아온 소스와 강의에서 진행되는 코드가 서로 다릅니다. 강의에서는 디폴트가 /users 입니다.하지만 실제 repository 에는 /users/1 로 단일 객체로 가져옵니다. 영상 내에서 해당 항목에 대한 명시적인 소스 수정 부분도 없어, 그 부분을 인지 못하고 나머지 부분만 영상대로 따라하면서 수정하면 제대로 강의를 진행을 할 수 없습니다.자잘한 부분이기는 하지만, 이런 부분은 당연히 적용되어야 하는 부분 같습니다. step by step 으로 따라가는 걸 전제로 하는 게 아닐까요?
-
해결됨타입스크립트 시작하기
객체 할당 관련 질문 있습니다.
전체 질문으로 올라가 있었어서 다시 올렸습니다;; 1) 4:45에서 "속성이 많을 수록 타입에 더 많은 제약을 가하는 것이고 이는 해당 타입의 값의 집합이 작아지는 것을 의미한다" 고 설명해주셨고,6:43에서는 "Person의 age 타입을 보면 Product의 타입이 더 크다"고 설명해주셨는데요그렇다면,타입이 가질 수 있는 값의 제약이 더 클수록 타입이 작고,타입이 가질 수 있는 값이 더 유연해질 수록 타입이 크다고 이해하면 되는 걸까요?2) 아래 코드를 작성해보니interface Person { name: string; } interface Product { name: string, age: number, } const obj = { name: "mkie", age: `23`, city: `abc`, }; let person: Person = obj let product: Product = obj; console.log(person.age)person.age에서 타입 오류가 발생하던데요그렇다면, person에 obj가 할당은 가능하지만person의 타입에 정의되지 않은 properties는 사용할 수 없다는 것으로 이해하는게 맞는건지요?할당 이후에 person을 log로 찍어보면 obj의 properties가 모두 출력되는데person.age에 접근해보면 타입 오류가 발생하고 있어서 이해가 잘 안되네요만일 그렇다면 저런 할당이 왜 필요한지도 이해가 안되고....... 실제로 저런식의 할당을 하는 경우는 어떤 것이 있을까요?
-
해결됨타입스크립트 시작하기
퀴즈 관련 질문이 있습니다.
퀴즈 4번 문제에 function f2(value: number) { if (value < 10) { return value; } else { return "too big"; } } const v2: number = f2(5); const v3: string = f2(35); const v4 = f2(5); 여기서 f2 의 반환 타입은 number | "too big"이 아닌가요?답안 4번 v4의 타입은 "number | string" 이다가 옳은 것으로 되어 있는데 제가 이해를 잘못한 건지....
-
미해결따라하며 배우는 리액트 A-Z
getByTestId
tdd 앱 개발 초입 강의에서 질문 있습니다.App.test.js에서는 screen.getByTestId("counter")를 했고, App.js 에서는 <h3> 내부에 data-testid="counter" 라고 되어 있는데요.어떻게 App.js 내부의 <h3> 태그의 data-testid가 getByTestId로 불릴 수 있는지 궁금합니다..!그리고 넘어간 정보가 왜 0이 아니라 TextContent가 맞는걸까요?
-
해결됨따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
[서버 실행해서 지금까지 나오는 에러 해결] 부분 진행 중 에러
import "reflect-metadata";^^^^^^SyntaxError: Cannot use import statement outside a module 해당 에러 발생 후 , package.json 파일에type 을 추가 후 실행 하였더니, 충돌 에러가 발생합니다 ㅠ 어떻게 해결 해야 하는지 조언좀 부탁드립니다.https://github.com/bottlesun/study/tree/master/09-redditClone-nextjs