λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Lect & Tip/React by GPT

λ¦¬μ•‘νŠΈμ™€ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό ν™œμš©ν•œ μ•ˆμ •μ μΈ μ»΄ν¬λ„ŒνŠΈ 개발

by st곡간 2025. 6. 2.
λ°˜μ‘ν˜•

λ¦¬μ•‘νŠΈμ™€ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό ν™œμš©ν•œ μ•ˆμ •μ μΈ μ»΄ν¬λ„ŒνŠΈ 개발

λ¦¬μ•‘νŠΈμ™€ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ˜ 쑰합은 졜근 ν”„λ‘ νŠΈμ—”λ“œ κ°œλ°œμ—μ„œ κ°€μž₯ 인기 μžˆλŠ” 선택지 쀑 ν•˜λ‚˜λ‘œ μžλ¦¬μž‘μ•˜μŠ΅λ‹ˆλ‹€. νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” 정적 νƒ€μž… 체킹과 κ°•λ ₯ν•œ μΈν„°νŽ˜μ΄μŠ€ κΈ°λŠ₯을 μ œκ³΅ν•˜μ—¬, μ»΄ν¬λ„ŒνŠΈ 개발 κ³Όμ •μ—μ„œ λ°œμƒν•  수 μžˆλŠ” 버그λ₯Ό 사전에 μ˜ˆλ°©ν•˜κ³ , μ½”λ“œμ˜ μ•ˆμ •μ„±κ³Ό 가독성을 λ†’μ—¬μ€λ‹ˆλ‹€.

λ³Έ ν¬μŠ€νŒ…μ—μ„œλŠ” νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό ν™œμš©ν•˜μ—¬ λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈλ₯Ό κ°œλ°œν•  λ•Œμ˜ 이점, μ‹€μ œ 사둀와 μ½”λ“œ μƒ˜ν”Œ, 그리고 μ•ˆμ •μ μΈ μ»΄ν¬λ„ŒνŠΈ 섀계λ₯Ό μœ„ν•œ λͺ¨λ²” 사둀λ₯Ό ꡬ체적으둜 μ†Œκ°œν•˜κ³ μž ν•©λ‹ˆλ‹€.

νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό λ„μž…ν•΄μ•Ό ν•˜λŠ” 이유

λ¦¬μ•‘νŠΈλŠ” μ»΄ν¬λ„ŒνŠΈ 기반의 UI λΌμ΄λΈŒλŸ¬λ¦¬λ‘œμ„œ μž¬μ‚¬μš©μ„±κ³Ό ν™•μž₯성이 λ›°μ–΄λ‚œ ꡬ쑰λ₯Ό μ œκ³΅ν•˜μ§€λ§Œ, μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 동적 타이핑 νŠΉμ„±μœΌλ‘œ 인해 λŸ°νƒ€μž„ μ‹œμ μ—μ„œ νƒ€μž… κ΄€λ ¨ μ—λŸ¬κ°€ λ°œμƒν•  κ°€λŠ₯성이 μžˆμŠ΅λ‹ˆλ‹€. νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό λ„μž…ν•˜λ©΄ λ‹€μŒκ³Ό 같은 μž₯점을 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

  • 정적 νƒ€μž… 체킹: 컴파일 λ‹¨κ³„μ—μ„œ νƒ€μž… 였λ₯˜λ₯Ό λ°œκ²¬ν•  수 μžˆμ–΄, λŸ°νƒ€μž„ 였λ₯˜λ₯Ό μ˜ˆλ°©ν•˜κ³  디버깅 μ‹œκ°„μ„ 단좕할 수 μžˆμŠ΅λ‹ˆλ‹€.
  • μ½”λ“œ μžλ™ μ™„μ„±κ³Ό λ¬Έμ„œν™”: νƒ€μž… μ •μ˜λ₯Ό 톡해 IDEμ—μ„œ μ½”λ“œ μžλ™ μ™„μ„± κΈ°λŠ₯을 κ°•ν™”ν•˜κ³ , μ½”λ“œ μžμ²΄κ°€ λ¬Έμ„œμ˜ 역할을 ν•˜κ²Œ λ˜μ–΄ ν˜‘μ—… μ‹œ 가독성을 λ†’μž…λ‹ˆλ‹€.
  • μΈν„°νŽ˜μ΄μŠ€μ™€ μ œλ„€λ¦­: λ³΅μž‘ν•œ 데이터 ꡬ쑰와 μ»΄ν¬λ„ŒνŠΈμ˜ props, μƒνƒœ 등을 λͺ…ν™•ν•˜κ²Œ μ •μ˜ν•  수 μžˆμ–΄, μ½”λ“œ ꡬ쑰λ₯Ό 보닀 κ²¬κ³ ν•˜κ²Œ λ§Œλ“­λ‹ˆλ‹€.
  • μœ μ§€λ³΄μˆ˜μ„± ν–₯상: νƒ€μž… μ •μ˜ 덕뢄에 νŒ€ λ‚΄μ—μ„œ μž‘μ„±λœ μ½”λ“œλ₯Ό μ΄ν•΄ν•˜κ³  μœ μ§€λ³΄μˆ˜ν•˜κΈ° μ‰¬μ›Œμ§‘λ‹ˆλ‹€.

λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈμ— νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ μš©ν•˜κΈ°

νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό λ¦¬μ•‘νŠΈ ν”„λ‘œμ νŠΈμ— λ„μž…ν•˜λŠ” 방법은 μ—¬λŸ¬ κ°€μ§€κ°€ μžˆμŠ΅λ‹ˆλ‹€. Create React App을 μ‚¬μš©ν•  경우, κΈ°λ³Έ ν…œν”Œλ¦Ώμ—μ„œ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μ§€μ›ν•˜λŠ” μ˜΅μ…˜μ„ μ„ νƒν•˜κ±°λ‚˜, κΈ°μ‘΄ ν”„λ‘œμ νŠΈμ— νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ—¬κΈ°μ„œλŠ” κ°„λ‹¨ν•œ μ˜ˆμ œμ™€ ν•¨κ»˜ λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈμ— νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μ μš©ν•˜λŠ” 방법을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

κ°„λ‹¨ν•œ μΉ΄μš΄ν„° μ»΄ν¬λ„ŒνŠΈ 예제

μ•„λž˜ μ½”λ“œλŠ” νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ μž‘μ„±ν•œ κ°„λ‹¨ν•œ μΉ΄μš΄ν„° μ»΄ν¬λ„ŒνŠΈμž…λ‹ˆλ‹€. μ»΄ν¬λ„ŒνŠΈμ˜ props와 μƒνƒœμ— λŒ€ν•΄ λͺ…ν™•ν•˜κ²Œ νƒ€μž…μ„ μ§€μ •ν•˜μ—¬, μ½”λ“œμ˜ μ•ˆμ •μ„±κ³Ό 가독성을 λ†’μ˜€μŠ΅λ‹ˆλ‹€.

// Counter.tsx
import React, { useState } from 'react';

// μ»΄ν¬λ„ŒνŠΈμ˜ props νƒ€μž… μ •μ˜
interface CounterProps {
  initialCount?: number;
}

const Counter: React.FC<CounterProps> = ({ initialCount = 0 }) => {
  // μƒνƒœμ˜ νƒ€μž…μ€ μžλ™μœΌλ‘œ number둜 μΆ”λ‘ λ©λ‹ˆλ‹€.
  const [count, setCount] = useState<number>(initialCount);

  const increment = (): void => setCount(prevCount => prevCount + 1);
  const decrement = (): void => setCount(prevCount => prevCount - 1);

  return (
    <div style={{ textAlign: 'center', margin: '20px' }}>
      <h2>ν˜„μž¬ 카운트: {count}</h2>
      <button onClick={decrement} style={{ marginRight: '10px' }}>κ°μ†Œ</button>
      <button onClick={increment}>증가</button>
    </div>
  );
};

export default Counter;

