Immer vs Immutable-js

sy uยท2022๋…„ 7์›” 12์ผ
0

๐Ÿšช ๋“ค์–ด๊ฐ€๊ธฐ

React๋‚˜ Redux๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค ๋ณด๋ฉด ๋ถˆ๋ณ€์„ฑ์ด๋ผ๋Š” ๊ฐœ๋…์„ ๋งŽ์ด ๋“ค์–ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ•˜๋Š”๋ฐ ํŠนํžˆ Redux-Toolkit์—์„œ๋Š” ๋‚ด์žฅ๋œ ๋ฏธ๋“ค์›จ์–ด๋กœ Immer ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋“ค์–ด๊ฐ€ ์žˆ๊ธฐ๋„ ํ•˜๋‹ค. ๋ถˆ๋ณ€์„ฑ์ด ๋ฌด์—‡์ด๊ณ  ๋ถˆ๋ณ€์„ฑ์ด ์™œ React์—์„œ ์ค‘์š”ํ•œ์ง€ ์•Œ์•„๋ณด๊ณ  ๋ถˆ๋ณ€์„ฑ ์œ ์ง€๋ฅผ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์žฅ๋‹จ์ ์— ๋Œ€ํ•ด์„œ๋„ ์•Œ์•„๋ณด์ž.

๐Ÿค” ๋ถˆ๋ณ€์„ฑ(Immutability)์ด๋ž€?

๋ถˆ๋ณ€์„ฑ์€ ๋ง ๊ทธ๋Œ€๋กœ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๊ฐ’์ด๋‚˜ ์ƒํƒœ๋ฅผ ๋งํ•œ๋‹ค. ์ฆ‰, ํ•œ๋ฒˆ ์ƒ์„ฑ๋œ ๊ฐ’์€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์—†๊ณ  ๊ทธ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

JavaScript ์›์‹œํƒ€์ž…์—์„œ ๋ถˆ๋ณ€์„ฑ

JavaScript์˜ ์›์‹œ ํƒ€์ž…์€ ๋ถˆ๋ณ€์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ์›์‹œ๊ฐ’์˜ ์ข…๋ฅ˜๋กœ๋Š” ๋ฌธ์ž(string), ์ˆซ์ž(number), bigint, ๋ถˆ๋ฆฐ(boolean), ์‹ฌ๋ณผ(symbol), null, undefined๊ฐ€ ์กด์žฌํ•œ๋‹ค.

์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์›์‹œํƒ€์ž…์˜ ๋ถˆ๋ณ€์„ฑ์„ ์ดํ•ดํ•ด๋ณด์ž.

let test = 'JavaScript'; // 1
test = 'React' // 2

์œ„ ์˜ˆ์‹œ๋Š” ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ  ๊ทธ ๋ณ€์ˆ˜์— ๋ฌธ์ž์—ด์„ ํ• ๋‹นํ•œ ํ›„, ๋‹ค๋ฅธ ๋ฌธ์ž์—ด์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์›์‹œ ๊ฐ’์ธ ๋ฌธ์ž์—ด์ด ๋ณ€๊ฒฝ๋๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฌธ์ž์—ด์€ ๋ณ€๊ฒฝ๋œ ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค.
ํ•œ ์ค„์”ฉ ์‚ดํŽด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. test ๋ณ€์ˆ˜๊ฐ€ ์„ ์–ธ, 'JavaScript' ๋ฌธ์ž์—ด ํ• ๋‹น
    ์ด๋Š” ๋ฉ”๋ชจ๋ฆฌ์—๋Š” 'JavaScript'๋ผ๋Š” ๋ฌธ์ž์—ด์ด ์ƒ์„ฑ๋˜๊ณ  test ๋ณ€์ˆ˜๋Š” 'JavaScript'๊ฐ€ ์ €์žฅ๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

  2. test ๋ณ€์ˆ˜์— 'React' ๋ฌธ์ž์—ด์„ ๊ฐ’์œผ๋กœ ์žฌํ• ๋‹น
    ์ด๋Š” test ๋ณ€์ˆ˜๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๊ฐ€ 'React'๊ฐ€ ์ €์žฅ๋œ ๋ฉ”๋ชจ๋ฆฌ์˜ ์œ„์น˜๋ผ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด 'JavaScript' ๋ฌธ์ž์—ด์„ ์–ด๋–ป๊ฒŒ ๋œ ๊ฑธ๊นŒ? ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์‚ฌ๋ผ์ง„ ๊ฑธ๊นŒ? ๋‹ต์€ โŒ ์ด๋‹ค.
    'JavaScript' ๋ฌธ์ž์—ด์€ ๋ฉ”๋ชจ๋ฆฌ์— ๊ณ„์† ์กด์žฌํ•˜๊ณ  'React' ๋ฌธ์ž์—ด์ด ์ƒˆ๋กœ ์ƒ์„ฑ๋œ๋‹ค. ์ฆ‰, ์›์‹œ ๋ณ€์ˆ˜์— ๊ฐ’์ด ์žฌํ• ๋‹น ๋œ๋‹ค๋Š” ๊ฒƒ์€ ๊ธฐ์กด ๋ฌธ์ž์—ด์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ƒˆ๋กญ๊ฒŒ ๋ฉ”๋ชจ๋ฆฌ์— ์ƒ์„ฑ๋œ ๊ฐ’์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒƒ์ด๋‹ค.

