코딩기록

리액트) 상태(state)관리- 원시타입 state와 참조타입 state 본문

프론트/리액트

리액트) 상태(state)관리- 원시타입 state와 참조타입 state

뽀짝코딩 2025. 1. 7. 13:30
728x90

원시타입 state와 참조타입 state는 

리액트에서 상태를 업뎃하는 방식과 리렌더링 조건에 차이가 있다.

[ state, setState ]

스테이트, 셋스테이트 통상적으로 이렇게 부른다. 살펴보면,

 

 

1. 원시 타입(Primitive Type) State

  • 원시 타입은 값 자체를 저장하는 데이터 타입.
  • string, number, boolean, null, undefined, symbol, bigint

특징

  • 값 자체가 변경되면 React는 해당 상태를 새 값으로 인식하고 리렌더링을 트리거함.
  • 업데이트가 간단하며 불변성(immutability)을 비교적 쉽게 유지할 수 있음.

예제 [ jsx ]

import React, { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0); // 원시 타입 (number)

  const increment = () => setCount(count + 1); // 새로운 값으로 업데이트
  const reset = () => setCount(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

setCount(count + 1)은 새로운 값을 반환하므로 React는 이 상태가 업데이트되었음을 인식하고 컴포넌트를 리렌더링함.

 

 

2. 참조 타입(Reference Type) State

  • 참조 타입은 메모리 주소를 참조하여 데이터를 저장.
     object, array, function 등.

특징

  • 참조 타입의 상태를 업데이트할 때는 **불변성(immutability)**을 유지해야 리렌더링이 트리거됨.
  • React는 객체의 참조(주소)를 비교하기 때문에, 객체의 내용이 변경되더라도 참조가 동일하면 리렌더링되지 않음.
  • 객체를 업데이트할 때는 반드시 새로운 객체를 만들어야 함.

예제

import React, { useState } from "react";

function TodoList() {
  const [todos, setTodos] = useState([]); // 참조 타입 (array)

  const addTodo = () => {
    const newTodo = { id: todos.length + 1, task: "New Task" };
    setTodos([...todos, newTodo]); // 새로운 배열로 업데이트
  };

  const clearTodos = () => setTodos([]); // 참조 변경

  return (
    <div>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>{todo.task}</li>
        ))}
      </ul>
      <button onClick={addTodo}>Add Todo</button>
      <button onClick={clearTodos}>Clear Todos</button>
    </div>
  );
}
  • ...todos: 기존 배열 todos를 펼쳐서 새로운 배열의 요소로 만듬. ( 불변성 유지, 참조 비교 )
  • 예를 들어, todos가 [ { id: 1, task: "Task 1" }, { id: 2, task: "Task 2" } ]이라면,
    ...todos는 [{ id: 1, task: "Task 1" }, { id: 2, task: "Task 2" }]과 동일한 요소를 가진 배열을 만듬.
  • newTodo: 새로운 작업을 나타내는 객체.
    • const newTodo = { id: 3, task: "Task 3" };
  • 즉, [...todos, newTodo]: 기존 배열 요소를 복사하고, 새로운 요소 newTodo를 배열 끝에 추가한 새 배열을 만듬.
  • [
      { id: 1, task: "Task 1" },
      { id: 2, task: "Task 2" },
      { id: 3, task: "Task 3" }
    ]
  • 그리고  React의 setTodos 함수는 이전 상태 todos와 참조가 다른 새 배열을 받음.
    • setTodos([...todos, newTodo]);
  • 이전 참조 todos 와 새 참조 [ ...todos, newTodo ] 가 다르기 때문에 Recat는 상태가 변경된 것을 인식하고 컴포넌트를 리렌더링함. 

 

3. 주요 차이점

특징원시 타입 State참조 타입 State

데이터 구조 값만 저장 (number, string 등) 메모리 주소를 참조 (object, array 등)
불변성 유지 비교적 쉽다 직접 수정하면 안 되고 새 객체/배열을 만들어야 함
상태 비교 방식 값 비교 (===) 참조 비교 (===)
리렌더링 조건 값이 변경되면 리렌더링 참조가 변경되어야 리렌더링
업데이트 방식 새 값을 할당 새 객체/배열 생성

 

 

4. 주의할 점

참조 타입을 직접 수정하면 안 되는 이유

React는 상태 변경 여부를 판단할 때 얕은 비교(shallow comparison)를 사용.
즉, 객체의 내용이 바뀌어도 참조가 같다면 React는 변경을 인식하지 않음.

const addItemWrong = () => {
  todos.push(newItem); // 기존 배열에 직접 추가
  setTodos(todos); // 참조는 동일
};

setTodos로 상태를 업데이트해도 참조가 변하지 않으므로 리렌더링되지 않음.

 

 

5. 정리

  • 원시 타입은 값 자체를 업데이트하므로 쉽게 관리 가능.
  • 참조 타입은 불변성을 유지하기 위해 새 객체/배열을 생성해야 상태 변경이 제대로 반영됨.
  • 상태 관리 라이브러리(e.g., Redux, Zustand)를 사용할 때도 불변성을 유지하는 패턴을 따르는 것이 중요.

 

 

 

 

 

참고 쳇지피티, 제로베이스강의

 

 

반응형
Comments