CodeIt Fs 2nd/위클리 페이퍼

codeit weekly paper5

localslave 2024. 9. 18. 23:37
  • useMemo, useCallback 에 대해 설명하고, 어떤 경우에 사용하면 좋을지, 남용할 경우 발생할 수 있는 문제점을 설명해 주세요.
  • 리액트 생명주기(life cycle)에 대해 설명해 주세요.
  • React에서 배열을 렌더링할 때 key를 설정해야 하는 이유와 key 설정 시 주의할 점을 설명하세요.

useMemo와 useCallback에 대한 설명

React의 useMemo와 useCallback은 성능 최적화를 위해 사용하는 Hooks입니다. 이 두 Hooks는 컴포넌트의 불필요한 재렌더링을 방지하여 성능을 향상시키는 데 도움을 줍니다.

useMemo의 기능과 차이점

useMemo는 값의 메모이제이션을 위해 사용됩니다. 즉, 비용이 많이 드는 연산 결과를 메모리에 저장하여, 동일한 연산을 반복하지 않고 저장된 값을 재사용할 수 있게 합니다. 이는 렌더링 성능을 최적화하는 데 유용합니다.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

위 예시에서 computeExpensiveValue는 a와 b가 변경되지 않는 한, 재계산되지 않고 이전의 계산된 값을 반환합니다.

useCallback의 기능과 차이점

useCallback은 함수의 메모이제이션을 위해 사용됩니다. 이 Hook은 전달된 함수를 다시 생성하지 않고 재사용할 필요가 있을 때 유용합니다. 특히, 하위 컴포넌트에 props로 함수를 전달할 때, 불필요한 재렌더링을 방지합니다.

const memoizedCallback = useCallback(() => {
    doSomething(a, b);
}, [a, b]);

위 예시에서 doSomething 함수는 a와 b가 변경되지 않는 한, 재생성되지 않고 동일한 참조를 유지합니다.

useMemo와 useCallback의 사용 적절성

사용 적절성

  1. 참조 동일성이 중요한 경우:
    • 하위 컴포넌트에 props로 함수나 객체를 전달할 때, 해당 값들이 변경되지 않도록 유지해야 하는 경우 사용합니다. 이를 통해 하위 컴포넌트의 불필요한 재렌더링을 방지할 수 있습니다.
  2. 비용이 많이 드는 연산:
    • 복잡한 계산이 포함된 데이터를 렌더링할 때, 연산 결과를 메모이제이션하여 재사용함으로써 성능을 최적화할 수 있습니다.

예시: useMemo 사용 시나리오

const filteredItems = useMemo(() => {
    return items.filter(item => item.active);
}, [items]);

예시: useCallback 사용 시나리오

const handleClick = useCallback(() => {
    console.log('Button clicked');
}, []);

useMemo와 useCallback의 남용 시 문제점

  1. 메모리 사용 비효율:
    • 메모이제이션은 계산된 값을 메모리에 저장하기 때문에, 불필요하게 많은 값을 저장하면 애플리케이션의 메모리 사용량이 증가하여 성능 저하를 일으킬 수 있습니다.
  2. 동작 시간의 비효율:
    • 메모이제이션의 오버헤드로 인해, 실제로 필요하지 않은 경우 오히려 애플리케이션의 응답 시간이 느려질 수 있습니다.
  3. 관리 지점 증가:
    • 코드의 복잡성이 증가하여, 의존성 배열의 관리가 어려워지고 디버깅이 복잡해질 수 있습니다. 잘못된 의존성 배열 설정은 버그를 초래할 수 있습니다.

결론

useMemo와 useCallback은 React에서 성능 최적화를 위해 중요한 도구입니다. 값과 함수를 메모이제이션하여 불필요한 재렌더링을 방지하고, 성능을 향상시킬 수 있습니다. 하지만, 이 두 Hook을 남용하면 메모리 사용 비효율, 동작 시간의 비효율, 관리 지점 증가 등의 문제를 초래할 수 있으므로, 적절한 상황에서만 사용하는 것이 중요합니다.