JavaScript ์ฐธ์กฐํƒ€์ž…์—์„œ ๋ถˆ๋ณ€์„ฑ

์ฐธ์กฐ ํƒ€์ž…์€ ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ์ฐธ์กฐ ํƒ€์ž…์—๋Š” ์›์‹œ ๊ฐ’์˜ ์ข…๋ฅ˜๋ฅผ ์ œ์™ธํ•œ ์ข…๋ฅ˜(๊ฐ์ฒด, ๋ฐฐ์—ด, ํ•จ์ˆ˜ ๋“ฑ...)์ด๋‹ค.

๊ฐ์ฒด๋กœ ์˜ˆ๋ฅผ ๋“ค์–ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

const test = {
    a: 'a value',
    b: 'b value',
}; // 1

test.b = 'c value'; // 2
/*
console.log(test);
{ a: "a value", b: "c value" }
*/
  1. test ๋ณ€์ˆ˜ ์„ ์–ธ, ๊ฐ์ฒด ํ• ๋‹น
    ์›์‹œ๊ฐ’๊ณผ ๋‹ฌ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ์—๋Š” ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ์ €์žฅ๋œ ์ฃผ์†Œ๊ฐ’์ด ์ €์žฅ๋œ๋‹ค. test๋Š” ์ด ์ฃผ์†Œ๊ฐ’์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

  2. test ๊ฐ์ฒด์˜ b ์†์„ฑ์— ๊ฐ’์„ ์žฌํ• ๋‹น
    ์›๋ณธ ๋ฐ์ดํ„ฐ๊ฐ€ ์ˆ˜์ •๋œ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ฐธ์กฐ ํƒ€์ž…์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ๋ถˆ๋ณ€์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์„๊นŒ?
์›์‹œ ํƒ€์ž…๊ณผ ๊ฐ™์ด ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ํ• ๋‹นํ•ด ์ค˜์•ผ ํ•œ๋‹ค.

์ฆ‰, ์œ„ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ์ผ๋ถ€ ์†์„ฑ์„ ๋‹ค๋ฅด๊ฒŒ ํ• ๋‹นํ•˜๊ณ  ์‹ถ์ง€๋งŒ ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•ด์•ผ ํ•œ๋‹ค๋ฉด
์•„๋ž˜์™€ ๊ฐ™์ด ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์žฌํ• ๋‹นํ•˜์—ฌ ์›๋ณธ ๋ฐ์ดํ„ฐ์˜ ์ˆ˜์ •์ด ์•„๋‹Œ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.

let test = {
    a: 'a value',
    b: 'b value',
};

test = {
	a: 'a value',
    b: 'c value',
}

๐Ÿ”Ž React์—์„œ ๋ถˆ๋ณ€์„ฑ์ด ์ค‘์š”ํ•œ ์ด์œ 

1. state ๊ฐฑ์‹ 

