πŸ”΅ 레벨둜그의 νƒ€μž…μŠ€ν¬λ¦½νŠΈ

thumb_hyeokΒ·2022λ…„ 10μ›” 2일
0

πŸ”₯ WoowaCourse

λͺ©λ‘ 보기
4/10
post-thumbnail

πŸš€ νƒ€μž…μŠ€ν¬λ¦½νŠΈ

μ–Όλ§ˆ 전에, ν”„λ‘œμ νŠΈμ—μ„œ μ‚¬μš©ν•˜λŠ” νƒ€μž…κ³Ό νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ½”λ“œμ˜ μ΄μœ μ™€ 기쀀에 λŒ€ν•΄μ„œ μ •λ¦¬ν•˜κ³  λ°œν‘œκΉŒμ§€ ν•˜λŠ” μ‹œκ°„μ΄ μžˆμ—ˆλ‹€. 이번 글은 κ·Έ λ•Œ μ •λ¦¬λœ 레벨둜그(λ‚˜μ˜ νŒ€ ν”„λ‘œμ νŠΈ)의 νƒ€μž…μŠ€ν¬λ¦½νŠΈ 기쀀에 λŒ€ν•΄ 적어보겠닀.

이 글을 적은 μ΄μœ λŠ” 곧 μžˆμ„ 6μ°¨ 데λͺ¨μ—μ„œ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ˜ μ—¬λŸ¬ 기쀀을 λ°œν‘œν•΄μ•Όν•˜κΈ° λ•Œλ¬Έμ— μ§€κΈˆκ³Ό κ·Έ λ•Œ μƒˆλ‘­κ²Œ μ„€μ •λœ 뢀뢄을 비ꡐ해보기 μœ„ν•¨μ΄λ‹€!

🌝 Component Typing With Children

λ ˆλ²¨λ‘œκ·Έμ—μ„œλŠ” children propsλ₯Ό JSX.Element 둜 νƒ€μž…μ„ μ§€μ •ν•˜κ³ μžˆλ‹€. μ΄λ ‡κ²Œ μ§€μ •ν•œ μ΄μœ λŠ” JSX.Element , ReactNode , ReactElement μ€‘μ—μ„œ κ°€μž₯ 쒁은 νƒ€μž…μ΄μ—¬μ„œ μ‚¬μš©ν–ˆλ‹€.

  • ReactNodeλŠ” λ¦¬μ•‘νŠΈκ°€ λ Œλ”λ§ν•  수 μžˆλŠ” λͺ¨λ“  것을 ν¬ν•¨ν•œλ‹€.
  • ReactElement 및 JSX.ElementλŠ” λͺ¨λ‘ 직접 JSX νŠΈλžœμŠ€νŒŒμΌλ§μ„ 거친 κ²°κ³Όμ΄κ±°λ‚˜, React.createElementλ₯Ό ν˜ΈμΆœν•œ 결과이닀.

ReactElementλŠ” typeκ³Ό propsκ°€ μžˆλŠ” 객체이고, JSX.ElementλŠ” type, propsκ°€ λͺ¨λ‘ any인 ReactElement이닀. JSX에 λŒ€ν•œ κ΅¬ν˜„μ€ 라이브러리 λ³„λ‘œ μ„ΈλΆ€μ μœΌλ‘œ λ‹€λ₯Ό 수 μžˆλ‹€. μ•„λž˜ 사진을 톡해 μ„Έ 가지λ₯Ό λΉ„κ΅ν•΄λ³΄μž.

ReactNode

ReactElement

JSX.Element


🌚 Component Typing Without Children

PropsWithChildren

μœ„μ˜ Component Typing With Children μ—μ„œ PropsWithChildren νƒ€μž…μ„ ν™œμš©ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ—, 여기도 children 만 propsμ—μ„œ 제거된 λ™μΌν•œ ν˜•νƒœμ˜ νƒ€μž…μ„ 각각의 μ»΄ν¬λ„ŒνŠΈμ˜ λ§€κ°œλ³€μˆ˜ νƒ€μž…μœΌλ‘œ Interface λ₯Ό 톡해 μž‘μ„±ν•΄ μ‚¬μš©ν•œλ‹€.