React 컴포넌트의 생명주기

React 컴포넌트의 생명주기는 컴포넌트가 생성되어 화면에 마운트되는 순간부터 업데이트를 거쳐 마지막으로 언마운트되어 제거되는 순간까지의 과정을 말합니다. 이 과정은 여러 생명주기 메서드로 나누어져 있으며, 이 메서드들은 컴포넌트의 생성, 업데이트, 제거와 관련된 시점에서 호출됩니다.

클래스 컴포넌트에서 주로 사용되는 생명주기 메서드

클래스 컴포넌트에서는 생명주기 메서드를 통해 컴포넌트의 다양한 상태 변화에 대응할 수 있습니다. 주요 생명주기 메서드는 다음과 같습니다:

  1. constructor()
    • 컴포넌트의 생성자 메서드로, 컴포넌트가 생성될 때 가장 먼저 실행됩니다. 초기 상태를 설정하고, 메서드를 바인딩할 때 사용됩니다.
class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = { count: 0 };
    }
}
  1. componentDidMount()
    • 컴포넌트가 처음 DOM에 마운트된 직후 호출됩니다. 외부 데이터 로딩, 타이머 설정 같은 사이드 이펙트를 발생시킬 때 사용됩니다.
class MyComponent extends React.Component {
    componentDidMount() {
        // 데이터 로딩 또는 타이머 설정
    }
}
  1. componentDidUpdate()
    • 컴포넌트가 업데이트된 후에 호출됩니다. 주로 DOM을 업데이트하거나 새로운 데이터에 반응할 때 사용됩니다.
class MyComponent extends React.Component {
    componentDidUpdate(prevProps, prevState) {
        if (this.state.count !== prevState.count) {
            // 상태 변화에 따른 로직 수행
        }
    }
}
  1. componentWillUnmount()
    • 컴포넌트가 DOM에서 제거될 때 호출됩니다. 타이머 제거, 네트워크 요청 취소 등의 정리 작업을 수행합니다.
class MyComponent extends React.Component {
    componentWillUnmount() {
        // 정리 작업 수행
    }
}

함수형 컴포넌트에서의 생명주기 관리

함수형 컴포넌트에서는 Hooks를 사용하여 생명주기를 관리합니다. 주로 사용되는 Hook은 useEffect()입니다. 이 Hook을 통해 클래스 컴포넌트의 componentDidMount, componentDidUpdate, componentWillUnmount를 하나의 API로 통합해 처리할 수 있습니다.

import React, { useState, useEffect } from 'react';

function MyComponent() {
    const [count, setCount] = useState(0);

    useEffect(() => {
        // 컴포넌트가 마운트된 직후 실행 (componentDidMount)
        // 상태나 props가 변경된 직후 실행 (componentDidUpdate)

        return () => {
            // 컴포넌트가 언마운트될 때 실행 (componentWillUnmount)
        };
    }, [count]); // 의존성 배열

    return (
        <div>
            <p>{count}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    );
}

결론

React 컴포넌트의 생명주기는 컴포넌트의 생성, 업데이트, 제거 과정을 관리하며, 이 과정에서 다양한 생명주기 메서드와 Hook을 사용할 수 있습니다. 클래스 컴포넌트에서는 constructor(), componentDidMount(), componentDidUpdate(), componentWillUnmount()와 같은 메서드를 사용하고, 함수형 컴포넌트에서는 useEffect() Hook을 통해 생명주기를 관리할 수 있습니다. 이러한 생명주기 관리를 통해 컴포넌트의 상태 변화에 유연하게 대응하고, 필요한 리소스를 효율적으로 관리할 수 있습니다.


React에서 배열을 렌더링할 때 key를 설정해야 하는 이유와 주의할 점

React에서 배열을 렌더링할 때 각 요소에 key를 설정하는 것은 매우 중요합니다. key는 React가 각 요소를 고유하게 식별하는 방법을 제공하여, 효율적인 렌더링을 가능하게 합니다.

