2024-04-01.md

๐Ÿก

DIL: ๋ชจ๋˜ ๋ฆฌ์•กํŠธ ๋”ฅ ๋‹ค์ด๋ธŒ, 5์ฃผ์ฐจ-1

์Šคํ„ฐ๋””: ์›”๊ฐ„ CS, https://github.com/monthly-cs/2024-03-modern-react-deep-dive
์˜ค๋Š˜ ์ง„ํ–‰: ๊ฐœ์ธ๊ณต๋ถ€


DIL-week5-1_2024-04-01

| DIL ์ฃผ์ฐจ | ๋ฒ”์œ„ | ๋‚ด์šฉ | ์˜ค๋Š˜์ฐจ ์ง„๋„ | | -------- | ---- | -------------------------------------------------- | ----------- | | 5์ฃผ์ฐจ | 9์žฅ | ๋ชจ๋˜ ๋ฆฌ์•กํŠธ ๊ฐœ๋ฐœ ๋„๊ตฌ๋กœ ๊ฐœ๋ฐœ ๋ฐ ๋ฐฐํฌ ํ™˜๊ฒฝ ๊ตฌ์ถ•ํ•˜๊ธฐ | 529p~528p |

์˜ค๋Š˜ ์ฝ์€ ๋‚ด์šฉ์„ markdown์œผ๋กœ ๊ฐ„๋‹จํžˆ ๋ฉ”๋ชจ
์ฝ์€ ์‹œ๊ฐ„: 9์‹œ~10์‹œ๋ฐ˜


๋ชจ๋˜ ๋ฆฌ์•กํŠธ ๊ฐœ๋ฐœ ๋„๊ตฌ๋กœ ๊ฐœ๋ฐœ ๋ฐ ๋ฐฐํฌ ํ™˜๊ฒฝ ๊ตฌ์ถ•ํ•˜๊ธฐ

Next.js๋กœ ๋ฆฌ์•กํŠธ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ๊ตฌ์ถ•ํ•˜๊ธฐ

  • ํ•œ๋•€ํ•œ๋•€ ๋งŒ๋“ค๊ธฐ ์ฑ•ํ„ฐ
  • create-react-app์€ ์œ ์ง€๋ณด์ˆ˜๋˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฌ๋‹ค.
    • 2023๋…„ 1์›” ๋ฆฌ์•กํŠธ ํŒ€ => ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ CLI๊ฐ€ ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ๋ฆฌ์•กํŠธ ๊ธฐ๋ฐ˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ์•ˆํ•˜๋Š” ๋Ÿฐ์ฒ˜ ํ˜•ํƒœ๋กœ ๋ณ€๊ฒฝ๋  ๊ฒƒ์ด๋ผ ๋ฐํž˜

