Reactμ—μ„œ Derived Stateλ₯Ό ν™œμš©ν•˜μ—¬ μƒνƒœ κ΄€λ¦¬ν•˜κΈ°

sumin
  • #React
  • #Derived State

λ“€μ–΄κ°€λ©°

μ•ˆλ…•ν•˜μ„Έμš”. 원더월 ν”„λ‘ νŠΈμ—”λ“œνŒ€ μ‹ μž… 개발자 μ§€μˆ˜λ―Όμž…λ‹ˆλ‹€.

λ¦¬μ•‘νŠΈμ—μ„œ μ€‘μš”ν•œ κ°œλ… 쀑 ν•˜λ‚˜μΈ νŒŒμƒ μƒνƒœ(Derived State)에 λŒ€ν•΄ μ•Œμ•„λ³΄λ €κ³  ν•©λ‹ˆλ‹€. νŒŒμƒ μƒνƒœλž€ 무엇이며, μƒνƒœλ₯Ό μ œλŒ€λ‘œ κ΄€λ¦¬ν•˜μ§€ μ•ŠμœΌλ©΄ λ°œμƒν•  수 μžˆλŠ” 문제점과 효과적으둜 μ‚¬μš©ν•˜λŠ” 방법에 λŒ€ν•΄ κ³΅μœ ν•˜λ €κ³  ν•©λ‹ˆλ‹€.

νŒŒμƒ μƒνƒœλž€

νŒŒμƒ μƒνƒœλŠ” κΈ°λ³Έ μƒνƒœλ‘œλΆ€ν„° μ§μ ‘μ μœΌλ‘œ κ³„μ‚°λœ μƒνƒœλ₯Ό λ§ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ μƒν’ˆ λͺ©λ‘μ΄λ‚˜ ν•„ν„°λ§λœ 데이터와 같이 κΈ°μ‘΄ μƒνƒœμ— κΈ°λ°˜ν•˜μ—¬ λ™μ μœΌλ‘œ λ³€ν•˜λŠ” μƒνƒœλ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€.

λ¦¬μ•‘νŠΈλ‘œ κ°œλ°œν•˜λ‹€ 보면, μƒνƒœλ₯Ό κ΄€λ¦¬ν•˜λŠ” 것 외에도 κ³„μ‚°λœ μƒνƒœλ‚˜ νŒŒμƒλœ 정보λ₯Ό ν•„μš”λ‘œ ν•  λ•Œκ°€ μžˆμŠ΅λ‹ˆλ‹€. μ΄λ•Œ νŒŒμƒ μƒνƒœ κ°œλ…μ΄ μ€‘μš”ν•œ 역할을 ν•©λ‹ˆλ‹€. νŒŒμƒ μƒνƒœλ₯Ό 톡해 μƒνƒœ 변화에 λŒ€ν•΄ λ¦¬λ Œλ”λ§μ„ λ°©μ§€ν•˜μ—¬ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ„±λŠ₯을 ν–₯μƒμ‹œν‚€κ³ , λ³΅μž‘ν•œ λ‘œμ§μ„ κ°„κ²°ν•˜κ²Œ ν‘œν˜„ν•˜κ³  관리할 수 μžˆμŠ΅λ‹ˆλ‹€.

μ•„λž˜λŠ” μƒν’ˆμ˜ μ˜€ν”ˆ μ‹œκ°„κ³Ό μ’…λ£Œ μ‹œκ°„μ„ 기반으둜 μƒν’ˆμ˜ μƒνƒœμ™€ 타이머λ₯Ό κ³„μ‚°ν•˜λŠ” μ˜ˆμ‹œμž…λ‹ˆλ‹€.

function formatTime(time) {
    const hour = Math.floor((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    const min = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60));
    const sec = Math.floor((time % (1000 * 60)) / 1000);

    const formatHour = String(hour).padStart(2, '0');
    const formatMin = String(min).padStart(2, '0');
    const formatSec = String(sec).padStart(2, '0');

    return `${formatHour}:${formatMin}:${formatSec}`;
}

