๊ฐ์๊ต์ ๊ธฐ์ฌ(Pull Request) ํ์ํฉ๋๋ค.
๋ฐฑ์๋ ๊ฐ์ข ๊ฐ์๊ต์์ ์ฌ๊ธฐ ์ ์์ต๋๋ค.
๋ผ์ด๋ธ๊ฐ์ข ํต์ฌ ๋ด์ฉ ์ ๋ฆฌํด์ ์ฌ๊ธฐ(README.md)์ ์ฌ๋ ค๋์์ต๋๋ค~ ๋ค์๋ณด๊ธฐํ๋ฉด์ ๊ฐ์ด ์ฝ๊ณ ๋ณต์ตํ์๋ฉด ๋ฉ๋๋ค!
๋ฐฑ๊ทธ๋ผ์ด๋ ์ธํ
- node 16๋ฒ์ (14๋ 17๋ ๊ด์ฐฎ์)๊ณผ MySQL์ ๋ฏธ๋ฆฌ ์ค์นํ๊ธฐ, mysql์ ์ค์น๊ณผ์ ์ค ๋น๋ฒ ์ค์ ํจ.
- ์ด ๋ ํฌ git clone ๋ฐ๊ธฐ
- cd back
- npm i bcrypt && npm i (์ฌ๊ธฐ์ ์๋ฌ๋๋ฉด ์ง๋ฌธ์ผ๋ก ๋ฌธ์)
- .env ์์ฑํ๊ธฐ(COOKIE_SECRET๊ณผ MYSQL_PASSWORD ๋น๋ฐ๋ฒํธ ์ค์ )
COOKIE_SECRET=cookienyamnyam
MYSQL_PASSWORD=๋๋น๋น๋ฒ
- config/config.json ์ค์ (MYSQL ์ ์ ์ค์ )
- npx sequelize db:create(์คํค๋ง ์์ฑ)
- npm run devํ๋ค๊ฐ ctrl + c๋ก ๋๊ธฐ(ํ ์ด๋ธ ์์ฑ)
- npx sequelize db:seed:all(๊ธฐ์ด ๋ฐ์ดํฐ ๋ฃ๊ธฐ)
- npm run dev(์์ผ๋ก ๋งค๋ฒ ์ด๊ฑธ๋ก ๋ฐฑ์๋ ์๋ฒ ์ผ์ผ ํจ, 1~8์ ํ ํ์ ์์)
- localhost:3095์์ ์๋ฒ ๋์๊ฐ๋ ์ค(ํ๋ก ํธ ๊ฐ์๋ localhost:3090์์ ์งํ๋จ)
- ๋ฐฑ์๋ ๊ฐ๋ฐ์๊ฐ API.md์ typings/db.ts๋ฅผ ๋จ๊ฒจ๋ ์ํฉ
๊ฐ์ข ์์
๊ฐ์ข์์ ์ธ๊ธํ๋๋ก ์ง์ ์ธํ ํ๊ธฐ๋ณด๋ค๋ ๊ทธ๋ฅ settings/ts ํด๋ ํด๋ก ๋ฐ์์ ํ์๋ ๊ฒ์ ์ถ์ฒ๋๋ฆฝ๋๋ค. ์ง์ ์ธํ ํ๊ธฐ์๋ ๋ฒ์ ์ด ์๊พธ ๋ฌ๋ผ์ ธ์ ์ธํ ๋ฒ์ด ๋ฐ๋๊ณ , ์ ๋ฌธ์๋ถ๋คํํ ๋ ๋ฒ๊ฒ์ต๋๋ค. ํด๋๊ฐ ๋ง์์ ํท๊ฐ๋ฆฌ๋ back ํด๋๋ ๋ฐฑ์๋ ์ฉ์ผ๋ก ๋จ๊ฒจ๋์๊ณ , setting/ts ํด๋๋ฅผ front ํด๋๋ก ๋ฐ๊พผ ๋ค ๋๋จธ์ง ํด๋๋ ์ ๋ถ ์ง์๋ฒ๋ฆฌ์ธ์.
1์ผ์ฐจ
- package.json
- npm init์ผ๋ก ์์ฑ
- npm i react react-dom
- npm i typescript @types/react @types/react-dom
- ์ค์น ํ package-lock.json๊ณผ node_modules ํด๋๊ฐ ์์ฑ๋จ
- .eslintrc
- eslint ์ค์ ํ์ผ
- ์ฝ๋ ์ ๊ฒ ๋๊ตฌ, ์ง์ ์ค์ ํ๋ฉด ํ์๊ฐ ์๊ฒฌ ์ถฉ๋์ด ์์ผ๋ prettier์ ์์
- npm i -D eslint
- .prettierrc
- prettier ์ค์ ํ์ผ
- ์ ์ฅํ๋ฉด ์์์ ์ฝ๋๋ฅผ ์์ ํด์ค(์๋ํฐ ์ค์ ํ์)
- npm i -D prettier eslint-plugin-prettier eslint-config-prettier
- tsconfig.json
- ํ์ ์คํฌ๋ฆฝํธ ์ค์
- ์ธ์ด ๋ฌธ๋ฒ๊ณผ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฒฐ๊ณผ๋ฌผ์ด ์ด๋ป๊ฒ ๋์์ผํ๋์ง ์ค์ ํ๋ ํ์ผ
- lib์ ES2020, DOM(๋ธ๋ผ์ฐ์ ), module์ esnext์ฒ๋ผ ์ต์ ์ค์ ์ด์ง๋ง target์ es5๋ก IE ๋ธ๋ผ์ฐ์ ์์๋ ๋์๊ฐ ์ ์๊ฒ ๋ณํ
- strict: true๋ฅผ ์ผ๋์์ผ ํ์ ์ฒดํน์ ํด์ค์ ์๋ฏธ๊ฐ ์์.
- webpack.config.ts
- ์นํฉ ์ค์
- ts, css, json, ์ต์ ๋ฌธ๋ฒ js ํ์ผ๋ค์ ํ๋๋ก ํฉ์ณ์ค.
- npm i -D webpack @types/webpack @types/node
- entry์์ ํ์ผ์ ์ ํํ๋ฉด module์ ์ ํด์ง rules๋๋ก js๋ก ๋ณํํ์ฌ ํ๋์ ํ์ผ๋ก ํฉ์ณ์ค(output). plugins๋ ํฉ์น๋ ์ค ๋ถ๊ฐ์ ์ธ ํจ๊ณผ๋ฅผ ์ค
- ts๋ babel-loader๋ก, css๋ style-loader์ css-loader๋ฅผ ํตํด js๋ก ๋ณํ
- babel์์๋ @babel/preset-env(์ต์ ๋ฌธ๋ฒ ๋ณํ) @babel/preset-react(๋ฆฌ์กํธ jsx ๋ณํ), @babel/preset-typescript(ํ์ ์คํฌ๋ฆฝํธ ๋ณํ)
- npm i -D css-loader style-loader @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/preset-typescript
- publicPath๊ฐ /dist/๊ณ [name].js์์ [name]์ด entry์ ์ ํ๋๋ก app์ผ๋ก ๋ฐ๋์ด /dist/app.js๊ฐ ๊ฒฐ๊ณผ๋ฌผ์ด ๋จ.
- index.html ์์ฑ
- ์์ด์ฝ, ํฐํธ, ํ๋น์ฝ๊ฐ์ ๊ฒ์ ์ฌ๋์์ ๊ทธ๋๋ก ์ฌ์ฉ
- client.tsx์ ๊ฐ๋จํ tsx ์์ฑ
- #app ํ๊ทธ์ ๋ฆฌ์กํธ๊ฐ ๋ ๋๋ง๋จ.
- ./dist/app.js๋ก ์นํฉ์ด ๋ง๋ค์ด๋ธ jsํ์ผ ๋ถ๋ฌ์ด
- tsconfig-for-webpack-config.json
- webpackํ ๋ webpack.config.ts๋ฅผ ์ธ์ ๋ชปํ๋ ๋ฌธ์
- npm i cross-env
- package.json์ scripts์ build๋ฅผ cross-env TS_NODE_PROJECT="tsconfig-for-webpack-config.json" webpack
- npm run build
- index.html ์คํํด๋ณด๊ธฐ
- ์นํฉ ๋ฐ๋ธ ์๋ฒ ์ค์น
- ๊ฐ๋ฐ์ฉ ์๋ฒ์ธ devServer ์ต์ ์ถ๊ฐ(port๋ 3090, publicPath๋ /dist/๋ก)
- webpack serveํ ๋ webpack.config.ts๋ฅผ ์ธ์ ๋ชปํ๋ ๋ฌธ์
- npm i -D ts-node webpack-dev-server @types/webpack-dev-server webpack-cli
- package.json์ scripts์ dev๋ฅผ cross-env TS_NODE_PROJECT="tsconfig-for-webpack-config.json" webpack serve --env development
- npm run devํ๋ฉด localhost:3090์์ ์๋ฒ ์คํ๋จ.
- hot reloading ์ค์
- npm i -D @pmmmwh/react-refresh-webpack-plugin react-refresh
- webpack์ babel-loader ์์ ์ค์ (env) ๋ฐ plugin์ผ๋ก ์ถ๊ฐ
- fork-ts-checker-webpack-plugin
- webpack์ ts์ฒดํฌ ํ eslint์ฒดํฌ ํ ๋น๋ ์์
- ts๋ eslint๋ ๋์์ ์ฒดํฌํ๋ฉด ๋ ํจ์จ์
- ์ด ํ๋ฌ๊ทธ์ธ์ด ๋์์ ์งํํ๊ฒ ํด์ค.
- ํด๋ ๊ตฌ์กฐ ์ธํ
- ํ์ด์ง๋ค์ pages
- ํ์ด์ง๊ฐ ๊ณตํต๋๋ ํ์ layouts
- ๊ฐ๋ณ ์ปดํฌ๋ํธ๋ components
- ์ปค์คํ ํ ์ hooks, ๊ธฐํ ํจ์๋ utils
- ๊ฐ ์ปดํฌ๋ํธ๋ ์ปดํฌ๋ํธ ํด๋ ์๋ index.tsx(JSX)์ styles.tsx(์คํ์ผ๋ง)
- ts์ webpack์์ alias ์ง์
- npm i -D tsconfig-paths
- tsconfig์์ baseUrl์ paths ์ค์
- webpack์์๋ resolve์์ alias ์ค์
- ../layouts/App๊ฐ์ ๊ฒ์ @layouts/App์ผ๋ก ์ ๊ทผ ๊ฐ๋ฅ
- emotion ์ธํ
- styled components์ ๋น์ทํ์ง๋ง ์ค์ ์ด ๊ฐ๋จํจ.
- npm i @emotion/react @emotion/styled
- npm i -D @emotion/babel-plugin (์นํฉ์ babel ์ค์ ์ถ๊ฐ)
- ์คํ์ผ๋ ์ปดํฌ๋ํธ๋ก ๋ง๋ค ๋ ๋ณ์๋ฅผ ๋ง์ด ๋ง๋๋ ์ ์ด๋ฏ๋ก & ๊ฐ์ ์ ํ์ ์ ๊ทน ํ์ฉํด์ผ ๋ณ์ ์ด๋ฆ์ง๊ธฐ๋ฅผ ์ต์ํํ ์ ์์.
- @layouts/App ์์ฑ
- ๋ฆฌ์กํธ ๋ผ์ฐํฐ ์ ์ฉํ๊ธฐ
- npm i react-router react-router-dom
- npm i -D @types/react-router @types/react-router-dom
- client.tsx์์ App์ BrowserRouter๋ก ๊ฐ์ธ๊ธฐ
- @layouts/App์ Switch, Redirect, Route ๋ฃ๊ธฐ
- @loadable/component
- ๋ผ์ฐํฐ๋ฅผ ์ฝ๋์คํ๋ฆฌํ ํด์ค
- ํ์๊ฐ์ ํ์ด์ง์ ์ ๊ทผํ ์ฌ๋์ ํ์๊ฐ์ ํ์ด์ง์ ํ์ํ JS๋ง ๋ฐ์
- 3์ด ๋ฃฐ ๊ธฐ์ตํ์!
- npm i @loadable/component @types/loadable__component
- @pages/SignUp ์์ฑ
2์ผ์ฐจ
- ํ์๊ฐ์ axios๋ก ์งํ
- npm i axios
- CORS ๋ฌธ์ ๋ฅผ ํผํ๊ธฐ ์ํด์ devServer์ proxy ์ธํ
- CORS๋ ๋ธ๋ผ์ฐ์ ์์ ๋ค๋ฅธ ๋๋ฉ์ธ์ ์๋ฒ๋ก ์์ฒญ์ ๋ณด๋ผ ๋ ๋ฐ์
- ๊ฐ์ ๋๋ฉ์ธ์ ์๋ฒ๋ก ์์ฒญ์ ๋ณด๋ด๊ฑฐ๋, ์๋ฒ๋ผ๋ฆฌ ์์ฒญ์ ๋ณด๋ผ ๋๋ ๋ฐ์ํ์ง ์์
- ๋ฐ๋ผ์ ๊ฐ์ ๋๋ฉ์ธ์ธ proxy์๋ฒ๋ฅผ ๋์ CORS๋ฅผ ํผํด๊ฐ ์ ์์.
- useInput ์ปค์คํ ํ ๋ง๋ค๊ธฐ
- ์ปค์คํ ํ ์ผ๋ก ํ ๋ค๊ฐ์ ์ค๋ณต๋ ๊ฒ์ ์ ๊ฑฐํ ์ ์์
- ํ ๋ด๋ถ์ ํ ์ ์์ฑํ ์ ์๋ ์ ์ผํ ์ผ์ด์ค
- useCallback์ return ์์ ๋ค์ด์๋ ํจ์์ ๊ผญ ์ ์ฉํด์ฃผ์
- useMemo๋ return ์์ ๋ค์ด์๋ ๊ฐ์ ์ ์ฉํ์
- @pages/LogIn ์์ฑ ๋ฐ SWR
- ๋ก๊ทธ์ธ ํ ์ฌ๋์ด ํ์๊ฐ์ /๋ก๊ทธ์ธ ํ์ด์ง์ ์ ๊ทผํ๋ค๋ฉด?
- GET ์์ฒญ์ SWR๋ก ํ๋ ๊ฒ๋ ๊ด์ฐฎ์
- npm i swr
- SWR์ fetcher(axios๋ฅผ ์ฌ์ฉ)๋ฅผ ๋ฌ์์ค.
- ๋ก๊ทธ์ธํ์์ ์ฆ๋ช ํ๊ธฐ ์ํด withCredentials: true ์์ผ๋ฉด ์ ๋จ.
- @layouts/Workspace ์์ฑ
- ๋์ ๋๋ ๊ตฌ์ญ ๋จ์๋ก ์คํ์ผ๋์ปดํฌ๋ํธ๋ก ๋ง๋ค์ด๋ .
- ๊ตฌ์ญ ๋ด๋ถ์ ํ๊ทธ๋ค์ ์คํ์ผ๋์ปดํฌ๋ํธ๋ก ๋ง๋ค๋ฉด ๋ณ์๋ช ์ง์ด์ผ ํ๋ css์ ํ์๋ก ์ ํ
- ๊ทธ๋ผ๋ฐํ
- npm i gravatar @types/gravatar
- Github๊ฐ์ ์์ด์ฝ์ ๋ง๋ค ์ ์์
- typescript ์ ์
- ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณ์, ๋งค๊ฐ๋ณ์, ๋ฆฌํด๊ฐ์ ํ์ ์ ๋ถ์ฌ์ฃผ๋ฉด ๋จ.
- ๋จ์ด ํ์ดํํด๋ ๊ฒ ๋ถ์ํ๋ ๊ฒ ์ด๋ ค์
- Go to Type Definition
- ์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์์๋ ๋ค๋ฅธ ์ฌ๋์ด ๋ง๋ ts ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ @types๋ก ์์ํ๋ ๊ฒ๋ค
- @components/DMList ์์ฑ
- ํ์ฌ ์ฑ๋ ์ฐธ์ฌ์ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ
- @pages/DirectMessage ์์ฑ
- Header์ ChatList, ChatBox๋ก ๊ตฌ์ฑ
- @components/ChatBox ๋จผ์ ์์ฑ
- react-mentions ํ์ฉ
- DM์์๋ ๋ฉ์ ๊ธฐ๋ฅ์ด ์์ง๋ง Channel์์๋ ์์ ๊ฒ
- DM ๋ณด๋ด๋ณด๊ธฐ
- optimistic UI
- ๋จผ์ ํ๋ก ํธ์์ ํ์ํ๊ณ , ์๋ฒ๋ก๋ ๊ทธ ๋ค์์ ์์ฒญ๋ณด๋
- ์์ฒญ ์คํจํ๋ ์๊ฐ ํ๋ก ํธ์์ ์ ๊ฑฐํ๊ณ ์๋ฌ ๋ฉ์์ง ๋์
- ๋ณด๋ผ ๋ ์๋ฌ๊ฐ๋ ๊ฒ์ ์๋ฒ์ชฝ์์ socket ์ฐ๊ฒฐ ์ฌ๋ถ๋ฅผ ํ์ธํ๊ธฐ ๋๋ฌธ
- DM ๋ก๋ฉ์ useSWRInfinite ์ฌ์ฉ
- ๊ฒฐ๊ณผ๋ฌผ์ด 2์ฐจ์ ๋ฐฐ์ด ๊ผด๋ก ๋์ด.
- ์ฒซ ๋ฒ์งธ ์ธ์๊ฐ ์ฃผ์ ๋ฌธ์์ด์ด ์๋ ์ฃผ์๋ฅผ ๋ฆฌํดํ๋ ํจ์
- ์ด ํจ์์ ๋งค๊ฐ๋ณ์๋ก ํ์ด์ง๊ฐ ๋ค์ด์์ด์ ํ์ฌ ๋ช ํ์ด์ง์ธ์ง ์ ์ ์์.
3์ผ์ฐจ
- Workspace์ ์์ผ ์ฐ๊ฒฐํ๊ธฐ
- socket.emit์ด ํด๋ผ์ด์ธํธ์์ ์๋ฒ๋ก, socket.on์ด ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก
- DMList์ onlineList, dm ์ด๋ฒคํธ ์ฐ๊ฒฐ
- @components/ChatList ์์ฑ ๋ฐ @components/Chat ๊ตฌํ
- npm i react-custom-scrollbars @types/react-custom-scrollbars
- makeSection ๊ตฌํ
- npm i dayjs
- dayjs๋ moment๋ฅผ ๋์ฒดํจ
- ํ๋กํ์ผ๋ง ํ๋ฉด์ Chat์ memo ์ ์ฉํ๊ธฐ
- ์ธํผ๋ํธ ์คํฌ๋กค๋ง ๊ตฌํ
- @components/ChannelList ์์ฑ
- @pages/ChannelMessage ์์ฑ
- Channel Chat ๋ณด๋ด๋ณด๊ธฐ
- ๋น๋ ์ค์
- ๋น๋ ๊ฒฐ๊ณผ๋ฌผ์ธ JS์ html์ ์๋ฒ๊ฐ๋ฐ์์๊ฒ ์ ๋ฌํ๊ธฐ