Type alias vs Interface

λͺ¨λ“  객체의 νƒ€μž…μ„ 지정할 λ•Œ Interface λ₯Ό μ‚¬μš©ν–ˆκ³ , 거의 λͺ¨λ“  νƒ€μž…μ΄ Interface λ₯Ό 톡해 μž‘μ„±λ˜κ³  μžˆμ§€λ§Œ, 가끔 ν•¨μˆ˜λ‚˜ λ³€μˆ˜μ˜ νƒ€μž…μ„ 지정할 λ•ŒλŠ” Type 별칭을 μ‚¬μš©ν•΄ μž‘μ„±ν•œλ‹€.

Event Type

λ ˆλ²¨λ‘œκ·Έμ—μ„œ μ‚¬μš©λ˜κ³  μžˆλŠ” 이벀트 νƒ€μž…λ“€μ€ μ•„λž˜μ™€ κ°™λ‹€.

React.SyntheticEvent<EventTarget>
React.FormEvent<HTMLFormElement>
React.MouseEvent<HTMLElement>
React.MouseEvent<HTMLButtonElement>
React.ChangeEvent<HTMLInputElement>
FocusEvent

μ΄λŸ¬ν•œ νƒ€μž…λ“€μ€ 일일이 찾아보고 μž‘μ„±ν•˜μ§€λŠ” μ•Šμ•˜κ³ , VSCode μ—μ„œ μ œκ³΅ν•˜λŠ” νƒ€μž… 섀정에 도움을 λ°›μ•„ μž‘μ„±ν–ˆμŠ΅λ‹ˆλ‹€. ν˜„μž¬λŠ” 직접 이벀트 객체λ₯Ό μ‚¬μš©ν•˜λŠ” ν•Έλ“€λŸ¬μ—λ§Œ 이벀트 νƒ€μž…μ„ 달아쀬닀.


βš“ Webpack Config with Loader

λΉŒλ“œ ν™˜κ²½μ— λ”°λΌμ„œ Webpack Config κ°€ λ‹€λ₯΄κ²Œ μ„€μ •λ˜μ–΄ μžˆλŠ”λ°, λ‹€λ₯Έ μš”μ†Œλ“€μ€ λͺ¨λ‘ λ°°μ œν•˜κ³  Loader λ₯Ό μ€‘μ‹¬μœΌλ‘œ 차이점과 μ„€μ •μ˜ 이유λ₯Ό 적어보겠닀.

local

local λΉŒλ“œμ—μ„œλŠ” babel-loader λ₯Ό μ‚¬μš©ν•˜μ˜€λŠ”λ°, λ‘œμ»¬μ—μ„œλŠ” 변경점에 λŒ€ν•œ 화면변경이 λΉ λ₯Έ 것이 κ°œλ°œν•  λ•Œ νŽΈν•˜κΈ° λ•Œλ¬Έμ— ts-loader 보닀 λΉ λ₯Έ babel-loader λ₯Ό μ‚¬μš©ν–ˆλ‹€. babel-loader λ₯Ό μ‚¬μš©ν•˜λ©΄ typescript μ‚¬μš©μ΄ λΆˆκ°€ν•˜κΈ°μ— babel.config.js μ—μ„œ μΆ”κ°€ 섀정을 ν•˜μ˜€λ‹€.

ν•˜μ§€λ§Œ μ§€κΈˆμ€ μ„€μ •μ—μ„œλŠ” 바벨은 νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ½”λ“œλ₯Ό μ œκ±°ν•˜κ³  μ»΄νŒŒμΌμ„ ν•˜κΈ° λ•Œλ¬Έμ— νƒ€μž… μ—λŸ¬λ₯Ό μž‘μ„ μˆ˜κ°€ μ—†κΈ° λ•Œλ¬Έμ— 좔가적인 babel.config.js 의 섀정이 ν•„μš”ν•˜λ‹€.