create-next-app ์—†์ด ๊ตฌ์ถ•ํ•˜๊ธฐ

  • tsconfig.json
{
  "$schema": "https://json.schemastore.org/tsconfig", // ์ž๋™์™„์„ฑ
  "compilerOptions": {
    // "ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ปดํŒŒ์ผํ•  ๋•Œ" ์‚ฌ์šฉํ•˜๋Š” ์˜ต์…˜

    "target": "ES5",
    // <target: ๋ณ€ํ™˜>
    // ๋ณ€ํ™˜์„ ๋ชฉํ‘œ๋กœ ํ•˜๋Š” ์–ธ์–ด ๋ฒ„์ „ (ํด๋ฆฌํ•„๊นŒ์ง€๋Š” ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค.)

    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    /* <lib: ๋ช…์„ธ>
     * - es5 ์ง€์› ๋ชฉํ‘œ์ผ ๋•Œ:
     *   => Promise, Map ๊ฐ์ฒด๋ฅผ ํด๋ฆฌํ•„ํ•ด์„œ ์ค€๋น„ ํ–ˆ์–ด๋„ ์กด์žฌ๋ฅผ ๋ชจ๋ฆ„
     *   => esnext๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์‹ ๊ทœ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ API ์ •๋ณด๋ฅผ ํ™•์ธ
     *   => ์—๋Ÿฌ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ฒŒ ํ•˜๊ธฐ
     * - DOM:
     *   - ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ™˜๊ฒฝ์—์„œ window, document ๋“ฑ ๋ธŒ๋ผ์šฐ์ € API ๋ช…์„ธ ์‚ฌ์šฉ
     */

    "allowJs": true,
    // ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋„ ์ปดํŒŒ์ผ ํ•  ์ง€ -> js์™€ ts๊ฐ€ ํ˜ผ์žฌ๋œ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•œ๋‹ค ex) TS ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

    "skipLibCheck": true,
    // ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” d.ts(ํƒ€์ž… ํŒŒ์ผ) ๊ฒ€์‚ฌ ์—ฌ๋ถ€
    // ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ๊ธธ์–ด์ง€๋ฏ€๋กœ ์ผ๋ฐ˜์ ์œผ๋กœ ๊บผ๋†“๋Š” ๊ฒฝ์šฐ ๋งŽ์Œ

    "strict": true,
    /**
     * <ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ์ปดํŒŒ์ผ๋Ÿฌ ์—„๊ฒฉ๋ชจ๋“œ>
     * - alwaysStrict: true
     *   - ๋ชจ๋“  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์— "use strict;" ์ถ”๊ฐ€
     * - strictNullCheck: true
     *   - ์—„๊ฒฉํ•œ ๋„ ๊ฒ€์‚ฌ: null๊ณผ undefined ๊ตฌ๋ถ„ (๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•˜์ž1)
     * - strictBindCallApply: true
     *   - call, bind, apply์— ์ •ํ™•ํ•œ ์ธ์ˆ˜ ์ˆ˜ ์š”์ฒญ (๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•˜์ž2)
     * - strictFunctionTypes: true
     *   - ํ•จ์ˆ˜ ํƒ€์ž…์— ๋Œ€ํ•œ ์—„๊ฒฉํ•จ~ (์ผœ๋†“์ž~)
     * - strictPropertyInitialization: true
     *   - ํด๋ž˜์Šค ๋ƒ…์˜ ํ”„๋กœํผํ‹ฐ์— ๊ฐ’ ํ• ๋‹น ํƒ€์ž… ์—„๊ฒฉํ•˜๊ฒŒ
     * - noImplicitAny: true
     *   - ํƒ€์ž… ๋ช…์‹œํ•˜์ง€ ์•Š์€ ๋ณ€์ˆ˜์— ์—๋Ÿฌ, false๋ฉด? any ํ• ๋‹น๋จ
     * - noImplicitThis: true
     *   - this๋ฅผ ์ถ”๋ก ํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์—์„œ ์—๋Ÿฌ, false๋ฉด? any ํ• ๋‹น๋จ
     * - useUnknownInCatchVariable: true
     *   - catch๋กœ ์žก์€ ๊ตฌ๋ฌธ => any ๋Œ€์‹  unknownํ• ๋‹น(4.0๋ฒ„์ „ ์ดํ›„), ํƒ€์ž… ๊ฐ€๋“œ ์‚ฌ์šฉ
     */

    "forceConsistentCasingInFileNames": true,
    // ํŒŒ์ผ ์ด๋ฆ„ ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ ๊ฐ•์ œ

    "noEmit": true,
    // ์ปดํŒŒ์ผ ํ•˜์ง€ ์•Š๊ณ , ํƒ€์ž… ์ฒดํฌ๋งŒ ํ•œ๋‹ค
    // ์™œ? Next.js๋Š” swc๊ฐ€ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ์ปดํŒŒ์ผํ•˜๋ฏ€๋กœ, TS๊ฐ€ ์ปดํŒŒ์ผํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

    "esModuleInterop": true,
    // CommonJS ๋ฐฉ์‹์œผ๋กœ ๋ณด๋‚ธ ๋ชจ๋“ˆ์„ ES ๋ชจ๋“ˆ import๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ํ•จ

    "module": "ESNext",
    // ๋ชจ๋“ˆ ์‹œ์Šคํ…œ ์„ค์ •: commonjs(require), esnext(import)

    "moduleResolution": "Node",
    // ๋ชจ๋“ˆ ํ•ด์„ ๋ฐฉ์‹: node(node_modules ๊ธฐ์ค€), classic(tsconfig.json ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ธฐ์ค€)

    "resolveJsonModule": true,
    // JSON ํŒŒ์ผ import (allowJS ์˜ต์…˜์ด ์ž๋™์œผ๋กœ ์ผœ์ง„๋‹ค..!)

    "isolatedModules": true,
    // import๋‚˜ export๊ฐ€ ์—†๋‹ค๋ฉด ๋‹จ์ˆœ ์Šคํฌ๋ฆฝํŠธ๋กœ ์ธ์‹ - ๋ง‰์Œ
    // ์™œ? ๋ชจ๋“ˆ ์‹œ์Šคํ…œ๊ณผ ์—ฐ๊ณ„๋˜์ง€ ์•Š๊ณ  ๋‹จ๋…์œผ๋กœ ์žˆ๋Š” ํŒŒ์ผ์˜ ์ƒ์„ฑ์„ ๋ง‰๊ธฐ ์œ„ํ•จ

    "jsx": "preserve",
    /*
     * <JSX ์ปดํŒŒ์ผ ์„ค์ •>
     * - react: React.createElement() ๊ธฐ๋ณธ๊ฐ’, ~๋ฆฌ์•กํŠธ 16๊นŒ์ง€ ๊ธฐ๋ณธ ๋ณ€ํ™˜ ๋ฐฉ์‹
     * - react-jsx: react/jsx-runtime ๋ฆฌ์•กํŠธ 17~
     * - react-jsxdev: ๋””๋ฒ„๊น… ์ •๋ณด ์ถ”๊ฐ€
     * - preserve: no ๋ณ€ํ™˜
     * - react-native: no ๋ณ€ํ™˜
     */

    "incremental": true,
    // .tsbuildinfo ํŒŒ์ผ์„ ๋””์Šคํฌ์— ์ €์žฅํ•œ๋‹ค(๋งˆ์ง€๋ง‰ ์ปดํŒŒ์ผ)
    // ๊ฐ€์žฅ ๋น„์šฉ์ด ์ ๊ฒŒ ๋“œ๋Š” ๋ฐฉ์‹์œผ๋กœ ์ปดํŒŒ์ผํ•ด ์†๋„ ์—…

    "baseUrl": "src",
    // ๋ชจ๋“ˆ์„ ์ฐพ์„ ๋•Œ ๊ธฐ์ค€ โœ‹

    "paths": {
      // ๊ฒฝ๋กœ ๋ณ„์นญ
      "๐ŸŸpages/*": ["pages/*"],
      "๐ŸŸhooks/*": ["hooks/*"],
      "๐ŸŸtypes/*": ["types/*"],
      "๐ŸŸcomponents/*": ["components/*"],
      "๐ŸŸutils/*": ["utils/*"]
    }
  },

  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  // ํƒ€์ž… ์Šคํฌ๋ฆฝํŠธ ์ปดํŒŒ์ผ ๋Œ€์ƒ์— ํฌํ•จ์‹œํ‚ฌ ํŒŒ์ผ ๋ชฉ๋ก

  "exclude": ["node_modules"]
  // ํƒ€์ž… ์Šคํฌ๋ฆฝํŠธ ์ปดํŒŒ์ผ ๋Œ€์ƒ์—์„œ ์ œ์™ธ์‹œํ‚ฌ ํŒŒ์ผ ๋ชฉ๋ก
}
  • ํƒ€์ž…์„ ์—„๊ฒฉํ•˜๊ฒŒ? -> yes
  • strict node๋Š”? ํƒ€์ž…์„ ์—„๊ฒฉํ•˜๊ฒŒ ์ง€ํ‚ค๋Š” ๊ฒƒ์„ ๋„์™€์ฃผ๊ณ , ํƒ€์ž… ์‹œ์Šคํ…œ์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋™๋ฌด์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์•„๋‹ˆ๋ฉด ์ผœ๋‘๊ธฐ
  • ๊ฒฝ๋กœ ๋ณ„์นญ์— @๋ฅผ ์•ˆ ์“ฐ๋Š”๊ฒŒ... ์ข‹๋‹ค?!
    • ์Šค์ฝ”ํ”„ ํŒจํ‚ค์ง€์— ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋„ค์ด๋ฐ์— ๋”ฐ๋ผ ์ถฉ๋Œํ•  ์—ฌ์ง€๊ฐ€ ์žˆ๋‹ค <- ๋‚ฉ๋“ํ•จ
    • ๊ธฐ์กด ํ”„๋กœ์ ํŠธ๋Š” ์–ด๋–ป๊ฒŒ ํ•˜๋Š๋ƒ