React๋Š” state๋‚˜ props๊ฐ€ ๊ฐฑ์‹ ๋  ๋•Œ, ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•œ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด state๋‚˜ props์˜ ๋ณ€ํ™”๋ฅผ ์–ด๋–ป๊ฒŒ ์•Œ์•„์ฐจ๋ฆด ์ˆ˜ ์žˆ์„๊นŒ?

์›์‹œ ๊ฐ’์€ ์ด์ „ state์™€ ์ƒˆ๋กœ์šด state์˜ ์–•์€ ๋น„๊ต๋ฅผ ํ†ตํ•ด state๊ฐ€ ๋ณ€๊ฒฝ๋๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋œ๋‹ค. ์–•์€ ๋น„๊ต๋Š” ์ฐธ์กฐ ํƒ€์ž…์ธ ๋ฐฐ์—ด์ด๋‚˜ ๊ฐ์ฒด์˜ ์†์„ฑ์„ ํ•˜๋‚˜ํ•˜๋‚˜ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋œ ์œ„์น˜์˜ ์ฃผ์†Œ ์ฆ‰, ์ฐธ์กฐ ๊ฐ’์„ ๋น„๊ตํ•œ๋‹ค.
์ด๊ฒŒ ์šฐ๋ฆฌ๊ฐ€ React์—์„œ ๋ถˆ๋ณ€์„ฑ์„ ์ง€์ผœ์•ผ ํ•˜๋Š” ์ด์œ ์ด๋‹ค.

๋งŒ์•ฝ state๊ฐ€ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฐ์ฒด๋ผ๊ณ  ๊ฐ€์ •ํ•ด ๋ณด์ž.

const [state, setState] = useState({
	a: { b: 'c' },
    c: 'e',
});

setState({
	...state,
    c: 'f',
});

state๋ฅผ ๊ฐฑ์‹ ํ•  ๋•Œ, ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ setState์˜ ์ธ์ž๋กœ ์ „๋‹ฌํ•˜์—ฌ state๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. ์ด์ „ state์™€ ์ƒˆ๋กœ์šด state๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์ฐธ์กฐ ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์— React๋Š” state์˜ ๊ฐฑ์‹ ์„ ์ถ”์ ํ•˜๊ณ  ๋ฆฌ๋ Œ๋”๋ง์„ ํŠธ๋ฆฌ๊ฑฐํ•  ์ˆ˜ ์žˆ๋‹ค.

2. Side Effect ๋ฐฉ์ง€

์›์‹œ ํƒ€์ž…์„ ์ œ์™ธํ•œ ์ฐธ์กฐ ํƒ€์ž…์˜ ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ .push์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋กœ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๊ฒŒ ๋˜๋ฉด ๊ทธ ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๋‹ค๋ฅธ ๊ณณ์—์„œ ์˜ˆ์ƒํ•  ์ˆ˜ ์—†๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ›‘ ์ถ”ํ›„ ์‹ค์ œ ์–ด๋–ค side effect ์‚ฌ๋ก€๊ฐ€ ์žˆ๋Š” ์ง€ ์ถ”๊ฐ€ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

๐Ÿ†š Immer vs Immutable-js

๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค๋Š” ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์กด์žฌํ•œ๋‹ค.
1. map, filter, reduce ๋“ฑ, ๊ธฐ์กด ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉ
2. spread operator(...)๋กœ ๋ณต์‚ฌ๋ณธ์„ ์‚ฌ์šฉ
3. Object.assign ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ณต์‚ฌ
4. Object.freeze ๋ถˆ๋ณ€ ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ
ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ์ž‘์—…๋“ค์„ ์ˆ˜๋™์„ ํ•˜์ง€ ์•Š์•„๋„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ํŽธํ•˜๊ฒŒ ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ถˆ๋ณ€์„ฑ์„ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ๋Œ€ํ‘œ์ ์ธ ๋‘ ๊ฐ€์ง€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์•Œ์•„๋ณด๊ณ  ์ฐจ์ด์ ์„ ๋น„๊ตํ•ด ๋ณด์ž.

Immer

