월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
리액트 버전업데이트에 관해 문의드려요
안녕하세요 리액트로 웹개발 시작한 6개월차 신입개발자 입니다. 강의 정말 잘 보고있는데 너무 감사하게도 우연히 저희 안건과 개발환경이 많이 겹쳐서 큰 도움받고있습니다! 현재 안건에서 쓰는 리액트버전이 15.6.1인데 이번에 최신버전 v18.2.0로 업데이트하는 미션이 떨어졌는데어떻게 헤쳐나가야할지 너무 답답해서 고민끝에 질문드립니다...현재 안건의 스펙입니다. ・안건종류: 데이트 매칭 어플・메인언어: react・상태관리: redux・프레임워크 : koa・미들웨어: redux-thunk ======== 개요 ======== 일단 검색으로는 잘 정리된곳 찾기가 어려워서 리액트공식문서와 책 위주로 참고해서 정리중인데요, 우선 큰 틀을 짜고 문제점들을 세분화하면서 틀을 좁혀가려고합니다.. react, react-dom 최신버전 인스톨후에러를 우선순위별로 리스트화 하기・ReactDOM.render is no longer supported in React 18. Use createRoot instead.・Warning: componentWillMount has been renamed, and is not recommended for use.・componentWillReceiveProps has been renamed・You have triggered an unhandledRejection, you may have forgotten to catch a Promise rejection공동작업을 위한 규칙 리스트화 하기 ・class 컴포넌트 → function 컴포넌트로 변경・life cycle → useEffect 로 처리, 또는 커스텀 hook・react-redux 의 connect 함수 → useSelector, useDispatch Hooks로 리덕스와 컴포넌트 연동・state 업데이트시 불변성을위한 spread 연산자, immer 사용・코드 스플리팅: 라우팅에 React.lazy or Suspense 적용・react-redux 디렉토리 구조: 일반구조(component, container, reducer)-> ducks 패턴 사용해서 파일 모듈화의존중인 라이브러리및 패키지 업데이트 2와 3을 진행하며 기타 에러를 해결 ======== 질문 ========3번의 [공동작업을 위한 규칙 리스트화]의 경우, 검색과 에러기준으로 만들고있는데 너무 부족한것같습니다. 프로젝트 버전 업그레이드시, 기준이 되는 컨텐츠가 있는지 궁금합니다.현재 리액트 구버전 15부터 16,17,18 최신버전까지의 모든 업데이트 변경점을 체크해서 일일이 적용해야하는지(←React공식문서블로그에서), 단순히 15->18로 점프해서 바뀐사항만 적용해도되는지현재 구버전에서 사용중인 각종 패키지, 라이브러리 업데이트는 어떤 방향으로 진행해야할지-> 이부분이 제일 손대기 어려울정도로 막막합니다. 리액트버전업뎃처럼 똑같이 최신버전인스톨, 에러체크, 버전별 변경점 체크후 적용및 수정 하면 될까요? 입사 3개월차에 선배나 가이드없이 진행중이라 정말 고민끝에 질문드립니다…혹시 시간나실때 답변이나 조언해주시면 정말 감사하겠습니다……(살려주세요…..)잘부탁드려요 ! (제발 구원의 손길을 ㅠㅠㅠ) package.json (react만 최신인스톨)"dependencies": { "@paypal/paypal-js": "4.1.0", "babel-runtime": "^6.25.0", "chart.js": "^2.6.0", "classnames": "^2.2.3", "es6-promise": "^4.1.1", "exif-js": "^2.2.1", "firebase": "^7.7.0", "history": "^3.3.0", "koa": "^1.2.0", "koa-static": "^2.0.0", "lodash.reverse": "^4.0.1", "lodash.sortby": "^4.5.0", "lodash.throttle": "^4.0.0", "lodash.uniqby": "^4.5.0", "moment": "^2.17.0", "moment-timezone": "^0.5.13", "node-fetch": "^2.6.6", "normalizr": "^2.3.0", "object-assign": "^4.0.1", "pm2": "^2.6.1", "prop-types": "^15.5.10", "react": "^18.2.0", "react-chartjs-2": "^2.5.6", "react-dom": "^18.2.0", "react-ga": "^2.1.2", "react-helmet": "^5.1.3", "react-infinite-scroller": "^1.2.4", "react-redux": "^5.0.2", "react-router": "^3.0.5", "react-router-redux": "^4.0.1", "react-router-scroll": "^0.4.1", "react-scroll": "1.5.4", "react-slick": "^0.14.5", "react-swipeable": "^4.0.1", "react-textarea-autosize": "^5.0.6", "redux": "^3.7.2", "redux-actions": "^2.2.1", "redux-api-middleware": "^1.0.3", "redux-logger": "^3.0.6", "redux-thunk": "^2.4.0" }, "devDependencies": { "babel-cli": "^6.7.5", "babel-eslint": "^8.2.3", "babel-plugin-espower": "^2.3.1", "babel-plugin-module-resolver": "^4.1.0", "babel-plugin-transform-async-to-generator": "^6.24.1", "babel-plugin-transform-class-properties": "^6.6.0", "babel-plugin-transform-export-extensions": "^6.22.0", "babel-plugin-transform-object-rest-spread": "^6.23.0", "babel-plugin-transform-runtime": "^6.15.0", "babel-preset-es2015": "^6.6.0", "babel-preset-react": "^6.3.13", "babel-register": "^6.7.2", "babelify": "^7.3.0", "browserify": "^13.0.0", "css-mqpacker": "^6.0.1", "csswring": "^6.0.0", "envify": "^4.1.0", "eslint": "^4.19.1", "eslint-config-tapplint": "^2.0.1", "eslint-config-tapplint-react": "^1.0.0", "eslint-plugin-react": "7.4.0", "gulp": "^3.9.0", "gulp-consolidate": "^0.2.0", "gulp-htmlmin": "^3.0.0", "gulp-iconfont": "^8.0.0", "gulp-imagemin": "^3.3.0", "gulp-notify": "^3.0.0", "gulp-plumber": "^1.0.1", "gulp-postcss": "^6.4.0", "gulp-rename": "^1.2.2", "gulp-sketch": "^1.0.5", "gulp-sourcemaps": "^2.0.0", "husky": "^0.14.3", "karma": "^1.1.0", "karma-browserify": "^5.0.5", "karma-chrome-launcher": "^2.2.0", "karma-mocha": "^1.0.1", "karma-mocha-reporter": "^2.0.3", "lint-staged": "^7.2.2", "lodash": "^4.11.1", "md5-file": "^4.0.0", "mocha": "^3.5.0", "postcss": "^5.2.17", "postcss-cssnext": "^3.1.1", "postcss-import": "^10.0.0", "postcss-media-variables": "^2.0.0", "postcss-nesting": "^2.3.1", "power-assert": "^1.4.4", "react-addons-test-utils": "~15.6.0", "react-prefixr": "^0.1.0", "require-dir": "^0.3.2", "stylelint": "^7.13.0", "stylelint-config-standard": "^16.0.0", "stylelint-order": "^0.5.0", "tapplint": "^0.9.0", "terser": "^4.6.11", "uglifyify": "^5.0.2", "watchify": "^3.7.0", "yargs": "^6.0.0" }
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
토글버튼 이벤트에 useCallback 사용이유
const onToggleComment = useCallback(() => { setCommentFormOpened((prev) => !prev) }, []) const onToggleComment = () => { setCommentFormOpened(!commentFormOpened) }해당 강의 주차에서 토글버튼에 useCallback을 사용한 이유가 무엇인가요?useCallback을 사용하지 않고 아래와 같이 구현하면 성능에 문제가 생기는 이유때문인지 궁금합니다.
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
버전이나 리뉴얼 관련해서..
작년에 사뒀는데 들으려고 보니 버전 차이가 조금 있더라고요그대로 들어도 무리가 없을지, 아니면 리뉴얼 예정이 있는지 궁금합니다 +) 타임어택 3기 예정도 궁금합니다!
- 해결됨[리뉴얼] React로 NodeBird SNS 만들기
post 로 id, password 전송시 => 크롬 개발자 도구, 네트워크, Request 에 보면 id, password 가 그대로 노출되는데 숨길순 없나요?
post 로 id, password 전송시 => 크롬 개발자 도구, 네트워크, Request 에 보면 id, password 가 그대로 노출되는데 숨길순 없나요?브라우저를 사용하는 유저가 보낸 거기 때문에 보안을 안해도 상관없을까요?
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
시퀄라이즈 컬럼 추가
시퀄라이즈에서 테이블 컬럼에 새로운 값을 추가하고 싶은데 어떻게 db에 반영을 할 수 있는지 궁금합니다
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
게시글 구현하기 부분에서 갑자기 SyntaxError: Cannot use import statement outside a module 에러가 뜹니다
\react-nodebird\front\node_modules\antd\es\button\button-group.js:9import classNames from 'classnames'; 에러가 뜨는 경로는 이렇게 되어있고,button -group 부분 코드는 여기 아래에 있습니다.import React, {useCallback, useState} from 'react'; import {Avatar, Button, Card, Popover} from 'antd'; import {EllipsisOutlined, HeartOutlined, MessageOutlined, RetweetOutlined, } from '@ant-design/icons' import ButtonGroup from 'antd/es/button/button-group'; import { useSelector } from 'react-redux'; const PostCard = ({post}) => { const {me} = useSelector((state) => state.user); const id = me && me.id; const [liked, setLiked] = useState(false); const [commentFormOpened, setCommentFormOpened] = useState(false); const onToggleLike = useCallback(() => { setLiked((prev) => !prev); }, []); const onToggleComment = useCallback(() => { setCommentFormOpened((prev) => !prev); }, []) return ( <div style={{marginBottom:20}}> <Card cover ={post.Images[0] && <PostImages images = {post.Images} />} actions = {[ <RetweetOutlined key = 'retweet'/>, liked ? <HeartTwoTone twoToneColor="#eb2f96" key = 'heart' onClick={onToggleLike}/> : <HeartOutlined key = 'heart'/>, <MessageOutlined key ='comment' onClick={onToggleComment}/>, <Popover key = 'more' content = {( <Button.Group> {id && post.User.id === id ? ( <> <Button>수정</Button> <Button type ='danger'>삭제</Button> </> ) : <Button>신고</Button> } </Button.Group> )}> <EllipsisOutlined/> </Popover>, ]} > <Image /> <Card.Meta avatar = {<Avatar>{post.User.nickname[0]}</Avatar>} title = {post.User.nickname} description={post.content} /> <Button></Button> </Card> {commentFormOpened && <div> 댓글부분 </div>} {/*<CommentForm /> <Comments />*/} </div> ); }; export default PostCard;구글링을 진행하여 package.json파일에 "type" : "module"을 작성하라고 나와서 작성하고 코드를 실행하면 TypeError: styled_components__WEBPACK_IMPORTED_MODULE_4__.div is not a functionat eval (webpack-internal:///./components/LoginForm.js:21:73)이렇게 스타일드 컴포넌트에러가 납니다. 그래서 스타일드 컴포넌트를 사용하는 모든 부분을 지우고 진행을 하면 가장 처음에 나는 에러인 SyntaxError: Cannot use import statement outside a module이 에러가 등장합니다.모든 버전은 가장 최신 버전 사용했습니다. 열심히 찾았는데 정답이 보이지 않아서질문 드립니다.
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
질문있습니다. reduces 상태값 관련
안녕하세요 다름이아니라 해당 강의 내용 중signup에서 해당 회원등록이 success 후 singDone 이 true 로 변하잖아요그래서 useEffect((singDone) => {Router.replace('/')},[singDone] )해서 ture 일떄 메인페이지로 이동하는데메인페이지이동했을때 __NEXT_REDUX_WRAPPER_HYDR.... 에서 singDone 상태값이 다시 false로 돌아왔던데이게 어떤 개념으로 되었던거지요?관련 개념 사용해서 프로젝트 중인데 저는 페이지를 넘기고 __NEXT_REDUX_WRAPPER_HYDR....에서 상태값이 그대로 ture 다시 접근이 안되네요... 관련 흐름은 같은 개념의 코드 흐름으로 짯는데 말이죠 그래서 말인데 이게 어떤 원리로 true로 바뀐 상태값이 다시 false로 초기화 되어서 해당 페이지를 다시 진입할 수 있던거였죠?
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
nginx에 대해서 질문입니다.
강의 내용과는 상관없지만 클라이언트에서 post요청으로 보낸 파라미터를 nginx에서 받고 그 파라미터를 서버쪽으로 보내주도록 nginx를 설정하고 싶은데 혹시 nginx에서 파라미터를 받는 방법에 대해서 여쭤봐도 될까요?nginx측에 $request_body로 파라미터를 받고 그걸 url로서버측에 전송하려고하는데 $request_body에 파라미터가 설정되있지 않아서 서버쪽에 전송을 해도 공백값만 전송이 되네요
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
댓글 구현하기 중 콘솔창에 출력이 안됩니다..
댓글창에 텍스트 입력후 버튼을 누르면id는 출력이되는데 e.target.value가 출력이 안됩니다..그런데 한참 지나면 또 출력이 됬다가 안됬다가 합니다..Next가 인식이 잘 안되어서 그런걸까여? 아래는 커스텀 훅은 코드 와CommentForm 코드 입니다..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]; }; import React, { useCallback } from "react"; import { Button, Form, Input } from "antd"; import useInput from "../hooks/useInput"; import PropTypes from "prop-types"; import { useSelector } from "react-redux"; const CommentForm = ({ post }) => { const id = useSelector((state) => state.user.me?.id); const [commentText, onChangeCommentText] = useInput(""); const onSubmitComment = useCallback(() => { console.log(post.id, commentText); }, []); return ( <Form onFinish={onSubmitComment}> <Form.Item> <Input.TextArea value={commentText} onChange={onChangeCommentText} rows={4} /> <Button type="primary" htmlType="submit"> 삐약 </Button> </Form.Item> </Form> ); }; CommentForm.propTypes = { post: PropTypes.object.isRequired, }; export default CommentForm;
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
더미데이터와 포스트폼 만들기 강의 중 사진업로드 input 관련 문의드립니다.
제 브라우저에서는 이미지업로드 input 이 숨겨져있지않고 보입니다.. display: block; 을 풀면 사라지는데.. input의 hidden이 먹히질 않은걸까요..?atnd 버전이 달라서 그런걸까요? 버전은 5입니다. <div> <input type="file" multiple hidden ref={imageInput} /> <Button onClick={onClickImageUpload}>이미지 업로드</Button> <Button type="primary" style={{ float: "right" }} htmlType="submit"> 짹짹 </Button> </div>
- 해결됨[리뉴얼] React로 NodeBird SNS 만들기
useInput을 typescript에서 사용하고 싶은데
강사님께 useInput 커스텀훅을 배웠는데, 굉장히 사용감이 좋아서 다른 react파일에서도 자주 사용하고 있었는데요 제가 이걸 typescript 프로젝트에서도 사용하고 싶은데, 제가 아직 typescript를 공부중이라 지식이 조금 부족해서요 ㅠ 혹시 도와주실수 있을까 싶어 질문드려 봅니다 .. const useInput = (initialValue: string | number) => { const [value, setValue] = useState(initialValue); const handler = useCallback((e: React.ChangeEvent<HTMLInputElement>) => { setValue(e.target.value); }, []); return [value, handler, setValue]; 이렇게 작성하고 input을 <input name="user-email" type="email" value={email} required onChange={onChangeEmail} />이렇게 작성하였는데 , value와 onChange 각각에서 이런 오류가 발생하는데, 구글링을 해보아도 잘 못찾겠어서,,ㅠ 혹시 어떤식으로 type 코드를 수정해야할지 도움을 주실수 있을까요 ?
- 해결됨[리뉴얼] React로 NodeBird SNS 만들기
컴포넌트의 props 를 비교후 리랜더링 방지해주는 memo() 사용안하시는 이유가있나요?
컴포넌트의 props 를 비교후 리랜더링 방지해주는 memo() 사용안하시는 이유가있나요?useCallback, useMemo 는 사용하시는 모습을 많이 보았는데, memo 는 사용하시는 모습을 보지 못하여 질문 합니다!
- 해결됨[리뉴얼] React로 NodeBird SNS 만들기
front 부분 여러가지 질문
nodebird react에서 front부분까지만 들은 상태입니다.redux 의 실행 흐름이dispatch(액션) -> 미들웨어(redux-saga) -> 리듀서 -> 스토어이러한 방식으로 알고 있는데언뜻 보면 미들웨어가 먼저 실행되니 success or failure가 먼저 실행될것 같은데saga함수에 딜레이를 안주더라도 실행은 request가 무조건 먼저 되는것 같습니다.왜 이렇게 실행이 되는건가요? 미들웨어와 리듀서가 비동기적으로 실행되는건가요?Success or failure가 먼저 실행되는 케이스가 있나요? 각 기능들에 대한 상태관리를 request, success, failure 3가지의 액션타입으로 관리하는 이유가 뭔가요? 공식문서에는 이렇게 나와있긴 한데 https://lunit.gitbook.io/redux-in-korean/advanced/asyncactions" 하나의 액션 타입에 표지를 두고 사용하건, 여러 액션 타입을 사용하건 여러분에게 달렸습니다. 여러분이 팀과 함께 정할 규칙일 뿐입니다. 여러 타입을 쓰면 실수는 줄겠지만, 여러분이 redux-actions와 같은 헬퍼 라이브러리를 써서 액션 생산자와 리듀서를 만든다면 이게 별 문제가 되지 않을 수도 있습니다. " 제로초님 입장에서는 어떻게 생각하시나요? 또 실무에서는 하나의 액션으로 처리하는지 아니면 강좌처럼 세가지의 액션으로 나누어서 처리하는지 궁금합니다. request에 대한 로직을 하나 보면case LOG_IN_REQUEST: draft.loginLoading = true; draft.logInError = null; draft.logInDone = false; // Done을 왜 굳이 초기화 해야하지?logInDone 같은 경우는 request 이전에도 이미 false라고 생각하는데 따로 초기화를 명시해주는 이유가 있나요? 프론트엔드를 구현할때 처음에 데이터 구조 잡을 때 아직 정해진거 없으면 전체 데이터베이스 구조를 제가 정하고 들어가야 하는건가요?전체 테이블 구조를 관계설정까지 다 잡고 들어가야 하는건지, 아니면 내가 구현하는 기능에 대한 테이블 구조만 하나씩 잡고 들어가면 되는건지 궁금합니다. 사실 이 강좌를 듣기 전에는 프론트엔드 부분 데이터를 구현할 때백엔드로 요청을 보내고, 그 응답으로 데이터를 건네받아서, 해당 데이터를 가지고 프론트에 직접 값을 표시하는 방식으로 웹이 돌아가겠지, 라고 생각을 했습니다.(프론트엔드에서 API 요청 -> 백엔드에서 데이터처리, 응답 -> 응답에서 받은 데이터로 뷰 가공 및 출력)그런데 강좌에서는 벡엔드에서의 처리와 별개로, 프론트에서의 데이터는 프론트에서의 로직만으로 처리하도록 구현하셨는데요. 이렇게 하는 이유가 있으신가요? 프론트를 처음 구현할때 처음에 데이터 구조 잡을 때 아직 정해진거 없으면 먼저 전체 데이터베이스 구조를 제가 정하고 들어가야 하는건가요?전체 테이블 구조를 관계설정까지 다 잡고 들어가야 하는건지, 아니면 내가 구현하는 기능에 대한 테이블 구조만 하나씩 잡고 들어가면 되는건지 궁금합니다. redux saga 함수 로직보면 백엔드API요청 후에 put 연산 success or failure 로직으로 나뉘는데원래 try catch 문 안쓰면 axios.post().then(() => put(action)).catch(e => put(action)) 이런식으로 쓰는 로직이랑 같은건가요?
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
제로초님 github에있는 최신코드랑 여기 리뉴얼한 코드랑 다른가요?
따라치기는 너무 무리일꺼같아서 제로초님 github에있는 react_nodebird master(default) pull 해서 그거랑 동영상 보면서 공부하고있는데요.코드가 리뉴얼강의 찍기 전에 올리신것인지, 제로초님이 강의하면서 적어주신 코드랑 그 깃허브에 저장되어있는 코드랑 좀 많이 달라서 문의드립니다.예를들면 LoginForm.js 에는LoginForm.propTypes = { setIsLoggedIn: PropTypes.func.isRequired, };이부분이 안들어가는데 여기 동영상 보면 이 코드를 적으시더라구요그리고 github 에있는건 인라인으로 css로 적용해주시는데, 새로운 강의에서는 리렌더링을 방지하기위해서 라고 하시면서 styled-components를 적용하시던데, 혹시 제가 최신으로 올리신 github를 못찾고있는것인가 해서 여쭤봅니다.!!혹시나 리뉴얼된 코드 올려주신게 있다면 경로를 여쭤봐도될까요?!
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
해쉬태그 관련
안녕하세요 강의를 바탕으로 포트폴리오를 만들고 있습니다 좋은 강의 항상 감사합니다제가 기존코드에서 추가하고 싶은 기능이 있습니다 포스트에서 많이 사용된 해쉬태그를 많이 사용된 순서로 순위를 보여주는 기능을 구현하고 싶은데 어떤식으로 구현해야할지 모르겠어서 질문 드립니다. 데이터베이스 모델부터 다시 정의해야 하는건지 어떻게 해야할지 감이 아예 안잡히네요 .
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
로그인시 500 에러 질문있습니다.
안녕하세요 강의를 보고 코드를 작성하고 테스트 중 잘 안되는 부분이 있어 질문드립니다. 현재 로그인 요청을 보낼때 네트워크에서 500에러를 발생하는데 에러를 추적해 본 결과 passport 로그인 과정 중에서 req.login 콜백함수 실행중에 loginErr이 발생하는것으로 확인했습니다.에러메시지로는 function serialized(e, o) { pass(i + 1, e, o); }로만 나와서 잘 확인이 어려운데 혹시 세션과 쿠키파서에 대한 에러내용일까요??에러내용, 코드 첨부드립니다.app.jsroutes/user.js
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
댓글 등록 관련 질문
안녕하세요 선생님. 댓글 등록을 만들던 중 궁금한 점이 생겨 질문 드립니다.제 프로젝트의 댓글에는 점수가 들어가는데, 한 게시글에 달린 댓글들의 점수의 평균을 어느 시점에서 처리하는게 좋을지 고민이 됩니다. 새 댓글을 생성 시에 댓글 평균을 내는게 좋은지, 아니면 게시글을 불러올 때 해당 게시글에 달린 댓글의 점수 평균을 계산하는게 좋은지 알 수 있을까요?
- 해결됨[리뉴얼] React로 NodeBird SNS 만들기
실무에서 시퀄라이즈로 스키마를 정의하지 못한 테이블과의 Join 이 많이 발생할 경우, 시퀄라이즈를 사용하는 장점이 있을까요?
실무에서 시퀄라이즈로 스키마를 정의하지 못한 테이블과의 Join 이 많이 발생할 경우, 시퀄라이즈를 사용하는 장점이 있을까요?
- 해결됨[리뉴얼] React로 NodeBird SNS 만들기
실무에서 db 마이그레이션 발생시, 시퀄라이즈 에서 하나요? 혹은 db를 직접 수정하나요?
실무에서 db 마이그레이션 발생시, 시퀄라이즈 에서 하나요? 혹은 db를 직접 수정하나요? 만약 db 를 직접 수정한다고 한다면, 처음 model 에 정의해준 시퀄라이즈로 작성한 스키마도 수정을 해주어야하나요? 예상되는 마이그레이션 사항 예1) varchar -> Text 로 컬럼의 타입 변경 예2) User 테이블에 age 컬럼 추가
- 미해결[리뉴얼] React로 NodeBird SNS 만들기
next.js pages 질문드립니다.
/board/talk/hello/board/talk/bye/board/talk/goodbye 위와 같이 url만 다르고 사용하는 컴포넌트가 같은 경우에,동적 라우팅 사용해서 /board/talk/[say] 이런 식으로 구현하는 방법 밖에 없을까요? 경우의 수가 늘 때마다 동적 라우팅하니까 뭔가 지저분해서요.