"esModuleInterop": true

  • CommonJS ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์„ฑ๋œ ๋ชจ๋“ˆ์„ ES ๋ชจ๋“ˆ ํ˜•์‹์œผ๋กœ importํ•˜๋Š” ๊ฒƒ์ด ์šฉ์ดํ•ด์ง

  • ๋ชจ๋“ˆ ์‹œ์Šคํ…œ

    • CommonJS๋Š” Node.js์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“ˆ ์‹œ์Šคํ…œ
    • ES ๋ชจ๋“ˆ์€ ECMAScript ํ‘œ์ค€์— ์ •์˜๋œ ๋ชจ๋“ˆ ์‹œ์Šคํ…œ
  • CommonJS ํƒ€์ž… ๋ชจ๋“ˆ๊ณผ esModuleInterop ์˜ˆ์‹œ

    // exports
    module.exports = {
      add: (a, b) => a + b,
      subtract: (a, b) => a - b,
    };
    
    // "esModuleInterop": false
    import * as math from "./math";
    
    console.log(math.add(5, 3)); // 8
    
    // "esModuleInterop": true
    import math, { add, subtract } from "./math";
    
    console.log(math.add(5, 3)); // 8
    console.log(add(5, 3)); // 8
    

"jsx" ์ปดํŒŒ์ผ ์„ค์ •