μΆ”κ°€μ μœΌλ‘œ ReactRefreshWebpackPlugin λ₯Ό ν™œμš©ν•˜μ—¬, λΉŒλ“œ 속도λ₯Ό λ†’μ˜€μŠ΅λ‹ˆλ‹€.

// webpack.js

module: {
    rules: [
      {
        test: /\.(ts|tsx)$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              plugins: [require.resolve('react-refresh/babel')],
            },
          },
        ],
      },
    ],
  },

// babel.config.js

module.exports = {
  presets: [
    '@babel/env',
    '@babel/preset-typescript',
    ['@babel/preset-react', { runtime: 'automatic' }],
  ],
};

develop, production

develop κ³Ό production 두 가지 ν™˜κ²½μ—μ„œλŠ” λͺ¨λ‘ 쑰금 λŠλ¦¬λ”λΌλ„ ts-loader λ₯Ό μ‚¬μš©ν•΄ μ»΄νŒŒμΌν•  λ•Œ νƒ€μž… 검사λ₯Ό μ§„ν–‰ν•˜λ„λ‘ν•˜μ—¬ 더 μ•ˆμ „ν•œ λΉŒλ“œ νŒŒμΌμ„ μ„œλ²„μ—μ„œ μ‹€ν–‰ν•˜λ„λ‘ ν–ˆλ‹€.

module: {
    rules: [
      {
        test: /\.(ts|tsx)$/,
        use: 'ts-loader',
      },
    ],
  },

πŸ›‘οΈ TSC & Type Checker의 μžμ„Έν•œ 차이

TSC

TSC λŠ” TypeScript Compiler 이닀. 큰 κ·Έλ¦Όμ—μ„œ 보면, 두 가지 역할을 μˆ˜ν–‰ν•œλ‹€.

  • μ΅œμ‹  νƒ€μž…μŠ€ν¬λ¦½νŠΈ/μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό λΈŒλΌμš°μ €μ—μ„œ λ™μž‘ν•  수 μžˆλ„λ‘
    κ΅¬λ²„μ „μ˜ μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ 트랜슀파일(transpile)ν•œλ‹€.
  • μ½”λ“œμ˜ νƒ€μž… 였λ₯˜λ₯Ό μ²΄ν¬ν•œλ‹€.

μ—¬κΈ°μ„œ λ†€λΌμš΄ 점은 이 두 가지가 μ„œλ‘œ μ™„λ²½νžˆ λ…λ¦½μ μ΄λΌλŠ” 것이닀. νƒ€μž…μŠ€ν¬λ¦½νŠΈλ‘œ μž‘μ„±ν•œ μ½”λ“œλ₯Ό μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ μ»΄νŒŒμΌν•  λ•Œ μž‘μ„±ν•œ νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ½”λ“œκ°€ μœ νš¨ν•œ μžλ°”μŠ€ν¬λ¦½νŠΈλΌλ©΄ νƒ€μž…μ˜€λ₯˜κ°€ μžˆλ”λΌλ„, TSCλŠ” μ½”λ“œλ₯Ό μ»΄νŒŒμΌμ— μ„±κ³΅ν•œλ‹€.

νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ λ³€ν™˜λ  λ•Œ μ½”λ“œ λ‚΄μ˜ νƒ€μž…μ—λŠ” 영ν–₯을 주지 μ•Šκ³ , λ˜ν•œ κ·Έ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μ‹€ν–‰ μ‹œμ μ—λ„ νƒ€μž…μ€ 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠλŠ”λ‹€.

