리액트를 사용하다 보면 상태(state)를 업데이트할 일이 많다. 그런데 상태를 직접 변경하면 안 되고 setState
나 useReducer
를 통해 새로운 객체를 만들어야 하는데, 이 과정에서 코드가 지저분해질 수 있다. immer.js는 이런 문제를 해결해주는 라이브러리로, 더 직관적이고 간결한 방식으로 상태를 업데이트할 수 있도록 도와준다.
immer.js란?
immer.js는 불변성을 유지하면서도 더 쉽게 상태를 업데이트할 수 있도록 도와주는 라이브러리다.
리액트에서는 상태를 직접 변경하면 안 되기 때문에, 일반적으로 상태를 변경할 때 새로운 객체를 만들어 반환해야 한다. 하지만 immer.js를 사용하면, 기존 객체를 직접 수정하는 것처럼 보이지만 실제로는 새로운 상태를 생성하는 방식으로 동작한다.
즉, 불변성을 자동으로 관리해주면서 코드의 가독성을 높여주는 역할을 한다.
immer.js 기본 사용법
produce
함수를 사용하여 현재 상태를 기반으로 변경 사항을 적용하는 draft를 제공한다.
설치 방법
npm install immer
# 또는
yarn add immer
기본 사용 예제
import { produce } from "immer";
const state = {
user: {
name: "Alice",
age: 25
}
};
const newState = produce(state, draft => {
draft.user.age += 1; // 기존 상태를 직접 변경하는 것처럼 작성
});
console.log(newState);
// { user: { name: 'Alice', age: 26 } }
console.log(state);
// { user: { name: 'Alice', age: 25 } } (원본 상태 유지)
불변성을 자동으로 유지
- 기존 방식에서는
spread
연산자로 객체를 복사해야 했지만, immer.js는 자동으로 불변성을 보장해준다. produce
내부에서draft
를 수정하는 것처럼 작성하면 immer.js가 새로운 객체를 반환한다.
왜 immer.js를 써야 할까?
리액트에서 상태를 다루다 보면 다음과 같은 코드를 작성해본 적이 있을 것이다.
const updateCity = () => {
setUser(prevUser => ({
...prevUser,
address: {
...prevUser.address,
city: "Seoul"
}
}));
};
...prevUser
로 기존 상태를 복사하고, 값을 수정할 때까지 반복해줘야 한다.
이럴 때 immer.js를 사용하면 더 짧고 직관적인 코드를 작성할 수 있다.
import { produce } from "immer";
const updateUser = () => {
setUser(prevUser => produce(prevUser, draft => {
draft.age += 1;
}));
};
🎯 리액트에서 immer.js 사용 예제
리액트에서 immer.js를 사용할 때는 위에서처럼 useState
와 produce
를 함께 사용하면 된다.
하지만 immer.js에서 제공하는 useImmer
훅을 사용하면 더욱 간결하게 상태를 업데이트할 수 있다.
📌 설치 방법
npm install use-immer
# 또는
yarn add use-immer
✅ useImmer
를 활용한 상태 업데이트
import React from "react";
import { useImmer } from "use-immer";
const App = () => {
const [user, updateUser] = useImmer({ name: "Alice", age: 25 });
const incrementAge = () => {
updateUser(draft => {
draft.age += 1;
});
};
return (
<div>
<p>{user.name}의 나이: {user.age}</p>
<button onClick={incrementAge}>나이 증가</button>
</div>
);
};
export default App;
useImmer
의 장점
✅ useState
를 사용할 때와 동일한 방식으로 상태를 관리 가능
✅ updateUser
함수 안에서 produce
를 따로 호출할 필요 없이 draft를 직접 수정 가능
✅ 코드가 더 직관적이고 간결해짐
정리
- immer.js는 불변성을 유지하면서도 직관적으로 상태를 변경할 수 있도록 도와주는 라이브러리
produce
함수를 활용하면 기존 객체를 직접 수정하는 것처럼 보이지만, 내부적으로 새로운 상태를 생성- 리액트의
useState
,useReducer
와 함께 사용하면 코드가 훨씬 깔끔해짐
개인적인 감상으론 기존 코드 베이스에 중첩된 상태를 업데이트하는 경우가 많은 경우나 redux를 사용하는 경우에 고려해볼 만 한 라이브러리인 것 같다.