export const Shrimp = () => <span>๐Ÿฆ</span>;
  • react: React.createElement() ๊ธฐ๋ณธ๊ฐ’, ~๋ฆฌ์•กํŠธ 16๊นŒ์ง€ ๊ธฐ๋ณธ ๋ณ€ํ™˜ ๋ฐฉ์‹
    export const Shrimp = () => React.createElement("span", null, "๐Ÿฆ");
    
  • react-jsx: react/jsx-runtime ๋ฆฌ์•กํŠธ 17~
    import { jsx as _jsx } from "react/jsx-runtime";
    export const Shrimp = () => _jsx("span", { children: "๐Ÿฆ" });
    
  • react-jsxdev: ๋””๋ฒ„๊น… ์ •๋ณด ์ถ”๊ฐ€
    import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
    const _jsxFileName = "file:///input.tsx";
    export const Shrimp = () =>
      _jsxDev(
        "span",
        { children: "๐Ÿฆ" },
        void 0,
        false,
        {
          fileName: _jsxFileName,
          lineNumber: 1,
          columnNumber: 27,
        },
        this
      );
    
  • preserve: no ๋ณ€ํ™˜, swc๊ฐ€ JSX๋ฅผ ๋ณ€ํ™˜ํ•˜๋ฏ€๋กœ Next.js์—์„œ preserve
    export const Shrimp = () => <span>๐Ÿฆ</span>;
    
  • react-native: no ๋ณ€ํ™˜ (RN์šฉ)
    export const Shrimp = () => <span>๐Ÿฆ</span>;