νƒ€μž…μŠ€ν¬λ¦½νŠΈμ˜ 였λ₯˜λŠ” Cλ‚˜ μžλ°” 같은 μ–Έμ–΄λ“€μ˜ κ²½κ³ (Warning)와 λΉ„μŠ·ν•˜λ‹€. λ¬Έμ œκ°€ 될 λ§Œν•œ 뢀뢄을 μ•Œλ € μ£Όμ§€λ§Œ, λΉŒλ“œλ₯Ό λ©ˆμΆ”μ§€λŠ” μ•ŠλŠ”λ‹€.

Type Checker

TSC κ°€ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό νƒ€μž…μŠ€ν¬λ¦½νŠΈ AST둜 λ³€ν™˜ν•œ λ‹€μŒ, TSC의 Type Checker κ°€ ASTλ₯Ό 확인해 νƒ€μž…μ„ 확인해 ν”„λ‘œκ·Έλž¨μ΄ 개발자의 κΈ°λŒ€λŒ€λ‘œ 싀행될 수 있게 ν•΄μ€€λ‹€.

μœ„μ—μ„œλ„ μ–ΈκΈ‰ν–ˆμ§€λ§Œ νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ½”λ“œκ°€ μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œλ‘œ μ»΄νŒŒμΌν•  λ•ŒλŠ” κ°œλ°œμžκ°€ μ‚¬μš©ν•œ νƒ€μž…μ„ ν™•μΈν•˜μ§€ μ•ŠμœΌλ©°, κ°œλ°œμžκ°€ κΈ°μž…ν•œ νƒ€μž… μ •λ³΄λŠ” μ΅œμ’…μ μœΌλ‘œ λ§Œλ“€μ–΄μ§€λŠ” ν”„λ‘œκ·Έλž¨μ— μ•„λ¬΄λŸ° 영ν–₯을 주지 μ•ŠμœΌλ©° 단지 νƒ€μž…μ„ ν™•μΈν•˜λŠ”λ°λ§Œ 쓰인닀.

νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” 점진적 μ»΄νŒŒμΌμ„ μ§€μ›ν•˜λŠ” 정적 언어이기 λ•Œλ¬Έμ—, μ‹€μ œ κ°œλ°œμžκ°€ 코딩을 μ‹œμž‘ν•˜λ©΄ μ½”λ“œ νŽΈμ§‘κΈ°κ°€ νƒ€μž… κ΄€λ ¨ μ—λŸ¬λ₯Ό λͺ¨λ‘ κ²€μΆœν•œλ‹€.


πŸ€” 의문

νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μ„€μΉ˜ν•˜κ²Œ 되면 tsc 뿐만 μ•„λ‹ˆλΌ tsserver μ—μ„œ μ œκ³΅ν•˜λŠ” μ–Έμ–΄ μ„œλΉ„μŠ€λ„ μ½”λ“œ νŽΈμ§‘κΈ°μ—μ„œ μ‚¬μš©ν•˜κ²Œ λœλ‹€. νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ μ½”λ“œλ₯Ό μž‘μ„± 쀑에 λ³€μˆ˜λ‚˜ ν•¨μˆ˜μ˜ νƒ€μž…μ„ λ¬΄μ—‡μœΌλ‘œ μΆ”λ‘ ν•˜λŠ”μ§€ μ•Œ 수 μžˆλŠ” 쒋은 도ꡬ인데, μ΄λ ‡κ²Œ νŽΈμ§‘κΈ°μ—μ„œ νƒ€μž…μ„ μ¦‰μ„μœΌλ‘œ 확인할 수 μžˆλ‹€λŠ” 것은 tsserver 에도 tsc 에 μžˆλŠ” 것과 λ™μΌν•œ Type Checker κ°€ μžˆλŠ” 걸까? 아직 곡뢀가 더 ν•„μš”ν•  것 κ°™λ‹€.

profile
μš°μ•„ν•œν…Œν¬μ½”μŠ€ 4κΈ° μ›Ή ν”„λ‘ νŠΈμ—”λ“œ

0개의 λŒ“κΈ€