DevLog:-)

프로젝트 캠프 : Next.js 2기 - 2주 회고 본문

프론트엔드

프로젝트 캠프 : Next.js 2기 - 2주 회고

hyeon200 2024. 7. 29. 01:40
반응형

 

 

Learned

리액트의 불변성과 상태 업데이트, 그리고 리듀서와 Context API

1. 불변성이란 무엇인가?

  • 불변성(Immutable): 데이터의 원본을 변경하지 않고 새로운 데이터를 생성하여 업데이트하는 것.
  • 리액트는 불변성을 기반으로 상태 업데이트를 감지한다.
    • 기존 주소값이 변경되지 않으면 React는 상태가 업데이트되지 않았다고 파단한다.
    • 따라서 새로운 참조값(주소)을 전달해야 화면이 변경된다.

2. 왜 불변성을 유지해야 하는가?

  • React는 상태의 참조값(주소)이 변경되는지 확인하여 리렌더링을 트리거한다.
  • 같은 참조값(주소)을 유지하면 React는 상태가 변경되지 않았다고 판단하여 화면에 변화가 발생하지 않는다.
  • 이를 위해 객체나 배열 같은 참조형 데이터는 새로운 값을 생성하여 업데이트해야 한다.

3. 불변성을 지키는 방법 (참조형 데이터의 처리)

//todos배열 업데이트를 해보자

let todos = [{ id: 1, text: "아침 먹기", isCompleted: false }];

const addTodo = text => {
  const newTodo = { id: todos.length + 1, text, isCompleted: false };
  todos = [...todos, newTodo]; // 새로운 배열로 업데이트 (불변성 유지)
};

const toggleTodo = id => {
  todos = todos.map(todo =>
    todo.id === id ? { ...todo, isCompleted: !todo.isCompleted } : todo
  ); // map으로 새로운 배열 생성
};

const deleteTodo = id => {
  todos = todos.filter(todo => todo.id !== id); // filter로 새로운 배열 생성
};
  • push 대신 spread 연산자([...todos, newTodo])를 사용하여 새로운 배열을 생성.
  • map과 filter 같은 내장 메서드로 새로운 배열을 만들어 상태를 업데이트.

4. 리액트에서 원시형 데이터와 참조형 데이터

  • 원시형 데이터 (Primitive Types): 숫자, 문자열, 불리언 등. 값 자체로 비교 가능.
const [count, setCount] = useState(0);
setCount(1); // 새로운 값 1을 넣음 -> 리렌더링 발생
  • 참조형 데이터 (Reference Types): 객체, 배열 등. 메모리 주소로 비교.
const [todos, setTodos] = useState([{ id: 1, text: "아침 먹기", isCompleted: false }]);
setTodos([...todos, { id: 2, text: "점심 먹기", isCompleted: false }]); // 새로운 배열 전달

5. React.memo와 메모이제이션

  • React.memo:
    • 컴포넌트의 렌더링 비용을 줄이기 위해 props가 변경되지 않을 경우 리렌더링을 방지.
    • 고차 함수로, 컴포넌트를 인자로 받아 메모이제이션된 컴포넌트를 반환.
    • 주의: 메모이제이션이 많아지면 성능 비용이 증가할 수 있으므로 적절히 사용해야 함.
const MemoizedComponent = React.memo(MyComponent);

6. 리듀서와 Context API

  • 리듀서(Reducer):
    • 상태를 관리하기 위한 함수. 상태와 액션을 입력받아 새로운 상태를 반환.
    • 리액트의 useReducer 훅으로 구현 가능.
     
const reducer = (state, action) => {
  switch (action.type) {
    case "ADD_TODO":
      return { ...state, todos: [...state.todos, action.payload] };
    case "TOGGLE_TODO":
      return {
        ...state,
        todos: state.todos.map(todo =>
          todo.id === action.payload ? { ...todo, isCompleted: !todo.isCompleted } : todo
        )
      };
    default:
      return state;
  }
};

const [state, dispatch] = useReducer(reducer, { todos: [] });


Context API:

  • 컴포넌트 트리에서 전역 상태를 관리할 때 사용.
  • 리듀서와 함께 사용하면 효율적으로 상태를 공유 가능.
const TodoContext = React.createContext();

const TodoProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, { todos: [] });

  return (
    <TodoContext.Provider value={{ state, dispatch }}>
      {children}
    </TodoContext.Provider>
  );
};

7. 요약

  • 리액트에서 불변성 유지: 새로운 참조값을 생성해 상태 업데이트.
  • 참조형 데이터 처리: map, filter, spread 연산자로 새로운 데이터 생성.
  • React.memo: 렌더링 최적화 도구로, 컴포넌트를 메모이제이션.
  • 리듀서와 Context API: 상태 관리와 전역 공유를 위해 사용.

 

 

 

 

 

[유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 2기 과정(B-log)

반응형