이 μ˜ˆμ œμ—μ„œλŠ” CounterProps μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜μ—¬ μ»΄ν¬λ„ŒνŠΈμ˜ propsλ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ§€μ •ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 초기 카운트 값은 선택적 μ†μ„±μœΌλ‘œ 처리되며, 기본값을 μ„€μ •ν•˜μ—¬ μ•ˆμ •μ μΈ λ™μž‘μ„ 보μž₯ν•©λ‹ˆλ‹€. λ˜ν•œ, μƒνƒœ 관리 μ‹œ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ˜ μ œλ„€λ¦­μ„ ν™œμš©ν•΄ μƒνƒœ λ³€μˆ˜μ˜ νƒ€μž…μ„ number둜 μ§€μ •ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

λ³΅μž‘ν•œ μΈν„°νŽ˜μ΄μŠ€μ™€ μ»΄ν¬λ„ŒνŠΈ 섀계

μ‹€μ œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œλŠ” λ‹€μ–‘ν•œ 데이터 ꡬ쑰와 λ³΅μž‘ν•œ μΈν„°λž™μ…˜μ΄ ν•„μš”ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이럴 λ•ŒλŠ” μΈν„°νŽ˜μ΄μŠ€μ™€ μ œλ„€λ¦­μ„ 적극 ν™œμš©ν•˜μ—¬ μ»΄ν¬λ„ŒνŠΈμ˜ μ•ˆμ •μ„±μ„ 높일 수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜ μ˜ˆμ œλŠ” μ‚¬μš©μž λͺ©λ‘μ„ λ Œλ”λ§ν•˜λŠ” μ»΄ν¬λ„ŒνŠΈλ₯Ό νƒ€μž…μŠ€ν¬λ¦½νŠΈλ‘œ κ΅¬ν˜„ν•œ μ‚¬λ‘€μž…λ‹ˆλ‹€.

// UserList.tsx
import React from 'react';

// μ‚¬μš©μž 데이터 νƒ€μž… μ •μ˜
interface User {
  id: number;
  name: string;
  email: string;
}

// μ»΄ν¬λ„ŒνŠΈμ˜ props νƒ€μž… μ •μ˜
interface UserListProps {
  users: User[];
  onUserClick: (user: User) => void;
}

const UserList: React.FC<UserListProps> = ({ users, onUserClick }) => {
  return (
    <ul>
      {users.map((user) => (
        <li key={user.id} style={{ margin: '10px 0', cursor: 'pointer' }} onClick={() => onUserClick(user)}>
          <strong>{user.name}</strong> - {user.email}
        </li>
      ))}
    </ul>
  );
};

export default UserList;

μœ„ μ˜ˆμ œλŠ” μ‚¬μš©μž 데이터λ₯Ό 담은 배열을 props둜 전달받아, 각 μ‚¬μš©μžλ₯Ό 리슀트 ν˜•νƒœλ‘œ 좜λ ₯ν•©λ‹ˆλ‹€. onUserClick ν•¨μˆ˜μ˜ νƒ€μž…λ„ λͺ…μ‹œν•˜μ—¬, μ‚¬μš©μžκ°€ 클릭할 λ•Œ μ •ν™•ν•œ νƒ€μž…μ˜ 데이터가 μ „λ‹¬λ˜λ„λ‘ ν•©λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ νŒ€μ› κ°„μ˜ ν˜‘μ—… μ‹œ 데이터 ꡬ쑰에 λŒ€ν•œ ν˜Όλž€μ„ 쀄이고, μ»΄ν¬λ„ŒνŠΈ κ°„ μΈν„°νŽ˜μ΄μŠ€λ₯Ό λͺ…ν™•ν•˜κ²Œ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ»€μŠ€ν…€ ν›…κ³Ό νƒ€μž…μŠ€ν¬λ¦½νŠΈμ˜ κ²°ν•©

νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” μ»€μŠ€ν…€ 훅을 μž‘μ„±ν•  λ•Œλ„ 큰 도움이 λ©λ‹ˆλ‹€. μ»€μŠ€ν…€ 훅을 μž‘μ„±ν•˜λ©΄ μž¬μ‚¬μš© κ°€λŠ₯ν•œ λ‘œμ§μ„ μ†μ‰½κ²Œ 뢄리할 수 μžˆλŠ”λ°, μ΄λ•Œ λ°˜ν™˜ κ°’μ˜ νƒ€μž…μ„ λͺ…ν™•ν•˜κ²Œ μ§€μ •ν•˜λ©΄ 훅을 μ‚¬μš©ν•˜λŠ” μ»΄ν¬λ„ŒνŠΈμ—μ„œλ„ μ•ˆμ •μ μΈ νƒ€μž… 체크가 κ°€λŠ₯ν•©λ‹ˆλ‹€.

μ•„λž˜λŠ” μœˆλ„μš° 크기λ₯Ό μΆ”μ ν•˜λŠ” μ»€μŠ€ν…€ 훅을 νƒ€μž…μŠ€ν¬λ¦½νŠΈλ‘œ μž‘μ„±ν•œ μ˜ˆμ œμž…λ‹ˆλ‹€.

// useWindowSize.ts
import { useState, useEffect } from 'react';

// μœˆλ„μš° 크기λ₯Ό λ‚˜νƒ€λ‚΄λŠ” νƒ€μž… μ •μ˜
interface WindowSize {
  width: number;
  height: number;
}

