Skip to content

๐Ÿงญ ๊ณตํ†ต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ ํƒ

Junsang Yu edited this page Nov 12, 2024 · 1 revision

๊ณตํ†ต

  • TypeScript
  • TypeScript ์ปดํŒŒ์ผ๋Ÿฌ(tsc vs. swc)
  • ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ € npm vs. pnpm vs. yarn
  • ESLint
  • Prettier
  • ๋””์ž์ธ + ์™€์ด์–ดํ”„๋ ˆ์ž„ ํˆด (Figma vs. Creatie)

๋ชจ๋…ธ๋ ˆํฌ? npm vs. pnpm vs. yarn?

๋ชจ๋…ธ๋ ˆํฌ

  • J025 : server์™€ client ํด๋”๋ฅผ ๋ถ„๋ฆฌํ•˜๊ณ  ๊ณตํ†ต์˜ ํŒจํ‚ค์ง€๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ npm์ด๋‚˜ yarn์˜ workspace ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด์„œ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํ•ด๊ฒฐ๋˜๋Š” ๋ฌธ์ œ๋ผ๊ณ  ๋ณด์ž…๋‹ˆ๋‹ค. ๋ชจ๋…ธ๋ ˆํฌ๋Š” ๋‹จ์ˆœํžˆ ์„œ๋ฒ„, ํด๋ผ์ด์–ธํŠธ ๊ตฌ๋ถ„์ด ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐ™์€ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ํ•œ ๋ฒˆ์— ๊ด€๋ฆฌํ•  ๋•Œ ๋„์ž…์ด ํ•„์š”ํ•œ ๊ฐœ๋…์œผ๋กœ ์ƒ๊ฐ๋ฉ๋‹ˆ๋‹ค. ๋ณดํ†ต ์šฉ๋Ÿ‰ ๋ฌธ์ œ๋‚˜ ์„ค์น˜ํ•˜๋Š”๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์„ ๊ฑฑ์ •ํ•˜๋Š”๋ฐ ์ €ํฌ ๊ทœ๋ชจ(ํ•˜๋‚˜์˜ ํ”„๋กœ๊ทธ๋žจ ๊ฐœ๋ฐœ)์—์„  ํ•„์š”์—†๋Š” ๊ฒƒ ์•„๋‹Œ์ง€?
  • J046 : ๋ชจ๋…ธ๋ ˆํฌ๋Š” ๊ทœ๋ชจ๊ฐ€ ํฐ ํšŒ์‚ฌ, ๋‹ค์ˆ˜์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•œ ๋ฒˆ์— ๊ด€๋ฆฌํ•˜๋Š” ์˜๋ฏธ๊ฐ€ ํฐ ๊ฒƒ ๊ฐ™๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ๋ฅผ ๋ชจ๋…ธ๋ ˆํฌ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์„์ง€๋Š” ์ž˜ ๋ชจ๋ฅด๊ฒ ์Œ ์—ฌ๋Ÿฌ ํ”„๋กœ์ ํŠธ์˜ ํŒจํ‚ค์ง€๋ฅผ ํ•œ ๋ฒˆ์— ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ = ๋ชจ๋…ธ๋ ˆํฌ ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ์˜ ํ”„๋ก ํŠธ์—”๋“œโ‹…๋ฐฑ์—”๋“œ ํŒจํ‚ค์ง€๋ฅผ ํ•œ ๋ฒˆ์— ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ โ‰  ๋ชจ๋…ธ๋ ˆํฌ ๋ผ๊ณ  ์ƒ๊ฐ
  • J166: ๋ชจ๋…ธ๋ ˆํฌ๋Š” ํ”„๋กœ์ ํŠธ๊ฐ„ ๊ณต์œ ๊ฐ€ ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๊ฐ€ ์žˆ์„ ๋•Œ ์“ฐ๋Š”๊ฑฐ ๊ฐ™์Œ. ์šฐ๋ฆฌ๋Š” ๊ฐ๊ฐ FE, BE ํ”„๋กœ์ ํŠธ๊ฐ€ ๊ณต์œ ํ•ด์•ผํ•˜๋Š” ํŒจํ‚ค์ง€/ํŒŒ์ผ์ด ์—†๋Š”๊ฑฐ ๊ฐ™์•„์„œ ํ•„์š”์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ณตํ†ต์œผ๋กœ eslint, prettier ๊ฐ™์€ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•  ํ•„์š”๋„ ์žˆ์–ด๋ณด์ž„
  • J290 : ๊ฐ™์€ ์ €์žฅ์†Œ์— ์žˆ๊ธฐ๋งŒ ํ•ด๋„ ๋ชจ๋…ธ๋ ˆํฌ๋ผ๊ณ  ํ•˜๋Š”๊ฐ€?