function GoodsStatusButton({ startTime, endTime }) {
    // ν˜„μž¬ μ‹œκ°„ μƒνƒœ
    const [currentTime, setCurrentTime] = useState(new Date().getTime());

    // 1μ΄ˆλ§ˆλ‹€ ν˜„μž¬ μ‹œκ°„μ„ μ—…λ°μ΄νŠΈ
    useEffect(() => {
        const timer = setInterval(() => {
            setCurrentTime(new Date().getTime());
        }, 1000);

        return () => clearInterval(timer);
    }, []);

    // μƒν’ˆ μƒνƒœλ₯Ό κ³„μ‚°ν•˜λŠ” νŒŒμƒ μƒνƒœ
    const goodsStatus = useMemo(() => {
        if (endTime < currentTime) {
            return 'quit';
        }

        if (startTime > currentTime) {
            return 'comingsoon'
        }

        return 'ready';
    }, [currentTime, startTime, endTime]);

    return (
        <button>
            {goodsStatus === 'comingsoon'
                ? formatTime(startTime - currentTime)
                : goodsStatus}
        </button>
    )
}

μœ„μ˜ μ½”λ“œμ—μ„œ goodsStatusλŠ” 1μ΄ˆλ§ˆλ‹€ λ³€κ²½λ˜λŠ” currentTimeκ³Ό startTime, endTime μƒνƒœλ“€μ„ 기반으둜 λ™μ μœΌλ‘œ κ³„μ‚°λ©λ‹ˆλ‹€. goodsStatus 값이 β€˜comingsoon’ 이라면 κ³„μ‚°λœ 타이머λ₯Ό λ²„νŠΌμ— λ³΄μ—¬μ€λ‹ˆλ‹€. μ΄λ ‡κ²Œ νŒŒμƒ μƒνƒœλ₯Ό ν™œμš©ν•˜λ©΄ λ³΅μž‘ν•œ 쑰건 λ‘œμ§μ„ λ‹¨μˆœν™”ν•˜κ³ , μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μƒνƒœ 관리λ₯Ό 효과적으둜 μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

잘λͺ»λœ μ‚¬μš© μ˜ˆμ‹œ

μƒνƒœλ₯Ό 잘λͺ» μ‚¬μš©ν–ˆμ„ λ•Œ κ²ͺ을 수 μžˆλŠ” 일반적인 λ¬Έμ œλ“€μ„ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

propsλ₯Ό μƒνƒœμ— λ³΅μ‚¬ν•˜κΈ°

propsλ₯Ό μƒνƒœμ— λ³΅μ‚¬ν•˜λŠ” 것은 λΆˆν•„μš”ν•œ λ©”λͺ¨λ¦¬ μ‚¬μš©μ„ μ΄ˆλž˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ, 단일 μ†ŒμŠ€κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šκ³  λ‘κ°œμ˜ μƒνƒœλ₯Ό 가지고 있기 λ•Œλ¬Έμ— 예기치 μ•Šμ€ λ™μž‘μ΄ λ°œμƒν•  수 있고 μ½”λ“œλ„ λ³΅μž‘ν•΄μ§‘λ‹ˆλ‹€.

function GoodsStatusButton({ startTime, endTime }) {
    const [startTimeValue, setStartTimeValue] = useState(startTime);
    const [endTimeValue, setEndTimeValue] = useState(endTime); 
    ...
}

λΆˆν•„μš”ν•œ λ¦¬λ Œλ”λ§

λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈμ—μ„œ νŒŒμƒ μƒνƒœλ₯Ό 계산할 λ•Œ useEffect λ‚΄λΆ€μ—μ„œ ν•΄λ‹Ή μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈν•˜λŠ” 둜직이 μžˆλ‹€λ©΄, μƒνƒœ 변경이 될 λ•Œλ§ˆλ‹€ useEffectκ°€ κ³„μ†ν•΄μ„œ μž¬μ‹€ν–‰λ  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 상황은 λ¬΄ν•œ 루프λ₯Ό λ°œμƒμ‹œν‚¬ 수 있으며, 이λ₯Ό ν”Όν•˜κΈ° μœ„ν•΄ μƒνƒœμ˜ λ³€κ²½ 쑰건을 잘 μ •μ˜ν•˜κ±°λ‚˜, μ˜μ‘΄μ„± 배열을 μ˜¬λ°”λ₯΄κ²Œ μ„€μ •ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€.