Immer๋Š” ๋ถˆ๋ณ€ state๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. Immer๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์œ„์—์„œ ์•Œ์•„๋ดค๋˜ spread operator์™€ ๊ฐ™์€ ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์›๋ณธ ๊ฐ์ฒด์˜ ๋ณต์‚ฌ๋ณธ์ธ draft ์ž„์‹œ ๊ฐ์ฒด์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. Immer๋Š” ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ ์šฉ๋œ draft ๊ฐ์ฒด๋กœ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

How Immer works
The basic idea is that with Immer you will apply all your changes to a temporary draft, which is a proxy of the currentState. Once all your mutations are completed, Immer will produce the nextState based on the mutations to the draft state. This means that you can interact with your data by simply modifying it while keeping all the benefits of immutable data.

์ถœ์ฒ˜: Immer ๊ณต์‹ํ™ˆํŽ˜์ด์ง€

const initialState = {
    page: {
        title: "count",
        count: 0,
    }
};

// Immer ์‚ฌ์šฉ ์ „
export const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'ADD_COUNT':
      return {
        ...state,
        page: {
        	...state.page,
            count: state.page.count + 1
        },
      };
    default:
      return state;
  }
};

// Immer ์‚ฌ์šฉ ํ›„
import produce from 'immer'

export const reducer = produce(state = initialState, (draft) => {
	switch (action.type) {
    case 'ADD_COUNT':
      draft.page.count = state.page.count + 1;
    default:
      return state;
  	}
});

์žฅ์ 

  1. ์ „์šฉ API๋‚˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๋ฐฐ์šฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
    • ์ผ๋ฐ˜ JavaScript ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ(๊ฐ์ฒด, ๋ฐฐ์—ด ๋“ฑ...)๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  2. ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ ๊ฐ์†Œ
    • ๊ฐ์ฒด์˜ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“œ๋Š” ์ž‘์—…์„ ์ˆ˜๋™์œผ๋กœ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— spread operation ๋“ฑ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
    • ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง„๋‹ค.
  3. JSON ํŒจ์น˜ ์ง€์›

๋‹จ์ 

  1. class ์ธ์Šคํ„ด์Šค์™€ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค.

Immutable-js

Immutable.js๋Š” Immer์™€ ๊ฐ™์ด ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์„ ๋•๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.
Immutable.js๋Š” List, Stack, Map, Set๊ณผ ๊ฐ™์€ ๋งŽ์€ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ฐฑ์‹ ์ด ์žˆ์„ ๋•Œ, ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ ๊ฐ’์ด ๋‹ฌ๋ผ์ง€์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. fromJS ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ผญ ๊ฐ์ฒด๋ฅผ Map, List ์™€ ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ ๋„ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ์ค€๋‹ค.

import { Map } from "immutable";

const initialState = Map({ // JavaScript์˜ ์ผ๋ฐ˜ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ Map ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ถˆ๋ณ€ ์ปฌ๋ ‰์…˜์„ ์ƒ์„ฑํ•œ๋‹ค.
  page: Map({
    title: "count",
    count: 0,
  })
});

export const reducer = (state = initialState, action) => {
  const page = state.get('page');
  switch (action.type) {
    case 'ADD_COUNT':
      return state.set('page', page.update((page) => page.set('count', page.get('count') + 1)));
    default:
      return state;
  }
};