my-monorepo/
โ”œโ”€โ”€ packages/             # ๊ฐ ํŒจํ‚ค์ง€๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํด๋”
โ”‚   โ”œโ”€โ”€ client/           # ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ (์˜ˆ: React, Vue ๋“ฑ)
โ”‚   โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ””โ”€โ”€ package.json
โ”‚   โ”œโ”€โ”€ server/           # ์„œ๋ฒ„ ์ฝ”๋“œ (์˜ˆ: Express, Nest ๋“ฑ)
โ”‚   โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ””โ”€โ”€ package.json
โ”‚   โ””โ”€โ”€ shared/           # ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„์—์„œ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ
โ”‚       โ”œโ”€โ”€ src/
โ”‚       โ””โ”€โ”€ package.json
โ”œโ”€โ”€ package.json          # ๋ฃจํŠธ package.json (์›Œํฌ์ŠคํŽ˜์ด์Šค ๊ด€๋ฆฌ์™€ ์Šคํฌ๋ฆฝํŠธ ์„ค์ •)
โ””โ”€โ”€ pnpm-workspace.yaml   # pnpm ๋ชจ๋…ธ๋ ˆํฌ ์„ค์ • ํŒŒ์ผ (pnpm์„ ์‚ฌ์šฉํ•  ๋•Œ๋งŒ ํ•„์š”)

npm vs yarn vs pnpm

npm vs yarn vs pnpm

yarn

์†”์งํžˆ npm ์“ฐ๋Š”๊ฒŒ.. ๋‚ซ์ง€ ์•Š๋‚˜?

npm

  • node_modules์— ํŒŒ์ผ๋กœ ์ž‘์„ฑ

pnpm

  • node_modules์— ํ•˜๋“œ๋งํฌ๋กœ ์ž‘์„ฑ
  • ์‚ฌ์‹ค npm์ด๋ž‘ ๋‹ค๋ฅผ ๊ฑด ํฌ๊ฒŒ ์—†์Œ
  • ์–ด์ฐจํ”ผ ํฌ๊ฒŒ ์˜์กด์„ฑ์ด๋‚˜ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ํฌ๊ฒŒ ์ขŒ์ง€์šฐ์ง€ํ•  ํ”„๋กœ์ ํŠธ๋Š” ์•„๋‹Œ ๊ฒƒ ๊ฐ™์Œ

yarn berry ์žฅ์ 

https://toss.tech/article/lightning-talks-package-manager

https://toss.tech/article/node-modules-and-yarn-berry

  • PnP โ†’ node_modules ๋Œ€์‹  pnp.cjs ํŒŒ์ผ์„ ์‚ฌ์šฉ
  • Zero-install

yarn berry ๋‹จ์ 

https://devocean.sk.com/blog/techBoardDetail.do?ID=166592&boardType=techBlog

https://engineering.ab180.co/stories/yarn-to-pnpm

  • VSCode ํ˜ธํ™˜ ๋ฌธ์ œ
  • ESLint ์•ˆ ๋œ๋‹ค?
  • ๋Ÿฌ๋‹ ์ปค๋ธŒ

๊ฒฐ๋ก 

  • npm
  • workspace๋ฅผ ์‚ฌ์šฉํ•ด์„œ eslint, prettier ํŒจํ‚ค์ง€ ๊ณต์œ 

yarn์€ npm๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅธ ์ ์ด ์—†๋Š” ๊ฒƒ ๊ฐ™๊ณ , yarn berry๋Š” ๋Ÿฌ๋‹ ์ปค๋ธŒ๊ฐ€ ๋„ˆ๋ฌด ๋†’์Œ.

npm์˜ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ์ง์ ‘์ ์œผ๋กœ ๊ฒฝํ—˜ํ•œ ํŒ€์›์ด ์—†๊ณ  ๊ธฐ์กด์— ํŒ€์›๋“ค์ด ๋ชจ๋‘ ์‚ฌ์šฉํ•˜๋˜ npm์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •.

ESLint

// eslint.config.js
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  { ignores: ['dist'] },
  {
    extends: [js.configs.recommended, ...tseslint.configs.recommended],
    files: ['**/*.{ts,tsx}'],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
    },
    plugins: {
      'react-hooks': reactHooks,
      'react-refresh': reactRefresh,
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
    },
  },
);

// eslint.config.js
import js from "@eslint/js";

export default [
    js.configs.recommended,
    {
        rules: {
            "no-unused-vars": "warn"
        }
    }
];
// tsconfing.json
{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ]
}

// tsconfig.app.json
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"]
}

// tsconfig.node.json
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2023"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["vite.config.ts"]
}

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
    open: true,
  },
});

image

Prettier

๐Ÿš€ ํ”„๋กœ์ ํŠธ ๊ทœ์น™

๐Ÿš€ ํ”„๋กœ์ ํŠธ ๊ธฐํš

๐Ÿ“ฝ ๋ฐ์ผ๋ฆฌ ์Šคํฌ๋Ÿผ

๐Ÿ‘ฅ ๊ทธ๋ฃน ํšŒ๊ณ 

๐Ÿ““ ๋ฉ˜ํ† ๋ง ์ผ์ง€

๐Ÿ“† ํšŒ์˜๋ก

๐Ÿง ๊ฐœ๋ฐœ์ผ์ง€

Clone this wiki locally