κ°œμ„ ν•˜κΈ°

순수 ν•¨μˆ˜ ν™œμš©ν•˜κΈ°

순수 ν•¨μˆ˜λŠ” λ™μΌν•œ μž…λ ₯에 λŒ€ν•΄ 항상 λ™μΌν•œ 좜λ ₯을 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€. νŒŒμƒ μƒνƒœμ˜ 계산에 순수 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ 예츑 κ°€λŠ₯ν•˜κ³  μ•ˆμ •μ μΈ μƒνƒœ 관리가 κ°€λŠ₯ν•΄μ§‘λ‹ˆλ‹€.

// 순수 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œ νŒŒμƒ μƒνƒœ
function computeGoodsStatus(startTime, endTime, currentTime) {
    if (endTime < currentTime) {
        return 'quit';
    }

    if (startTime > currentTime) {
        return 'comingsoon'
    }

    return 'ready';
}

useMemo ν›… μ‚¬μš©ν•˜κΈ°

useMemo와 μ˜μ‘΄μ„± 배열을 μ‚¬μš©ν•˜λ©΄ 계산 λΉ„μš©μ΄ 높은 νŒŒμƒ μƒνƒœλ₯Ό 효율적으둜 관리할 수 μžˆμŠ΅λ‹ˆλ‹€. μ˜μ‘΄μ„± 배열에 ν¬ν•¨λœ 값이 변경될 λ•Œλ§Œ 계산이 μž¬μ‹€ν–‰λ©λ‹ˆλ‹€.

// useMemoλ₯Ό μ΄μš©ν•œ νŒŒμƒ μƒνƒœ
const goodsStatus = useMemo(() => {
    return computeGoodsStatus(startTime, endTime, currentTime);
}, [startTime, endTime, currentTime])

마치며

νŒŒμƒ μƒνƒœμ— λŒ€ν•œ μ΄ν•΄λŠ” λ¦¬μ•‘νŠΈ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ„±λŠ₯κ³Ό ꡬ쑰에 μžˆμ–΄ μ€‘μš”ν•œ 역할을 ν•©λ‹ˆλ‹€. λ¦¬μ•‘νŠΈμ—μ„œ μƒνƒœ 관리와 둜직이 λ³΅μž‘ν•΄μ§ˆ λ•Œλ§ˆλ‹€ useStateλ§Œμ„ μ˜μ‘΄ν•˜λŠ” 것이 항상 졜적의 방법은 μ•„λ‹™λ‹ˆλ‹€. νŠΉμ • μƒνƒœκ°’μ„ useState 없이 직접 κ³„μ‚°ν•˜κ±°λ‚˜ νŒŒμƒ μƒνƒœλ‘œ κ΄€λ¦¬ν•˜λŠ” 것도 κ³ λ €ν•˜λ©΄ μ½”λ“œμ˜ λ³΅μž‘μ„±μ„ 쀄이고 효율적인 μ½”λ“œμ™€ μ‚¬μš©μž κ²½ν—˜μ„ μ œκ³΅ν•  수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

이 글을 톡해 νŒŒμƒ μƒνƒœμ— λŒ€ν•΄ 도움이 λ˜μ—ˆμœΌλ©΄ μ’‹κ² μŠ΅λ‹ˆλ‹€. κ°μ‚¬ν•©λ‹ˆλ‹€!

더 읽어볼 자료

← λͺ©λ‘μœΌλ‘œ λŒμ•„κ°€κΈ°

Art Changes Life

λ…Έλ¨ΈμŠ€μ™€ ν•¨κ»˜ μ—”ν„°ν…Œν¬ 산업을 ν˜μ‹ ν•΄λ‚˜κ°ˆ 멀버λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€.

μ±„μš© 쀑인 곡고 보기