const useWindowSize = (): WindowSize => {
  const [windowSize, setWindowSize] = useState<WindowSize>({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  useEffect(() => {
    const handleResize = (): void => {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return windowSize;
};

export default useWindowSize;

이 μ»€μŠ€ν…€ 훅은 WindowSize μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν™œμš©ν•˜μ—¬ λ°˜ν™˜ κ°’μ˜ νƒ€μž…μ„ μ§€μ •ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 훅을 μ‚¬μš©ν•˜λŠ” μ»΄ν¬λ„ŒνŠΈμ—μ„œ μžλ™ μ™„μ„± 및 νƒ€μž… 였λ₯˜λ₯Ό μ‰½κ²Œ 확인할 수 있으며, μ½”λ“œμ˜ μ•ˆμ •μ„±μ„ λ†’μ—¬μ€λ‹ˆλ‹€.

νƒ€μž…μŠ€ν¬λ¦½νŠΈ 기반의 μ•ˆμ •μ μΈ μ»΄ν¬λ„ŒνŠΈ 개발 μ „λž΅

νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό ν™œμš©ν•˜μ—¬ λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈλ₯Ό κ°œλ°œν•  λ•Œ κ³ λ €ν•΄μ•Ό ν•  λͺ‡ κ°€μ§€ λͺ¨λ²” μ‚¬λ‘€λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  1. λͺ…μ‹œμ  νƒ€μž… μ§€μ •
    κ°€λŠ₯ν•˜λ©΄ λͺ¨λ“  props, μƒνƒœ, ν•¨μˆ˜μ˜ λ°˜ν™˜ 값에 λŒ€ν•΄ λͺ…μ‹œμ μœΌλ‘œ νƒ€μž…μ„ μ§€μ •ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 μ˜λ„μΉ˜ μ•Šμ€ νƒ€μž… 였λ₯˜λ₯Ό 사전에 μ˜ˆλ°©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  2. μΈν„°νŽ˜μ΄μŠ€μ™€ νƒ€μž… 별칭 ν™œμš©
    λ³΅μž‘ν•œ 데이터 κ΅¬μ‘°λŠ” μΈν„°νŽ˜μ΄μŠ€λ‚˜ νƒ€μž… 별칭(type alias)을 ν™œμš©ν•˜μ—¬ μ„ μ–Έν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 μ½”λ“œμ˜ 가독성을 높이고, μ—¬λŸ¬ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μΌκ΄€λœ 데이터 ꡬ쑰λ₯Ό μœ μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  3. μ œλ„€λ¦­(Generic) ν™œμš©
    μž¬μ‚¬μš© κ°€λŠ₯ν•œ μ»΄ν¬λ„ŒνŠΈλ‚˜ ν›…μ—μ„œλŠ” μ œλ„€λ¦­μ„ ν™œμš©ν•˜μ—¬ λ‹€μ–‘ν•œ 데이터 νƒ€μž…μ„ μ²˜λ¦¬ν•  수 μžˆλ„λ‘ μ„€κ³„ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, 리슀트 μ»΄ν¬λ„ŒνŠΈλ‚˜ 폼 μ»΄ν¬λ„ŒνŠΈμ—μ„œλŠ” μ œλ„€λ¦­μ„ μ‚¬μš©ν•˜λ©΄ λ”μš± μœ μ—°ν•œ μ½”λ“œ μž‘μ„±μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.
  4. νƒ€μž…μŠ€ν¬λ¦½νŠΈ 컴파일 μ˜΅μ…˜ ν™œμš©
    tsconfig.json νŒŒμΌμ—μ„œ strict μ˜΅μ…˜ 등을 ν™œμ„±ν™”ν•˜μ—¬, λ”μš± μ—„κ²©ν•œ νƒ€μž… 체크λ₯Ό μˆ˜ν–‰ν•˜λ„λ‘ μ„€μ •ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 잠재적인 버그λ₯Ό 쑰기에 λ°œκ²¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  5. μžλ™ν™”λœ ν…ŒμŠ€νŠΈμ™€ 정적 뢄석 도ꡬ λ„μž…
    νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό ν™œμš©ν•˜λ©΄ ESLint, Prettier, 그리고 Jest와 같은 도ꡬλ₯Ό μ—°λ™ν•˜μ—¬ μ½”λ“œμ˜ ν’ˆμ§ˆκ³Ό μ•ˆμ •μ„±μ„ 높일 수 μžˆμŠ΅λ‹ˆλ‹€. 정적 뢄석 도ꡬλ₯Ό 톡해 μ½”λ“œ κ·œμΉ™μ„ κ°•μ œν•˜λ©΄, ν˜‘μ—… μ‹œ μΌκ΄€λœ μ½”λ“œ μŠ€νƒ€μΌμ„ μœ μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ²°λ‘ 

λ¦¬μ•‘νŠΈμ™€ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό κ²°ν•©ν•œ 개발 ν™˜κ²½μ€ μ½”λ“œμ˜ μ•ˆμ •μ„±κ³Ό μœ μ§€λ³΄μˆ˜μ„±μ„ 크게 ν–₯μƒμ‹œν‚΅λ‹ˆλ‹€. 정적 νƒ€μž… 체킹, λͺ…μ‹œμ  μΈν„°νŽ˜μ΄μŠ€ μ •μ˜, μ œλ„€λ¦­ ν™œμš© 등을 톡해 μ»΄ν¬λ„ŒνŠΈμ˜ 버그λ₯Ό 사전에 μ˜ˆλ°©ν•˜κ³ , νŒ€ λ‚΄ ν˜‘μ—…μ—μ„œ λ°œμƒν•  수 μžˆλŠ” ν˜Όλž€μ„ 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€. μ‹€μ œ 사둀와 μ½”λ“œ μƒ˜ν”Œμ„ 톡해 μ‚΄νŽ΄λ³Έ κ²ƒμ²˜λŸΌ, νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό λ„μž…ν•œ λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈλŠ” λ”μš± κ²¬κ³ ν•˜κ³  예츑 κ°€λŠ₯ν•œ λ°©μ‹μœΌλ‘œ λ™μž‘ν•˜λ©°, ν–₯ν›„ ν™•μž₯μ„± μžˆλŠ” ν”„λ‘œμ νŠΈ κ°œλ°œμ— μžˆμ–΄ 큰 경쟁λ ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.

μ•žμœΌλ‘œ λ¦¬μ•‘νŠΈ 기반 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 개발 μ‹œ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό 적극 ν™œμš©ν•˜μ—¬, μ½”λ“œμ˜ μ•ˆμ •μ„±κ³Ό 생산성을 높이고, μ‚¬μš©μž κ²½ν—˜κ³Ό 개발자 κ²½ν—˜ λͺ¨λ‘μ—μ„œ μš°μˆ˜ν•œ κ²°κ³Όλ₯Ό λ§Œλ“€μ–΄λ‚΄μ‹œκΈΈ λ°”λžλ‹ˆλ‹€.

λ°˜μ‘ν˜•

λŒ“κΈ€