์žฅ์ 

  1. ๋ฐ์ดํ„ฐ์˜ ๊ฐฑ์‹ ์ด ์žˆ์„ ๋•Œ, set์™€ ๊ฐ™์ด ์ปฌ๋ ‰์…˜์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ๋Œ€์‹  ์ƒˆ๋กœ์šด ๋ถˆ๋ณ€ ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜
    • ๊ฐ์ฒด์˜ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“œ๋Š” ์ž‘์—…์„ ์ˆ˜๋™์œผ๋กœ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— spread operation ๋“ฑ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
    • ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง„๋‹ค.
  2. ์ปฌ๋ ‰์…˜์„ ๋‹ค์‹œ JavaScript ๊ฐ์ฒด๋กœ ๊นŠ๊ฑฐ๋‚˜ ์–•๊ฒŒ ๋‹ค์‹œ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Œ
  3. Batching Mutations๊ณผ Lazy Seq์œผ๋กœ ์„ฑ๋Šฅ ์ตœ์ ํ™”
    • Batching Mutations: ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ „์— ๋ฐ์ดํ„ฐ์˜ ๋ณ€ํ™”๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์ค€๋‹ค๋ฉด ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๋ถˆ๋ณ€ ์ปฌ๋ ‰์…˜์„ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ๋ฐ˜ํ™˜ํ•  ๋•Œ๋งŒ ์ƒˆ๋กœ์šด ๋ถˆ๋ณ€ ์ปฌ๋ ‰์…˜์„ ์ƒ์„ฑํ•œ๋‹ค.
      const result = [].withMutations(function (list) {
      	list.push(4).push(5).push(6);
      }); // push๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ํ–ˆ์ง€๋งŒ ์ƒˆ๋กœ์šด ์ปฌ๋ ‰์…˜์€ ํ•˜๋‚˜๋งŒ ์ƒ์„ฑ
    • Lazy Seq: Seq๋Š” ์ƒ์„ฑ ํ›„, ์ˆ˜์ •์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉฐ ์ผ๋‹จ ์‚ฌ์šฉ๋˜๋ฉด ํ•„์š”ํ•œ ์ž‘์—…๋งŒ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ฆ‰, ์—ฐ์‡„ ์ž‘์—…(filter, map ๋“ฑ...)์ด ์žˆ์„ ๊ฒฝ์šฐ ์ƒˆ๋กœ์šด ์ปฌ๋ ‰์…˜์„ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ํ•„์š”ํ•œ ๋งŒํผ๋งŒ ์—ฐ์‚ฐํ•œ๋‹ค.
    • ex: const oddSquares = Seq([1, 2, 3, 4, 5, 6, 7, 8])
      .filter(x => x % 2 !== 0) // ์ค‘๊ฐ„ ๋ฐฐ์—ด์ด ์ƒ์„ฑ๋˜์ง€ ์•Š๋Š”๋‹ค.
      .map(x => x * x); // filter๋Š” 3๋ฒˆ๋งŒ map์€ 1๋ฒˆ๋งŒ ํ˜ธ์ถœ๋œ๋‹ค.

๋‹จ์ 

  1. JavaScript์˜ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ๊ธฐ ํ•™์Šต ๋น„์šฉ์ด ๋†’๋‹ค.
  2. JavaScript ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ๊ณ ์œ ํ•œ ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ๋•Œ ๋น„์šฉ์ด ๋งŽ์ด ๋“ ๋‹ค.

๐Ÿง‘โ€๐Ÿ’ป ๊ฒฐ๋ก 

๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—๋Š” ๊ฐ๊ฐ์˜ ์žฅ์ ๊ณผ ๋‹จ์ ์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ ํƒ์€ ๊ฐœ๋ฐœํ•˜๋Š” ์‚ฌ๋žŒ์ด ํ•„์š”์— ๋”ฐ๋ผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.
๋‹ค๋งŒ Immutable-js ์ปฌ๋ ‰์…˜์˜ ํ•™์Šต์— ๋งŽ์€ ์‹œ๊ฐ„์„ ํˆฌ์žํ•  ์ˆ˜ ์—†๋‹ค๋ฉด ๊ฐ™์€ ๋ชฉ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ JavaScript์˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Immer๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

์ž˜๋ชป๋œ ๋‚ด์šฉ์ด๋‚˜ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€ ๋‚จ๊ฒจ์ฃผ์„ธ์š”~

๐Ÿ—ƒ๏ธ ์ฐธ๊ณ  ๋ธ”๋กœ๊ทธ

Immutability in React: Thereโ€™s nothing wrong with mutating objects
๋ฆฌ์•กํŠธ ๋ถˆ๋ณ€์„ฑ์ด๋ž€ ๋ฌด์—‡์ด๊ณ , ์™œ ์ง€์ผœ์•ผ ํ• ๊นŒ?
spread operator๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ setStateํ•˜๊ธฐ
Immer and Immutable.js: How do they compare?
Immutable collections for JavaScript
Immutable js ๊ฐ„๋‹จ์ •๋ฆฌ

0๊ฐœ์˜ ๋Œ“๊ธ€