#
๋ชจ๋ ์ ์ฒด ๋ชฉ๋ก ๋ณด๊ธฐpip list
#
์ ๋ฐ์ดํธ๊ฐ ํ์ํ ํญ๋ชฉ ๋ณด๊ธฐpip list --outdated
#
์ ๋ฐ์ดํธ๊ฐ ํ์ํ์ง ์์ ์ต์ ํญ๋ชฉ ๋ณด๊ธฐpip list --uptodate
#
PIP ์ ๋ฐ์ดํธํ๊ธฐpip install --upgrade pip
scp [์ต์
] [๊ณ์ ๋ช
]@[์๊ฒฉ IP ์ฃผ์]:[์๋ณธ ๊ฒฝ๋ก] [์ ์ก ๋ฐ์ ์์น]
scp abc@111.222.333.444:/home/abc/index.html /home/me/
scp [์ต์
] [์๋ณธ ๊ฒฝ๋ก ๋ฐ ํ์ผ] [๊ณ์ ๋ช
]@[์๊ฒฉ IP ์ฃผ์]:[์ ์กํ ๊ฒฝ๋ก]
scp /home/me/index.html abc@111.222.333.444:/home/abc/
chown -R username.username folder/
๋ช ๋ น์ด๋ก ํด๋น ํด๋์ ์์ ์๋ฅผ username์ผ๋ก ๋ฐ๊ฟ ์ ์๋ค.
[๊ธฐ๋ณธ] ๋ฆฌ๋ ์ค์ ํผ๋ฏธ์ (๊ถํ)์ ์กฐ์ ํ๊ธฐ (chmod, chown)
MacOS + zsh
Google Drive File Stream (๋ฌด์ ํ ์ฉ๋)
MacOS ์ฉ๋ ๋ถ์กฑ
์ฐ์ ์คํฌ๋ฆฐ์ท์ด๋ ๋์์ ๋ณด๊ด
ํ๋ฃจ๋ง๋ค ์คํฌ๋ฆฐ์ท ํด๋์ ํ์ผ์ด ์์ด๋ ๊ฒ ๋ฐฉ์ง
Dock์์ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๊ฒ ๊ด๋ฆฌ
screenshots ํด๋์ ํ์ผ์ด ์์ผ๋ฉด
๋ชจ๋ prev-screenshots๋ก ๋ณต์ฌํ๋ค.
screenshots ํด๋์ ํ์ผ์ ๋ชจ๋ ์ง์ด๋ค (์ง์ธ ๋ confirm [y/n] ๋ฉ์์ง ๋์ฐ์ง์๊ฒ ์ต์ ์ค์ )
์์ผ๋ฉด ์์ฝ
~/scripts/mv_screenshots.sh
#!/bin/zsh
target=/Volumes/GoogleDrive/๋ด\ ๋๋ผ์ด๋ธ/์ด๋ฏธ์ง/screenshotsarchive=/Volumes/GoogleDrive/๋ด\ ๋๋ผ์ด๋ธ/์ด๋ฏธ์ง/prev-screenshots
if find "$target" -mindepth 1 -print -quit 2>/dev/null | grep -q .; then setopt localoptions rmstarsilent cp -R "$target" "$archive/`date +\%Y-\%m-\%d`" rm "$target"/*else echo "Target '$target' is empty"fi
Bash checking if folder has contents
Why does rm -f ask me for confirmation on zsh?
crontab -e
30 23 * * * zsh ~/scripts/mv_screenshots.sh >> ~/log/job_`date +\%Y-\%m-\%d`.log 2>&1
์์ ์ค์ผ์ฅด๋ฌ ํฌ๋ก (Cron) ๊ฐ๋จ ์ฌ์ฉ๋ฒ
Crontab.guru - The cron schedule expression editor
๊ธฐ๋ณธ์ ์ธ Merge ๋ฐฉ๋ฒ์ผ๋ก ํ๋์ ๋ธ๋์น์ ๋ณ๊ฒฝ ์ด๋ ฅ ์ ์ฒด๋ฅผ ํฉ์น๋ ๋ฐฉ๋ฒ์ด๋ค.
๋ ๋ณ๊ฒฝ ์ด๋ ฅ์ ๋ณํฉํ Merge commit์ด ์๋ก ์์ฑ๋๋ค.
๋ธ๋์น ์์ ๋ชจ๋ ์ปค๋ฐ์ ํ๋๋ก ๋ณํฉํ ๋ด์ฉ์ ๋ค๋ฅธ ๋ธ๋์น์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ด๋ค.
PR์ ์๋ commit log๋ค์ ํ ๊ฐ์ ์ปค๋ฐ์ผ๋ก ์ถ๋ ค์ main ๋ธ๋์น์ ๋ณํฉํ ์ ์๊ธฐ ๋๋ฌธ์, 1 PR = 1 commit ์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ค.
[Git] Merge ์ดํดํ๊ธฐ (Merge / Squash and Merge / Rebase and Merge)
6. Github์ผ๋ก ํ์ ํ๋ ๋ฒ
GitHub์ Merge, Squash and Merge, Rebase and Merge ์ ํํ ์ดํดํ๊ธฐ : TOAST Meetup
๋ธ๋์น ์์ ๋ชจ๋ commit๋ค์ ํฉ์น์ง ์๊ณ main ๋ธ๋์น์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ด๋ค.
Github์์๋ PR์ ๋ํ ๋จธ์ง ๋ฐฉ๋ฒ์ ๋ค์ ์ฌ์ง๊ณผ ๊ฐ์ด ์ ๊ณตํ๋ค.
Squash and merge ๊ธฐ๋ฅ์ ์ฌ์ฉํ ๊ฒฝ์ฐ, Merge commit์ด ๋ฐ๋ก ์์ฑ๋์ง ์๊ณ , PR ํ์ดํ์ ์ปค๋ฐ ์ ๋ชฉ์ผ๋ก ํ๊ณ , ๋ธ๋์น์ commit log๋ค์ด ์ปค๋ฐ ๋ด์ฉ์ผ๋ก ์์ฑ๋๋ค.
๋ฐ๋ฉด, GitLab์์๋ MR์ ๋จธ์งํ ๋, Squash commits์ ์ต์ ์ ์ฒดํฌํ ์ ์๋๋ก ํ๋๋ฐ, GitHub๊ณผ ๋ฌ๋ฆฌ ๊ธฐ๋ณธ์ ์ผ๋ก Merge commit์ด ์์ฑ๋๋๋ก ์ค์ ๋์ด ์๋ค.
Merge commit์ ์์ฑํ์ง ์๊ธฐ ์ํด์๋ Fast-forward merge๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
Fast-Forward Merge๋ฅผ ์ฌ์ฉํ๊ณ Squash commits ์ต์ ์ ์ฒดํฌํ์ง ์์ผ๋ฉด, Rebase and Merge ์ฒ๋ผ ๋์ํ๋ค.
Fast-Forward Merge๋ฅผ ์ฌ์ฉํ๊ณ Squash commits ์ต์ ์ ์ฒดํฌํ๋ฉด Squash and Merge ์ฒ๋ผ ๋์ํ๋ค.
ํ์ง๋ง GitHub์์ ์๋์ ์ผ๋ก ์ปค๋ฐ ๋ฉ์์ง body์ ๋ธ๋์น์ ์ปค๋ฐ ๋ก๊ทธ๋ฅผ ๊ธฐ๋กํด์ฃผ๋๋ฐ๋ฉด, GitLab์์๋ ์ปค๋ฐ ๋ก๊ทธ๋ฅผ ๊ธฐ๋กํด์ฃผ์ง ์๋๋ค. Merge Request์ ๋ด์ฉ์ด ์๋ค๋ฉด์ด ๋ด์ฉ์ ๋ด์ ์ ์๊ณ , Modify commit message ๋ฒํผ์ ์ฌ์ฉํ์ฌ ์ง์ ์์ ํ๋ ๊ฒ๋๊ฐ๋ฅํ๋ค.
โ ๋์์ธ ์์คํ ์ ๊ณ์ ์งํํ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๊ตฌ์ฑ ์์ ๋ชจ์์ด๊ณ , ์ผ๊ด์ฑ๊ณผ ์๋๋ฅผ ๋ณด์ฅํ๋ ๊ท์น์ ๋ฐ๋ฅด๋ ๋ชจ๋ ์ ํ์ ๊ฐ๋ฐํ๊ธฐ ์ํ ๋จ์ผ ์ง์ค ๊ณต๊ธ์(SSOT)์ด๋ค.
.gitignore
, package.json
์์ฑnpx -p @storybook/cli sb init --type react
yarn storybook
@storybook/react
๊ฐ react
, react-dom
์ peer-dependency๋ก ๊ฐ์ง๋ฏ๋ก react, react-dom ์ ์ค์นํด์ผ ์คํํ ์ ์๋ค. ์ค์นํ์ง ์์ผ๋ฉด ๋ค์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
Error: Cannot find module 'react-dom/package.json'
ํ์ง๋ง, dependency ์ ์ง์ ์ถ๊ฐํ๋ฉด, ๊ฐ๋ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ ์ ์ ๊ฐ react
, react-dom
์ญ์ ์ค์น ๋ฐ๊ฒ ๋๋ค. (๊ฒ๋ค๊ฐ ์ ํด์ง ๋ฒ์ ์ผ๋ก)
๋ฐ๋ผ์ ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์์ฑํ๋ ์์ฑ์ ์ ์ฅ์์๋ storybook์ ์คํํ๋ ๊ฐ๋ฐ ์์๋ง ์ด ์์กด์ฑ์ด ํ์ํ๋ฏ๋ก devDependency์ ๋ช ์ํด์ผํ๋ค.
๋ํ, ์ด ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ์ฌ์ฉ์ ์
์ฅ์์๋ react
, react-dom
๊ณผ ํจ๊ป ์ฌ์ฉํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ฐ๋ผ์ peerDependency์๋ ๋ช
์ํด์ผํ๋ค.
peerDependency๋ ์ด ์์กด์ฑ๊ณผ ํจ๊ป ์ฌ์ฉํด์ผ ํ๋ค๋ ๋ป์ด๊ณ , ์ ์ ๊ฐ ์ง์ ์ค์น ํด์ผํ๊ธฐ ๋๋ฌธ์ด๋ค.
devDependency๋ ํ๋ก์ ํธ์ ๋ก์ปฌ์๋ง ์ค์น๋๊ณ ๋ฐฐํฌ์์๋ ์ ์ ๊ฐ ๋ค์ด๋ก๋ํ์ง ์๊ธฐ๋๋ฌธ์ peerDependency์ devDependency์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ ์ถ๊ฐํด๋ ๋ฌด๋ฐฉํ๋ค.
yarn add -D react react-dom
// package.json"peerDependencies": { "react": "17.0.1", "react-dom": "17.0.1", "styled-components": "5.2.1"}
Duplicate same dependency in package.json devDependencies and peerDependencies?
typescript, react-docgen-typescript-loader ์ค์น
yarn add -D typescript react-docgen-typescript-loader
stories
typescript ๋ฒ์ ์ผ๋ก ๋ณ๊ฒฝ
create-react-app typescript ํ ํ๋ฆฟ์ sb init ์ผ๋ก ์์ฑํ ts ๋ฒ์ stories๋ก ํ ์คํธ
.storybook/main.js
๋ณ๊ฒฝ
module.exports = { stories: [ '../stories/**/*.stories.mdx', '../stories/**/*.stories.@(js|jsx|ts|tsx)', ], addons: ['@storybook/addon-links', '@storybook/addon-essentials'], typescript: { check: false, checkOptions: {}, reactDocgen: 'react-docgen-typescript', reactDocgenTypescriptOptions: { shouldExtractLiteralValuesFromEnum: true, propFilter: (prop) => prop.parent ? !/node_modules/.test(prop.parent.fileName) : true, }, },};
tsconfig.json
์ถ๊ฐ
{ "compilerOptions": { "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" }, "include": ["stories"]}
โ ์นํฉ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ ๋ฒ๋ค๋ฌ๋ผ๋ฉด, ๋กค์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ํ ๋ฒ๋ค๋ฌ๋ค.
Webpack and Rollup: the same but different
"devDependencies": { "babel-preset-react-app": "10.0.0", // create-react-app์์ ์ฌ์ฉํ๋ babel ์ค์ "rollup": "2.35.1", "rollup-plugin-babel": "4.4.0", // babel ์ฌ์ฉ์ ์ํ ํ๋ก๊ทธ์ธ "rollup-plugin-cleaner": "1.0.0", // build ์ ์ dist ํด๋ ์ญ์ "rollup-plugin-commonjs": "10.1.0", // CommonJS์ ๋ชจ๋ ์ฝ๋๋ฅผ ES6๋ก ๋ณํํ์ฌ ๊ฒฐ๊ณผ๋ฌผ์ ํฌํจ "rollup-plugin-node-resolve": "5.2.0", // ์จ๋ํํฐ ๋ชจ๋์ ์ฌ์ฉํ๊ธฐ์ํ ์ฉ๋ "rollup-plugin-peer-deps-external": "2.2.4", // peerDependencies๋ฅผ ๋ฒ๋ค๋ง๋ ๊ฒฐ๊ณผ์ ํฌํจํ์ง ์์}
rollup.config.js
import commonjs from 'rollup-plugin-commonjs';import cleaner from 'rollup-plugin-cleaner';import resolve from 'rollup-plugin-node-resolve';import babel from 'rollup-plugin-babel';import external from 'rollup-plugin-peer-deps-external';import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import pkg from './package.json';
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
process.env.BABEL_ENV = 'production';
export default { input: './src/index.ts', plugins: [ cleaner({targets: ['./dist/']}), peerDepsExternal(), resolve({extensions}), commonjs({ include: 'node_modules/**', }), babel({ extensions, include: ['src/**/*'], presets: [['react-app', {flow: false, typescript: true}]], runtimeHelpers: true, }), ], output: [ { file: pkg.module, format: 'es', }, ],};
declaration์ด๋, ์ปดํฌ๋ํธ๋ค์์ ์ฌ์ฉํ๊ณ ์๋ ํ์ ์ ๋ณด๋ค์ ์ง๋๊ณ ์๋ ํ์ผ.
์ด๋ ๋ค์ ๋ช ๋ น์ด๋ก ์์ฑ์ ํ ์ ์๋ค.
tsc --emitDeclarationOnly
์ด ๋ช ๋ น์ด๋ฅผ ์คํํ๊ธฐ ์ ์ tsconfig.json ์ ์์ ํด์ฃผ์ด์ผ ํ๋ค.
{ "compilerOptions": { "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "jsx": "react", "declaration": true, "declarationDir": "dist/types" }, "include": ["src"], "exclude": ["**/*.stories.tsx"]}
declaration
ย ๊ฐ์ย true
ย ,ย declarationDir
ย ๊ฒฝ๋ก๋ฅผย "dist/types"
ย ๋ก,
allowJs: ์๋ฐ์คํฌ๋ฆฝํธ์ ํผ์ฉ์ ํ๊ณ ์๋ค๋ฉด declaration ํ์ผ์ ๋ง๋ค์ง ๋ชปํ๋ฏ๋ก์ ๊ฑฐ.
noEmit: ๊ฒฐ๊ณผ๋ฌผ์ ๋ง๋ค์ง ์๋๋ค๋ ์ต์ ์ผ๋ก ์ ๊ฑฐ.
isolatedModules: ์๋ฌด ๊ฐ๋ ๋ด๋ณด๋ด์ง ์๋ ํ์ผ์ ๋ฐฉ์งํ๋ ์ต์ . ์ ๊ฑฐ
stories.tsx
ย ํ์ฅ์๋ ๋ชจ๋ ๋ฌด์ํ๋๋กย exclude
ย ์ต์
์ ์ค์
package.json์๋ Build ์ปค๋งจ๋๋ฅผ ์ถ๊ฐํ๋ค.
"build": "rollup -c && tsc --emitDeclarationOnly",
package.json์์ module, types, files ๋ฅผ ์ถ๊ฐํ๋ค. name์ scope๋ฅผ ์ฌ์ฉํ๋ค.
{ "name": "@younho9/design-system", "module": "dist/index.js", "types": "dist/types/index.d.ts", "files": ["/dist"]}
๋ฐฐํฌ ๋ช ๋ น์ด
# npm publishnpm publish --access public # scope๋ฅผ ์ฌ์ฉํ ๋
Do you think your component library is your design system? Think again
TypeScript์ Storybook์ ์ฌ์ฉํ ๋ฆฌ์กํธ ๋์์ธ ์์คํ ๊ตฌ์ถํ๊ธฐ
How to create a react component library with TypeScript, rollup.js and Storybook
Building a Design System Package With Storybook, TypeScript, and React in 15 Minutes