묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
Aws s3
배포를 하려고 하는 와중에 Aws s3 사용에 관련해서 과금이 많이 나올까봐 걱정이 되는데 혹시 보안적으로 안전하게 사용하는 방법 있을까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
작성자 비밀번호 레이아웃이 깨져요
_app.js에 글로벌 적용시켜서 전체 레이아웃은 잡았는데 작성자랑 비밀번호 구역이 들어가는 부분에서 justify-content: space-between; 명령어가 먹질 않아요ㅠㅠ뭐가 문젠가 해서 justify-content: center 해봐도 먹히지않아 문제가 다른곳에 있는것같은데 도통 알수가 없습니다..아래에 코드 첨부합니다ㅠ index.jsemotion.js
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
npx sequelize db:create
npx sequelize db:create를 하면 제로초님 처럼 Access denied for user 'root'@'localhost' (using password: YES) 이게 뜹니다 그래서 mysql로 들어가서 root 비밀번호를 바꿨습니다. 이렇게 뜨고 잘 바꿨는데도 계속 에러가 뜹니다. 구글에도 쳐보고 했지만 mysql_native_password 로 바꾸는 안내만 봐서... 어떻게 조치를 더 해야될까요 ?
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
npm run dev 에러
[제로초 강좌 질문 필독 사항입니다]질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다.도움이 되는 질문을 하는 방법을 알려드립니다.https://www.youtube.com/watch?v=PUKOWrOuC0c0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다.1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다.2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다.3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요.4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요.5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다.6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
antd 별점 라이브러리 및 antd.css import 관련 질문
안녕하세요, 멘토님이 질문이 하나쯤은 있을 줄 알고 찾아봤는데 없어서 올립니다.antd 별점과 모달을 듣고 섹션9 퀴즈 부분을 진행 중인데섹션9 퀴즈 1번인 별점 클릭 시 별점 가져오기를 진행하는데 점수가 이상하게 출력됩니다.4점 위치에서 클릭하면 2점이 나온다던가,3점 위치에서 클릭하면 뒤이어 아까 선택했던 4점이 나오는 등이전에 선택했던 별점들이 한 차례 뒤로 밀려서 출력되는 느낌입니다.추후에 해당 부분 리뷰가 있을진 모르겠으나, 먼저 퀴즈와 포폴을 다 만들고 보려고 하는 것도 있고 해당 부분은 왜 이런지.. 추후에 포폴에 적용할 때도 문제가 될듯 싶어서 질문올립니다. 그리고 어떨 때는 강의에서 알려주신 것 처럼import "antd/dist/antd.css";를 import해야 정상 렌더링 되는 때가 있고, 어떨 때(어떤 것?)는 해당 CSS를 import하지 않아도 정상 렌더링 되는 현상도 있습니다.이것은 또 왜 경우가 나뉘는지 궁금합니다. 감사합니다.
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
postcss-preset-env대신 postcss autoprefixer 설치 해도 될까요?
tailwind.css 공식 홈페이지에는 postcss와 autoprefixer 설치가 나오던데 저걸 대신 설치 해도 될까요?https://tailwindcss.com/docs/guides/nextjs2번째 질문으로 위에 tailwind css 공식 홈페이지대로 하면 잘 되는데 저거 대로 진행해도 될까요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
svg 파일 관련 질문드립니다.
svg 파일을 사용하기 위해서 @svgr/webpack 설정하고 import 해서 컴포넌트처럼 사용하고있는데요.이미지 파일을 public에 두고 사용중인데 svg 파일은 제가 찾아본바로는 이미지 파일이라기보다 html/css에 가깝고 컴포넌트처럼 import 해서 사용하면 이미지가 아니기때문에 public 폴더가 아닌 다른 폴더로 빼서 파일을 관리해야될것같은데 svg 파일은 어디에 두는게 좋은가요? public 폴더에 놔두고 사용하는게 좋은지 아니면 따로 assests 폴더등을 만들어서 따로 관리하는게 좋은지 궁금합니다. !
-
미해결만들면서 배우는 프론트엔드 DO IT 코딩 (Next.js, Typescript)
배포 관련 질문
안녕하세요, 강사님.강의를 듣고 있는 학생입니다.제가 Next.js를 가지고 개발을 하고 있는데 배포를 할 때, Next.js로만 dockerfile을 작성해서 배포하면 되는 걸까요? 아니면 Vue.js와 같은 SPA 처럼 Nginx를 포함시켜서 dockerfile을 작성하고 각각 컨테이너를 만들고 연결시켜주면 되는 건가요?제가 이쪽 지식이 부족해서 수업 이외에 다른 것도 여쭤보게 되었는데,, 만약 답변이 가능하시다면 염치불구하고 물어보고 싶습니다 ㅠㅠ배포 환경은 EC2와 같은 가상컴퓨터환경(클라우드)에서 쿠버네티스를 만들고 그 위에 올릴거 같은데,, 어떤 구조를 참고하면 좋을지 고민이에요.
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
압축파일 말고, git이나 코드 복사할 수 있는 링크는 없나요?
생각보다 파일의 용량이 커서 압축이 안 풀립니다..ㅎㅎ복사해도 되는 부분들은 복사해서 쓰고 싶은데 있으면 공유 부탁드릴게요
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
loadPosts 에러
안녕하세요 선생님.무한스크롤링 강의까지 수강 했습니다. faker로 dummydata 만들어서 무한 스크롤링 구현했는데 중간에 뭘 잘못 건드렸는지 에러가 뜨네요..제 생각에는 아래의 에러 부분 문제 인거 같아서 post saga 부분과 reducer를 오랜 시간 봤는데 어디가 잘못 된건지 모르겠습니다... react_devtools_backend.js:2655 The above error occurred in task loadPosts created by throttle(LOAD_POSTS_REQUEST, loadPosts) created by watchLoadPosts created by postSaga created by rootSagaTasks cancelled due to error:throttle(LOAD_POSTS_REQUEST, loadPosts)watchAddPostwatchRemovePostwatchAddCommentuserSaga
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
ADD_COMMENT_FAILURE 에러
error - ./sagas/post.jsAttempted import error: 'ADD_COMMENT_FAILURE' is not exported from '../reducers/post'.와 같이 오류 코드가 뜹니다. 간단한 문제인거 같은데 해결이 안되네요.아래는 두 코드입니다. ./reducer/post.jsimport shortId from 'shortid'; import faker from 'faker'; import produce from '../util/produce'; export const initialState = { mainPosts: [], imagePaths: [], hasMorePosts: true, loadPostsLoading: false, loadPostsDone: false, loadPostsError: null, addPostLoading: false, addPostDone: false, addPostError: null, removePostLoading: false, removePostDone: false, removePostError: null, addCommentLoading: false, addCommentDone: false, addCommentError: null, }; // -> index.js export const generateDummyPost = (number) => Array(number).fill().map(() => ({ id: shortId.generate(), User: { id: shortId.generate(), nickname: faker.name.findName(), }, content: faker.lorem.paragraph(), //아무런 글자 Images: [{ src: faker.image.image(), //공간만 차지할꺼면 placeholder }], Comments: [{ User: { id: shortId.generate(), nickname: faker.name.findName(), }, content: faker.lorem.sentence(), }], })); export const LOAD_POSTS_REQUEST = 'LOAD_POSTS_REQUEST'; export const LOAD_POSTS_SUCCESS = 'LOAD_POSTS_SUCCESS'; export const LOAD_POSTS_FAILURE = 'LOAD_POSTS_FAILURE'; export const ADD_POST_REQUEST = 'ADD_POST_REQUEST'; export const ADD_POST_SUCCESS = 'ADD_POST_SUCCESS'; export const ADD_POST_FAILURE = 'ADD_POST_FAILURE'; export const REMOVE_POST_REQUEST = 'REMOVE_POST_REQUEST'; export const REMOVE_POST_SUCCESS = 'REMOVE_POST_SUCCESS'; export const REMOVE_POST_FAILURE = 'REMOVE_POST_FAILURE'; export const ADD_COMMENT_REQUEST = 'ADD_COMMENT_REQUEST'; export const ADD_COMMENT_SUCCESS = 'ADD_COMMENT_SUCCESS'; export const ADD_COMMENT_FAILURE = 'ADD_COMMENT_FAILURE'; export const addPost = (data) => ({ type: ADD_POST_REQUEST, data, }); export const addComment = (data) => ({ type: ADD_COMMENT_REQUEST, data, }); const dummyPost = (data) => ({ id: data.id, content: data.content, User: { id: 1, nickname: '제로초', }, Images: [], Comments: [], }); const dummyComment = (data) => ({ id: shortId.generate(), content: data, User: { id: 1, nickname: '제로초', }, }); // 이전 상태를 액션을 통해 다음 상태로 만들어내는 함수(불변성은 지키면서) const reducer = (state = initialState, action) => produce(state, (draft) => { switch (action.type) { //state를 draft로 case LOAD_POSTS_REQUEST: draft.loadPostsLoading = true; //리퀘스트가 갔을때는 로딩 draft.loadPostsDone = false; draft.loadPostsError = null; break; case LOAD_POSTS_SUCCESS: draft.loadPostsLoading = false; draft.loadPostsDone = true; draft.mainPosts = action.data.concat(draft.mainPosts); //데이터합치기 draft.hasMorePosts = draft.mainPosts.length < 50; //50개로 제한 게시글 50개만 보겠다. break; case LOAD_POSTS_FAILURE: draft.loadPostsLoading = false; draft.loadPostsError = action.error; break; case ADD_POST_REQUEST: draft.addPostLoading = true; draft.addPostDone = false; draft.addPostError = null; break; case ADD_POST_SUCCESS: draft.addPostLoading = false; draft.addPostDone = true; draft.mainPosts.unshift(dummyPost(action.data)); break; case ADD_POST_FAILURE: draft.addPostLoading = false; draft.addPostError = action.error; break; case REMOVE_POST_REQUEST: draft.removePostLoading = true; draft.removePostDone = false; draft.removePostError = null; break; case REMOVE_POST_SUCCESS: draft.removePostLoading = false; draft.removePostDone = true; draft.mainPosts = draft.mainPosts.filter((v) => v.id !== action.data); break; case REMOVE_POST_FAILURE: draft.removePostLoading = false; draft.removePostError = action.error; break; case ADD_COMMENT_REQUEST: draft.addCommentLoading = true; draft.addCommentDone = false; draft.addCommentError = null; break; case ADD_COMMENT_SUCCESS: { const post = draft.mainPosts.find((v) => v.id === action.data.postId); post.Comments.unshift(dummyComment(action.data.content)); draft.addCommentLoading = false; draft.addCommentDone = true; break; // const postIndex = state.mainPosts.findIndex((v) => v.id === action.data.postId); // const post = { ...state.mainPosts[postIndex] }; // post.Comments = [dummyComment(action.data.content), ...post.Comments]; // const mainPosts = [...state.mainPosts]; // mainPosts[postIndex] = post; // return { // ...state, // mainPosts, // addCommentLoading: false, // addCommentDone: true, // }; } case ADD_COMMENT_FAILURE: draft.addCommentLoading = false; draft.addCommentError = action.error; break; default: break; } }); export default reducer;./sagas/post.jsimport axios from 'axios'; import shortId from 'shortid'; import { all, delay, fork, put, takeLatest, throttle } from 'redux-saga/effects'; import { ADD_COMMENT_FAILURE, ADD_COMMENT_REQUEST, ADD_COMMENT_SUCCESS, ADD_POST_FAILURE, ADD_POST_REQUEST, ADD_POST_SUCCESS, generateDummyPost, LOAD_POSTS_FAILURE, LOAD_POSTS_REQUEST, LOAD_POSTS_SUCCESS, REMOVE_POST_FAILURE, REMOVE_POST_REQUEST, REMOVE_POST_SUCCESS, } from '../reducers/post'; import { ADD_POST_TO_ME, REMOVE_POST_OF_ME } from '../reducers/user'; function loadPostsAPI(data) { return axios.get('/api/posts', data); } function* loadPosts(action) { try { // const result = yield call(loadPostsAPI, action.data); yield delay(1000); yield put({ type: LOAD_POSTS_SUCCESS, data: generateDummyPost(10), }); } catch (err) { console.error(err); yield put({ type: LOAD_POSTS_FAILURE, data: err.response.data, }); } } function addPostAPI(data) { return axios.post('/api/post', data); } function* addPost(action) { try { // const result = yield call(addPostAPI, action.data); yield delay(1000); //서버를 구현하기 전까지 딜레이로 구현하는 효과 const id = shortId.generate(); yield put({ type: ADD_POST_SUCCESS, data: { id, content: action.data, }, }); yield put({ type: ADD_POST_TO_ME, data: id, }); } catch (err) { console.error(err); yield put({ type: ADD_POST_FAILURE, data: err.response.data, }); } } function removePostAPI(data) { return axios.delete('/api/post', data); } function* removePost(action) { try { // const result = yield call(removePostAPI, action.data); yield delay(1000); yield put({ type: REMOVE_POST_SUCCESS, data: action.data, }); yield put({ type: REMOVE_POST_OF_ME, data: action.data, }); } catch (err) { console.error(err); yield put({ type: REMOVE_POST_FAILURE, data: err.response.data, }); } } function addCommentAPI(data) { return axios.post(`/api/post/${data.postId}/comment`, data); } function* addComment(action) { try { // const result = yield call(addCommentAPI, action.data); yield delay(1000); yield put({ type: ADD_COMMENT_SUCCESS, data: action.data, }); } catch (err) { yield put({ type: ADD_COMMENT_FAILURE, data: err.response.data, }); } } //takeevery function* watchLoadPosts() { yield throttle(5000, LOAD_POSTS_REQUEST, loadPosts); //5초동안은 post request 한 번만 실행 } function* watchAddPost() { //클릭 실수 2번했을때(동시에 로딩 중일때) 마지막 클릭만 실행되게 every는 두 번 다 실행 yield takeLatest(ADD_POST_REQUEST, addPost); } function* watchRemovePost() { yield takeLatest(REMOVE_POST_REQUEST, removePost); } function* watchAddComment() { yield takeLatest(ADD_COMMENT_REQUEST, addComment); } export default function* postSaga() { yield all([ fork(watchAddPost), fork(watchLoadPosts), fork(watchRemovePost), fork(watchAddComment), ]); }제로초님 강의와 깃허브 보면서 제 코드에 문제가 있는지 찾아보고 수정도 해봤습니다.import export둘다 잘 들어 갔는데 다른 문제 일까요? 아니면 install이 안된게 있는 걸까요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
중복된 닉네임
중복된 닉네임할때 const exUser = await User.findOne({ where: { email: req.body.email, nickname: req.body.nickname, }, });이렇게 추가 해주면 되나요? 아니면 따로 만들어줘야하나요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
컨테이너 파일과 타입스 파일 매칭 질문
안녕하세요~ 포트폴리오 주소 가져오기 공부하면서 질문드립니다BoardWrite 컨테이너 파일과 타입스 파일에서 타입 명시해주는 부분이 이해되지 않습니다동그라미 친 부분만 그대로 타입 명시해주면 되는 줄 알았는데 타입스 파일에는 4부분으로 나눠져서 타입이 명시되 있어서요~ 저는 타입스 파일에서 4번째 동그라미만 있으면 될 것 같았어요~
-
해결됨따라하며 배우는 리액트 A-Z[19버전 반영]
Create Post 가 안되네요 ㅜ
강의 따라 하던 중에 앞 부분은 무리없이 잘 되었는데,강사님 코드 그대로 따라쳐도Create Post 가 아무 반응을 안합니다.물론 pocketBase에 아무 것도 안올라갑니다.혹시나 하여 Postman 으로pocketBase에 직접 POST request 해봤는데바로 잘 올라갑니다!
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
프론트쪽에서 env 나누나요?
현재 강의 front쪽에서 env 로컬 배포 일떄도 나누나요?
-
해결됨따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
노드 아예 모르는 상태로 들어도 괜찮을까요?
리액트는 어느정도 프로젝트도 해보고 웬만한건 구현이 가능한 정도인데 노드에 관해서 전혀 모르는데 수강해도 괜찮을까요?혹시 노드 지식이 필요하다면 어떤 강의를 듣고 와서 수강을 해야할까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
antd rating 질문
안녕하세요 ant design 사이트에서 별점을 가져와서 사용하는 부분 질문있습니다콘테이너 파일에서는 리턴부분에 바로 setStar={setStar}로 넘겨주면 프레젠터 파일에서 props.setStar로 받고 있습니다 다른 매개변수처럼 onChange 함수를 사용하지 않고 바로 setStar로 넘겨주는 이유는 무엇인가요? 작동이 되는 이유가 궁금합니다그리고 types 파일에서 setStar: Dispatch<SetStateAction<number>>;타입을 이렇게 받고 있는데 이 설명은 강의에서 못본것 같아서요~ ant design 사이트에서 알 수 있는 것인가요?? BoardCommentWrite.container.tsx 파일BoardCommentWrite.types.tsx 파일
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
fetchBoardComments 데이터를 map으로 뿌린 el 타입 지정
안녕하세요 멘토님!시간을 짬짬히 내서 공부하는지라 진도는 느리지만 그래도 여차저차 타입스크립트 포폴 전환까지 완료헀습니다.빨간 줄 한 곳도 없이 무사히 전환 완료하였으나 강의 내용에도 나오지 않은듯한? 부분에서 궁금한게 생겨서 질문 드립니다.댓글 리스트 컴포넌트 부분을 map으로 렌더링 하는 방식으로 작업하였는데요, 여기 el의 타입을 지정하는 부분에서 Pick<IQuery, "fetchBoardComments"> 타입이 먹히지 않아서 삽질을 좀 했습니다. 그래도 여차저차 types.ts 내부를 참고하면서 수정해본 결과, el: IBoardComment 를 그대로 el의 타입으로 지정해주니까 컴파일 에러가 사라지고 해결되었습니다.이건 알고 해결했다기 보다는 모르고 바꿨는데 운 좋게 에러가 사라진 것이라 왜 해결됐는지 알고 넘어가고 싶어서 질문드립니다. (이게 편법이거나 정답이 아닐 수도 있다는 생각도 들었습니다.)그리고 Pick<IQuery, "fetchBoardComments">와 IBoardComment는 어떠한 차이가 있는지 궁금합니다. 참고로 el을 props drilling 하여 보낸 presenter 부분은 이렇게 사용하고 있습니다. 감사합니다.
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
함께 아는 친구 기능 구현
다른 유저와 공통적으로 팔로잉을 하고 있는 유저 숫자를 구하고 싶은데 혹시 api를 어떤 방식으로 코딩하면 될까요? 항상 좋은강의 감사합니다
-
해결됨Next.js 시작하기(feat. 지도 서비스 개발)
killall -9 node 가 무엇인지요?
강의에서 포트가 남아있을경우 killall -9 node명령어를 사용하라고 하셨는데요..포트가 남아있다는게 무슨 뜻인지 모르겠습니다..저는 vscode로 진행중이며,npm run bulid 후에 npm run dev로 서버를 다시 시작하고 코드가 변경될때마다 Ctrl + c로 껏다가 다시 재시작 하여 반복 하는데요.강사님께서는 killall -9 node를 사용하시는데 이걸 왜 쓰는지 모르겠어요..그리고 killall node 사이의 -9 는 무슨뜻인가요?