key의 필요성 설명

key는 React가 렌더링 과정에서 각 요소를 유일하게 식별하는 방법을 제공합니다. 이는 특히 배열의 요소가 재정렬되거나 업데이트될 때 중요한 역할을 합니다. key를 통해 React는 어떤 항목이 변경되었는지, 추가되었는지 또는 제거되었는지를 정확히 파악할 수 있습니다. 이로 인해 불필요한 요소의 생성과 파괴를 방지하고, 변경된 요소만을 효율적으로 갱신할 수 있습니다.

const listItems = items.map(item => <li key={item.id}>{item.name}</li>);

key의 역할

key는 React의 렌더링 성능 최적화에 크게 기여합니다. key가 없으면 React는 매 렌더링마다 모든 요소를 새로 생성하고 제거해야 합니다. 그러나 key를 사용하면 React는 이전 상태와 새로운 상태를 비교하여 변경된 부분만 업데이트합니다. 이렇게 하면 DOM 조작이 최소화되어 성능이 향상됩니다.

key 설정 주의사항

  • 고유한 값 사용: 각 key는 리스트 내에서 고유해야 합니다. 동일한 리스트에서 key가 중복되면 React가 어떤 요소가 변경되었는지 제대로 판단할 수 없게 되어, 의도하지 않은 동작이 발생할 수 있습니다.
  • 인덱스 사용 주의: 배열의 인덱스를 key로 사용하는 것은 일반적으로 권장되지 않습니다. 이는 배열의 요소가 추가, 삭제, 재정렬 될 때 인덱스가 변할 수 있기 때문입니다. 이러한 경우 React는 요소의 변화를 정확히 파악하지 못해 불필요한 재렌더링이 발생할 수 있습니다.
// 좋지 않은 예시: 인덱스를 key로 사용
const listItems = items.map((item, index) => <li key={index}>{item.name}</li>);
  • 안정적인 고유 값 사용: key로는 요소의 고유 식별자를 사용하는 것이 가장 좋습니다. 예를 들어, 데이터베이스의 고유 ID나 UUID 등을 사용할 수 있습니다.
// 좋은 예시: 고유한 ID를 key로 사용
const listItems = items.map(item => <li key={item.id}>{item.name}</li>);

예외 상황 설명

리스트가 정적이거나 배열에 변동이 없는 경우, 인덱스를 key로 사용할 수 있습니다. 예를 들어, 리스트가 한 번 로드되고 이후에 업데이트되거나 재정렬되지 않는 경우에는 인덱스를 key로 사용하는 것이 가능합니다.

// 예외 상황: 리스트가 정적일 때 인덱스를 key로 사용
const staticItems = ['Item1', 'Item2', 'Item3'];
const listItems = staticItems.map((item, index) => <li key={index}>{item}</li>);

그러나 가능한 한 인덱스를 key로 사용하는 것을 피하고, 각 항목의 고유한 식별자를 사용하는 것이 최선입니다. 이렇게 하면 React의 효율적인 렌더링을 보장하고, 잠재적인 버그 발생 가능성을 줄일 수 있습니다.

결론

React에서 배열을 렌더링할 때 key를 설정하는 것은 필수적입니다. key는 React가 각 요소를 유일하게 식별하고, 효율적인 업데이트를 수행하는 데 도움을 줍니다. key 설정 시 고유한 값을 사용하고, 인덱스를 key로 사용하는 것을 피해야 합니다. 이를 통해 React 애플리케이션의 성능을 최적화하고, 코드의 안정성을 높일 수 있습니다.

'CodeIt Fs 2nd > 위클리 페이퍼' 카테고리의 다른 글

11.11  (0) 2024.11.11
codeit weekly paper6  (1) 2024.09.18
codeit weekly paper4  (0) 2024.09.18
codeit weekly paper3  (0) 2024.09.18
codeit weekly paper2  (0) 2024.08.08