일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- Linux
- SOLID
- nodejs
- js
- review
- DM
- Git
- react
- postgresql
- sqlite
- python
- PRISMA
- CV
- vscode
- ps
- C++
- API
- mongo
- ML
- figma
- CSS
- GAN
- html
- UI
- DB
- Express
- ts
- PyTorch
- frontend
- threejs
- Today
- Total
아카이브
[Solid] Syntax | 10. Produce와 불변성 본문
※ Signal과 Store를 살펴보고 오면 도움이 됩니다.
SolidJS는 기본적으로 반응형 Signal을 사용하지만,
때로는 Signal을 불변값(immutable)으로 다루는 것이 더 편리할 수 있습니다.
produce() 함수는 Signal이나 Store를 불변성으로 다루기 위해 사용됩니다.
불변성(Immutability)
프로그램을 실행하는데 있어 어떤 값들은 변경되면 치명적인 영향을 끼치는 경우도 있습니다. 때문에 다른 사람들과 협업할 때 함부로 값을 바꾸지 못하게 할 필요가 있으며, 이때 불변성을 통해 값이 변경될 수 없도록 보호할 수 있습니다. 불변 객체는 내부 상태를 제공하는 메소드를 제공하지 않거나, 방어적 복사(defensive-copy)를 통해서만 제공합니다. 대표적인 불변 객체의 예로 Java의 string과 Python의 tuple이 있습니다.
1. 값을 직접 변경하는 경우
먼저 불변성을 지키지 않는 경우를 살펴봅시다.
const [state, setState] = createSignal({ count: 0, items: [] });
const incorrectUpdate = () => {
const currentState = state();
currentState.count += 1; // 상태를 직접 변경합니다.
setState(currentState); // 변경된 상태를 다시 설정합니다.
};
위 코드에서 incorrectUpdate( ) 함수는 상태 객체를 직접 변경하려고 합니다.
이렇게 해도 기능 자체는 문제 없이 작동하지만, 몇 가지 문제가 발생할 수 있습니다.
1. 불변성 위반 Signal이 직접 변경되면서 불변성이 깨집니다. 이는 Signal 관리의 일관성을 해칠 수 있습니다.
2. 반응성 깨짐 SolidJS의 반응성 시스템이 Signal값의 변경을 감지하지 못할 수 있습니다. setState( )는 완전히 새로운 값을 갱신할 때만 반응성을 발동시킵니다. 따라서 배열의 요소만 바꾸는 경우 처럼 동일한 객체를 다시 설정하는 경우엔 변경 사항이 반영되지 않을 수 있습니다. [자세한 설명]
때문에 되도록이변 불변성을 지키면서 Signal 값을 수정해야할 필요가 있습니다.
2. 불변성을 지키면서 직접 값 수정하는 경우
다음과 같이 불변성을 지키면서 직접 값을 수정할 수도 있습니다.
setState({ count: state().count + 1, items: [] });
이는 변경된 값을 포함한 객체를 새로 생성해서 setState()에 갱신하는 방법입니다.
Setter 함수를 사용했으므로, 새로운 객체를 인식하여 반응성도 지킬 수 있게 됩니다.
이 방법은 간단하고 작은 상태 변경에 적합합니다.
하지만, 복잡한 업데이트가 필요한 경우에는 코드가 길어지고 관리하기 어려울 수 있습니다.
3. Produce를 사용하는 경우
produce( )는 다음과 같이 사용할 수 있습니다.
setState(produce(draft => {
draft.count += 1;
draft.items = [];
}));
produce( )를 사용하는 경우, Signal 값을 직접 변경하는 대신 변경 가능한 초안(draft)에 변경을 적용합니다.
이 초안은 내부적으로 관리되며, 초안의 바탕으로 새로운 불변 객체가 생성됩니다.
produce( )를 사용하면서 굳이 상태를 직접 변경하고자 하더라도 Solid가 별도의 오류를 발생시키지는 않습니다.
그럼에도 produce( )를 사용하면 불변성을 유지하면서 안전하게 업데이트되므로, 상태를 더 직관적이고 안정적이게 관리할 수 있습니다.
특히, Signal과 Store의 수가 많아 복잡한 업데이트가 필요한 경우에 유용합니다.
아래는 Store와 produce( )를 이용한 예제입니다.
import { render, For } from "solid-js/web";
import { createStore, produce } from "solid-js/store";
const App = () => {
let input;
let todoId = 0;
const [todos, setTodos] = createStore([]);
const addTodo = (text) => {
setTodos(
produce((todos) => {
todos.push({ id: ++todoId, text, completed: false });
}),
);
};
const toggleTodo = (id) => {
setTodos(
todo => todo.id === id,
produce((todo) => (todo.completed = !todo.completed)),
);
};
return (
<>
<div>
<input ref={input} />
<button
onClick={(e) => {
if (!input.value.trim()) return;
addTodo(input.value);
input.value = "";
}}
>
Add Todo
</button>
</div>
<For each={todos}>
{(todo) => {
const { id, text } = todo;
console.log(`Creating ${text}`)
return <div>
<input
type="checkbox"
checked={todo.completed}
onchange={[toggleTodo, id]}
/>
<span
style={{ "text-decoration": todo.completed ? "line-through" : "none" }}
>{text}</span>
</div>
}}
</For>
</>
);
};
render(App, document.getElementById("app"));
'Frontend > SolidJS' 카테고리의 다른 글
[Solid] Syntax | 12. On & Untrack (0) | 2024.07.01 |
---|---|
[Solid] Syntax | 11. Context (0) | 2024.06.27 |
[Solid] SolidJS 프로젝트 시작하기 (0) | 2024.06.25 |
[Solid] Syntax | 09. Store (0) | 2024.06.24 |
[Solid] Syntax | 08. props (0) | 2024.06.21 |