- Published on
Typescript์ Immutability
- Author
- Name
- yceffort
Table of Contents
- ๋ถ๋ณ์ฑ
- ๋ถ๋ณ์ฑ์ ๋ ผํ๊ธฐ์ ์์
- ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ถ๋ณ์ฑ
- ํ์ ์คํฌ๋ฆฝํธ์ ๋ถ๋ณ์ฑ
- ๋ถ๋ณ์ฑ์ ์ํ ๊ฐ์ด๋
- ๋ฆฌํฉํ ๋ง
๋ถ๋ณ์ฑ
Immutability(์ดํ ๋ถ๋ณ์ฑ)์ด๋, ์ด๊ธฐ์ ํ ๋น ํ ์ดํ์ ๋ ์ด์ ์ํ๊ฐ ๋ณํ์ง ์๋ ๊ฐ์ฒด๋ฅผ ์๋ฏธํ๋ค. ํ๋ก์ ํธ ๋ด์ ๋ชจ๋ ๊ฐ์ฒด์ ์ด ๋ถ๋ณ์ฑ์ ์ ์ฉํ๋ฉด, ๊ฐ๋ ์ฑ ํฅ์, ์ฝ๋์ ๋ํ ์ดํด๋ ์ฆ๊ฐ, ์ค๋ ๋์ ์์ ์ฑ ๋ฑ์ ํ๋ณดํ ์ ์๋ค.
๋ถ๋ณ์ฑ์ ๋ ผํ๊ธฐ์ ์์
์ํํธ์จ์ด ์ํคํ ์ณ์ ์ ํต์ ์ธ ๊ฐ์ฒด์งํฅ ์ ๊ทผ๋ฒ์์, ๋ชจ๋ ํด๋์ค ์ธ์คํด์ค๋ ํน์ ์ธ์คํด์ค์๋ง ์ฐ๊ฒฐ๋ ์ํ๋ฅผ ๊ฐ์ง ์ ์๋ค. ์ํ์ ์ด๊ธฐํ๋ ํด๋์ค ์์ฑ์์์ ๋ฐ์ํ๋ฉฐ, ํด๋์ค ๋ฉ์๋๋ฅผ ํธ์ถ ํ ๋ ํด๋น ์ํ์ ๋ํ ๋ณ๊ฒฝ์ ์ ์ฉํ ์ ์๋ค. ์๋ฌด๋ฆฌ ์ด๋ฌํ ์ํ ๊ฐ์ ๋ณํ๊ฐ ์ฒด๊ณ์ ์ผ๋ก ์ ๋ฆฌ๋์ด ์๋ค๊ณ ํ๋๋ผ๋, ํด๋์ค์ ์ํ๊ฐ ๋ณํ ์ ์๋ค๋ ์ธก๋ฉด์ ํด๋์ค์ ์์กดํ๋ ์ฝ๋์ ๊ตฌ์กฐ์ ํฌ๊ฒ ์ํฅ์ ๋ฏธ์น๋ค.
์ด๋ฌํ ์ํ ๊ฐ ๋ณ์ด์ ๋ฐ๋ฅธ ๋จ์ ์ ์ดํดํ๊ธฐ์ ์์, ๋๊ฐ์ ํ์ ์ ํจ์๋ฅผ ๋จผ์ ์๊ฐํ๊ณ ์ํ๋ค.
- synchronous(๋๊ธฐ): ํํ ์คํ ์ปจํ ์คํธ์์ ์ฆ์ ์คํ๋์ด ๋ฆฌํดํ๋ค
- asynchronous(๋น๋๊ธฐ) ํ์ฌ ์คํ์ปจํ ์คํธ์์ ๋๊ธฐํ๋ฉฐ, ๋ค๋ฅธ ์คํ ์ปจํ ์คํธ์์ ์คํ๋์ด ๊ฐ์ ๊ฐ์ ธ์จ๋ค.
์ฝ๋ ์คํํ๊ฒฝ์ ๋ฐ๋ผ, ํด๋ก์ ธ๊ฐ ๋น๋๊ธฐ ํจ์๊ฐ ๋๋๋ ๊ฒ์ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ํธ์ถํ๋ฉฐ, ๊ทธ ํจ์๊ฐ ์ํ๊ฐ์ ๋ฐ๊พผ๋ค๋ฉด, ํด๋ก์ ธ ๋ด๋ถ์์์ ํจ์ ํธ์ถ์ ๋ํด ์ ๋ขฐ์ฑ์ ๊ฐ์ง ์๊ฐ ์๋ค. ๋๊ธฐํธ์ถ์๋ ์ด๋ฌํ ๋ถ์ํจ๊ณผ๊ฐ ์๋ค. ๊ทธ๋ฌ๋, ํน์ ์ํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ํธ์ถ์, ๋๊ธฐ ํจ์๊ฐ ๋ด๋ถ์์ ์ํ๋ฅผ ๋ณ๊ฒฝํด๋ฒ๋ฆฐ๋ค๋ฉด ๋ชจ๋ ๋ฌดํจ๊ฐ ๋๋ฒ๋ฆฐ๋ค.
๋๋ฒ์งธ๋ก, ๋ถ๋ณํจ์์ ๋ณ์ดํจ์๋ฅผ ๊ตฌ๋ถํด์ผ ํ๋ค. ๋ถ๋ณํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ์ ๋ถ์ํจ๊ณผ๋ฅผ ๋ง๋ค์ง ์์ผ๋ฉฐ, ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ๋ค๋ ๋จํ๋์ ํจ๊ณผ(effect) ๋ง ๊ฐ์ง๋ค. ๊ทธ๋ฌ๋ ๋ณ์ด ํจ์๋ ๋ด๋ถ์์ ์ํ๋ฅผ ๋ฐ๊ฟ ์ ์๋ ๊ฐ๋ฅ์ฑ์ด ์๊ณ , ์ด๋ ๋ถ์ํจ๊ณผ๋ฅผ ๋ถ๋ฌ ์ผ์ผํค๊ฒ ๋๋ค.
์ธ๋ฒ์งธ๋ก, ๊ฐ์ฒด์งํฅ ์ํคํ
์ณ์์ ๊ฐ๋ฐ์๋ ์ด๋ค ํด๋์ค์์๋ getter์ setter๋ฅผ ์ ์ํ ์ ์๋ค. getter
๋ ๋จ์ํ ์ํ๊ฐ์ ๋ฆฌํดํ๋ ํ์๋ก, ๋ถ๋ณํจ์๋ก ๋์ํ๋ค. ๋ฐ๋ฉด์ setter
๋ ์ํ์ ๊ฐ์ ๋ถ์ฌํ๋ฏ๋ก ๋ณ์ด๋ฅผ ์ด๋ฅดํค๊ฒ ๋๋ค.
๋ง์ง๋ง์ผ๋ก, ์ด๋ฌํ ๋ชจ๋ ๊ฐ๋ ์ ๋ค ํตํ์ด์, ๊ฐ๋ฐ์๋ ์ฝ๋์ ๋ค์ํ ์์น์ ๋ค์ํ ์คํ ์ปจํ ์คํธ (์ค๋ ๋, ์ฝ๋ฐฑ ๋ชจ๋)์์ ๋ณ์ด๋๋ ์ํ๊ฐ ๋ง๋๋ ์ ์ฌ์ ์ธ ๋ณต์ก์ฑ์ ๋ณผ ์ ์์ด์ผ ํ๋ค. ๊ฐ๋ฐ์๋ค์ด ๋ฏธ๋์ ๋ณต์กํจ์ผ๋ก ๋ถํฐ ์ํ๋ฅผ ๋ณดํธํ๋ ์ง์นจ์ ๋ฐ๋ฅด์ง ์๋๋ค๋ฉด ์ฝ๋์ ๋ํ ๋๋ฒ๊น ์ด๋ ์ถ๋ก ์ด ๋ณต์กํ ์์คํ ์์ ๊ณจ์นซ๊ฑฐ๋ฆฌ๋ก ์์ฉํ ์ ์๋ค. ์ด๊ฒ์ ๋ถ๋ณ์ฑ์ ์ ์ฉํ๋ ๊ทผ๋ณธ์ ์ธ ์ด์ , ํ๋ก์ ํธ์ ์ํํ ์ ์ง๋ณด์๋ฅผ ์ง์ํ๊ธฐ ์ํ ์์์ ๋จ์ด ๋จ๋ฆด ์ ์๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์ ๋ถ๋ณ์ฑ
์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ฉํฐ ํจ๋ฌ๋ค์ ์ธ์ด์ด๋ฏ๋ก, ๊ฐ๋ฐ์์๊ฒ ํจ์ํ ์ฌ๊ณ ๋ฅผ ๊ฐ์ํ์ง ์์ผ๋ฉด์๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ธก๋ฉด์ ๊ตฌํํ ์ ์๋ค. ์ธ์ด ์์ฒด์ ์ผ๋ก๋ ์์ ์ธ๊ธํ ๋ถ๋ณ์ฑ์ ์ง์ํ๋๋ฐ, ์ด๋ฅผ ์ํด ๋ช๊ฐ์ง ๋ฌธ์์ด์ ๋ถ์ฌ์ผ ํ๋ค. ๋ถ๋ณ์ฑ์ ์ ์ฉํ๊ธฐ ์ํด์๋, ํด๋น ๋ณ์๋ ๊ฐ์ฒด์ ๋ช ํํ๊ฒ ํํํ๋ ์์ ์ ๊ฑฐ์ณ์ผ ํ๋ค.
Primitive, wrapper type
์๋ฐ์คํฌ๋ฆฝํธ์๋ ๋ช๊ฐ์ง ์์ํ์
(boolean
number
bigint
string
symbol
null
undefined
) ์ด ์๋ค. ์ด๋ค ๋ชจ๋ ๋ฉ์๋๊ฐ ์๋ค. ๋ฐ๋ผ์ ๋ถ๋ณ์ ๋ฐฉ์์ผ๋ก ์๋ํ๋ฉฐ, ์ด๋ ํจ์๋ก ์ด๋ค์ ์ ๋ฌํ๋ ๊ฒ์ด ๋ถ์ํจ๊ณผ๋ฅผ ๋ง๋ค์ง ์๋ ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค. ๋๋ถ๋ถ์ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์๊ฐ 5๊ฐ์ง wrapper (object)์ ๋ํด ์ ์์ง ๋ชปํ๋ค. (Boolean
Number
BigInt
String
Symbol
) ์ด๋ ์ธ์ด๊ฐ ์์ํ์
๊ณผ ๋ํผ ๊ฐ์ฒด์ ์ํธ๊ตํ(interchangeable)์ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.
๋ชจ๋ ๊ฐ์ฒด (์์ํ์ ์ด ์๋๊ฒ, ํจ์ ํฌํจ)๋ ๋ฉ์๋๋ฅผ ํฌํจํ๋ฏ๋ก ๊ฐ์ ๋ณํ๊ฐ ์์ ์ ์๋ค. ๊ฐ์ฒด๋, ๊ทธ ์ ์์ ๋ฐ๋ผ ํ๋กํ ํ์ ์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ์ด๋ฌํ ํ๋กํ ํ์ ์ ๋ฐ๊พธ๋ ๊ฒ์ ๊ฐ์ฒด์ ๋์์ ๋ฐ๊ฟ ์๋ ์๋ค.
๋ณ์ ์ ์ธ
๊ฐ๋ฐ์๋ค์ ๋ณ์๋ฅผ ์ ์ธํ๊ธฐ ์ํด์ let
const
๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ๊ฐ์ธ์ ์ผ๋ก ๊ฐ๋ฐ์๋ค์๊ฒ let
์ ์ฌ์ฉ์ ์์ ํ๋๋ก ํ๊ฒ ํ๋ ํธ์ด๋ค. let
์ ์ค์ฝํ ๋ด์์ ๋ช๋ฒ์ด๊ณ ์ฌํ ๋น์ด ์ด๋ฃจ์ด์ ธ์ ๋ฌธ์ ๊ฐ ๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ฒฝํ์ด ๋ง์ ๊ฐ๋ฐ์๋ค์, ๋ณ์์ ์ฌ ํ ๋น์ ์ฌ๋ฌ ํจ์์ ๋๋๊ณ , ์ด๋ฅผ ๋ณ๋๋ก ๋ฆฌํดํ๋๋ก ๋ฆฌํฉํ ๋ง ํ๋ค.
๊ฐ์ฒด ๋๊ฒฐ
์๋ฐ์คํฌ๋ฆฝํธ๋ ๊ฐ์ฒด๋ฅผ ์๊ฒ
๋ถ๋ณํ๊ฒ ๋ง๋ค์ด์ฃผ๋ ํจ์๋ฅผ ๊ฐ์ง๊ณ ์๋ค. ์๊ฒ
๋ผ๋ ๋ง์ ์ฃผ๋ชฉํ์. ์ค์ฒฉ๋ ๊ฐ์ฒด์์๋ ์ด๋ฌํ ํน์ฑ์ด ์ ์ฉ๋์ง ์๋๋ค. Object.freeze
ํจ์๋ ๋ง๊ทธ๋๋ก ๊ฐ์ฒด๋ฅผ ๋๊ฒฐ์์ผ ์ฃผ๋ฉฐ, ์ด๋ฅผ ์๊ฒ ๋ถ๋ณํ๊ฒ ๋ง๋ค์ด์ค๋ค.
const obj = {
a: {
b: 1,
},
}
Object.freeze(obj)
obj.a = null // ์๋จ!
obj.b = true // ์๋จ!
obj.a.b = 2 // ๋จ?!!
Object.freeze
๋ ๊ฐ์ฒด์ ๋ฐํ์ ์์ค์์ ์ง์ ์ ์ผ๋ก ์ ํ์ ๊ฑด๋ค. ๊ฐ์ฒด๋ฅผ ๋๊ฒฐํ๋ฉด, writable
๊ณผ configurable
๊ฐ false๋ก ๋ฐ๋๋ค. ์ด-๊ธ์ ์ฐธ๊ณ ํ์. ์๋ฌดํผ, ๊ฐ์ฒด๋ฅผ ์ ๋ง๋ก ๊น๊ฒ ๋ถ๋ณํ๊ฒ ๋ง๋ค๊ธฐ ์ํด์๋, ๋ณ๋๋ก ์จ๋ ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์ค์ค๋ก ๊ตฌํํด์ผ ํ๋ค.
ํจ์ ์์ฑ
ํจ์ ๋ํ ๊ฐ์ฒด๋ผ๋ ์ ์์, ๋ชจ๋ ํจ์ ์์ฑ์ ์ ์ฌ์ ์ผ๋ก ๋ณํ ์ ์๋ ๊ฐ๋ฅ์ฑ์ด ์๋ค. ๊ฐ์ฒด๋ฅผ ํจ์์ ์ ๋ฌํ๋ ๊ฒ์ ๋ฉ๋ชจ๋ฆฌ ์ฐธ์กฐ์ ์ํด์ ์ผ์ด๋๊ณ , ์ ๋ฌ๋ ์์ํ์ ์ ๊ฐ์ ์ํด ์ผ์ด๋๋ค๊ณ ๋ณด์. ํฅ๋ฏธ๋กญ๊ฒ๋(ํน์ ๊ท์ฐฎ๊ฒ๋) ์๋ฐ์คํฌ๋ฆฝํธ๋ ํจ์์ arguments๋ฅผ ์ฌํ ๋น ํ ์ ์๋๋ก ํด์ฃผ๋๋ฐ, ์ด๋ ํด๋ก์ ธ ๊ท์น์ ๋ฐ๋ผ ํจ์ ๋ฒ์ ๋ฐ์์๋ ์ํฅ์ ๋ฏธ์น์ง ์๋๋ค.
ํ์ ์คํฌ๋ฆฝํธ์ ๋ถ๋ณ์ฑ
ํ์
์คํฌ๋ฆฝํธ๋ ๋ถ๋ณ์ฑ๊ณผ ๊ด๋ จ๋์ด ๋๋ผ์ด ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. compile-time ํ์
์์คํ
์ ํ์ฉํ์ฌ, ์๋ ์ ์ ์๊ฒ ์ ๋ฌ๋๋ ์ฝ๋์ ์์ ์ค์ด๊ณ , ๋ฐํ์ ๋ ๋ฒจ์ ๋ํ ์ ํ์ ๋ช
์ํ ์๋ ์๊ฒ ํด์ค๋ค. ํ์
์คํฌ๋ฆฝํธ๋ ๋ถ๋ณ์ฑ์ ๋ฌ์ฑํ๊ธฐ ์ํด, readonly
์์ฑ์ ๊ฐ๋
์ ๋์
ํ๋ค.
readonly
readonly
๋ ํ์
๊ณผ ์ธํฐํ์ด์ค, ํด๋์ค ์์ฑ๊ณผ ์์ฑ์์ ์ฌ์ฉํ ์ ์๋ค.
readonly
: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#readonly-and-const- readonly
ํด๋์ค ๋ ๋ฒจ์์ ์์๋ฅผ ์ ์ํ๋ฉด, ๊ฐ์ฒด ์ค์ง ๋จํ๋ฒ, ๊ฐ์ฒด ์์ฑ์ค์๋ง ํ ๋น๋ ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ ์์ฑ์ ์ ์ํ ์ ์๋ค.
readonly
์ ์ฌ์ฉ
ํ์ ์คํฌ๋ฆฝํธ๋ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ์์ ๋ถ๋ณ์ฑ์ ์ ๊ณตํ๋ค.
Readonly<T>
: https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytypeReadonlyArray<T>
: https://www.typescriptlang.org/docs/handbook/2/objects.html#the-readonlyarray-typeReadonlySet<T>
ReadonlyMap<K, V>
Object.freeze<T>
๊ฐ ๊ฒฐ๊ณผ๋ก Readonly<T>
๋ฅผ ๋ฆฌํดํ๋ค๋ ์ฌ์ค์ ์ฃผ๋ชฉํ์. ์ด๋ ์๋ฐ์คํฌ๋ฆฝํธ์ freeze
์ readonly
์ฌ์ด์ ์ผ์ข
์ ์ฐ๊ฒฐ๊ณ ๋ฆฌ๋ค.
๊น์ ๋ถ๋ณ์ฑ
์ธ๊ธํ๋ค์ํผ, readonly
๋ ๊น์ ๋ถ๋ณ์ฑ์ ์ ๊ณตํ์ง ์์ผ๋ฏ๋ก ๊ฐ๋ฐ์๊ฐ ์จ๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐ๊ฑฐ๋ ์ง์ ๊ตฌํํด์ผ ํ๋ค. ts-essentials์์ ์ ๊ณตํ๋ DeepReadonly๋ฅผ ์ฌ์ฉํด๋ณด์.
๋ถ๋ณ์ฑ์ ์ํ ๊ฐ์ด๋
ํ๋ก์ ํธ ๋ด๋ถ์ ๊ฐ์ฒด์ ๋ถ๋ณ์ฑ์ ์ ์ฉํ๋ ๊ฒ์ ๋งค์ฐ ์ค์ํ๋ฏ๋ก, ํ๋ก์ ํธ์ ํต์ฌ ์ํคํ ์ณ ์๋ฆฌ์ ํตํฉ๋์ด์ผ ํ๋ค. ๋ฌผ๋ก ์ํํธ์จ์ด ์ ๋ฌธ๊ฐ๋ค์ด ์ด๋์ ๋๊น์ง ์ด๋ฌํ ํจํด์ ์ ์ฉํด์ผ ํ๋์ง๋ ๋ง์ ๋ ผ์์ด ์์์ง๋ง, ๋์ฒด๋ก ๋ค์๊ณผ ๊ฐ์ ํ์ ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์ ์ํ ์ง์นจ์ ์ถ์ฒํ๋ค.
const
๋ก ๋ณ์ ์ ์ธํ๊ธฐ- ์ปดํ์ผ ํ์ ๋ถ๋ณ์ฑ ์ฌ์ฉ
- ํด๋์ค ์ธ์คํด์ค์ ์ฌ์ฉ์ ํจ์๋ก๋ง ์ ํ
Readonly<T>
๋ฅผ ์ฌ์ฉํ์ฌ ๋ถ๋ณ์ ํ์ ์ผ๋ก ์ ์ธ- ๋ถ๋ณ์ ์ ํ์์ ์ ์ ํ ์๋ธํ์ ์ ์ถ์ถํ์ฌ ๋ณ์ด ํ์ ์ ์ฌ์ฉํ๋, ์ด์ ๋ํ ์ฌ์ฉ์ ํ์ ์ง์ ๊ฒ
- ์์ ๋ถ๋ณ์ฑ์ ๊น์ ๋ถ๋ณ์ฑ์ ํจ๊ณผ์ ์ผ๋ก ์ ์ฉํ๊ธฐ ์ํ์ฌ ๋ชจ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ ๊ฒ (= ์์ ๋ถ๋ณ์ฑ ๋ง์ผ๋ก ๊น์ ๋ถ๋ณ์ฑ์ ๋ฌ์ฑํ ์ ์์ด์ผ ํ๋ค)
- ํจ์๋ ๋ถ๋ณ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์์ผ ํ๋ค.
- ํจ์๋ ๋ถ๋ณ๊ฐ์ ๋ฆฌํดํด์ผ ํ๋ค.
- ๊ฐ์ฅ ์ต์ ์ ํจ์๋ ์์ํจ์๋ค.
ํ๋ก์ ํธ ์ ์ฒด ์์ญ์ ๋ถ๋ณ ํ์ ์ ์ ์ธํ๋ฉด, ๊ฐ๋ฐ์๋ค์ ๊ฐ๋ฐ์์ ๋ถ๋ณ์ฑ์ ๋จผ์ ์ผ๋ํด๋ ์ ์์ผ๋ฉฐ, ํ์ํ ๊ฒฝ์ฐ ์ด๋ฌํ ๋ถ๋ณํ์ ์ ๋์์ ์ป์ด ๋ณด๋ค ๋ณต์กํ ํ์ ์ ๊ตฌ์ฑํ ์๋ ์๋ค. ์์คํ ์ ๋๋ถ๋ถ์ ํจ์๋ ๋ณ๊ฒฝํ ์ ์๋ ๊ตฌ์กฐ๋ฅผ ์์ฉํ๊ณ , ์ด๋ฅผ ๋ง๋ค์ด ๋ด์ผ ํ๋ค. ์๋ ์ฝ๋๋ฅผ ์ฐธ์กฐํ์.
type Writable<K extends string | number | symbol, V> = {
-readonly [P in K]: V
}
type ExtractFromReadonlySet<T> = T extends ReadonlySet<infer R> ? R : never
type ExtractFromReadonlyArray<T> = T extends ReadonlyArray<infer R> ? R : never
type ExtractFromReadonlyMap<T> =
T extends ReadonlyMap<infer K, infer V> ? [K, V] : never
// ์์ ์์ค์ ๋ถ๋ณ์ฑ ํ์
์ ์ด์ฉํ์ฌ, ๊น์ ๋ถ๋ณ์ฑ์ ๊ฐ์ ํ๋ค.
type User = Readonly<{
id: string
groups: ReadonlySet<
Readonly<{
id: string
public: boolean
}>
>
}>
// ReadonlySet๋ก ๋ถํฐ ํ์
์ ์ถ์ถํ๋ค.
type ExtractFromReadonlySet<T> = T extends ReadonlySet<infer R> ? R : never
// ํจ์๋ ๋ถ๋ณ์ ์ธ์๋ฅผ ๋ฐ๋๋ค
// ํจ์๊ฐ ๋ถ๋ณ ํ์
์ ๊ฐ์ ๋ฆฌํดํ๋ค.
// ์์ํจ์
const getUserPublicGroupIds = (user: User): User['groups'] => {
// ๋ณ์๋ const๋ก ์ ์ธ๋์ด์ผ ํ๋ค.
const set = new Set<ExtractFromReadonlySet<User['groups']>>()
Array.from(user.groups).forEach((group) => {
if (group.public) {
set.add(group)
}
})
return set
}
๋ฆฌํฉํ ๋ง
์๋ก์ด ํ๋ก์ ํธ์ ๊ฒฝ์ฐ์ ์๊ด์์ง๋ง, ์ค๋๋ ์ฝ๋๋ฒ ์ด์ค์ ๋ฆฌํฉํ ๋ง์ ์๋ จ๋ ๊ฐ๋ฐ์์๊ฒ๋ ๋ฌธ์ ๊ฐ ๋ ์ ์์ผ๋ฏ๋ก ์ํํธ์จ์ด ์ ๋ฌธ๊ฐ๋ค์ด ํญ์ ํ๋ก์ ํธ ์ ๋ฐ์ ๋ณ๊ฒฝ์ ์ฌ์ ์ ๊ณํํ ํ์๊ฐ ์๋ค.
ํ์ ์คํฌ๋ฆฝํธ ํ๋ก์ ํธ์ ๋ถ๋ณ์ฑ์ ๊ฐ์ ํ๋ ์์ ์ ํ๊ธฐ ์ํด, ์๋์ ๊ฐ์ ๋ชฉ๋ก์ ์์ฑํด๋ณด์๋ค.
- ๊ธฐ์กด ํจ์์ ๋ฐํ ๊ฐ์ ๋ถ๋ณ์ผ๋ก ๋ณ๊ฒฝํ๊ณ , ๊ทธ์ ๋ฐ๋ฅธ ๋ฌธ์ ํด๊ฒฐ
- ๊ธฐ์กด ํจ์์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ถ๋ณ์ผ๋ก ๋ณ๊ฒฝํ๊ณ , ๊ทธ์ ๋ฐ๋ฅธ ๋ฌธ์ ํด๊ฒฐ
- ์์ ๋ณต์ฌ, ๋๋ ๊น์ ๋ณต์ฌ๋ฅผ ํตํด ๋ถ๋ณ์ ๊ตฌ์กฐ๋ก ๋ณ๊ฒฝ
- ์ฝ๋ ๋ฆฌํฉํ ๋ง ์ค์ ์ปดํ์ผ๋ฌ๊ฐ ์ ์ฌ์ ์ผ๋ก ๋ชจ๋ ๋ฒ๊ทธ๋ฅผ ๋ณด์ฌ์ค ๊ฒ์ด๋ผ ๊ธฐ๋ํ์ง ๋ง ๊ฒ
- ๊ด๋ฒ์ํ ํ ์คํธ์ ์์กด
๋ฆฌํด ํ์ ์ ๋ถ๋ณํ๊ฒ ๋ง๋๋ ๊ฒ์ ๋ฆฌํฉํ ๋ง์ ์ฒซ๋ฒ์งธ ๋จ๊ณ๋ค. ํจ์๊ฐ ๋ถ๋ณํ ๊ฐ์ผ๋ก ๋ฆฌํดํ๊ธฐ ์ํด, ์๋์ ๊ฐ์ ์์ ์ ์ํํด์ผ ํ๋ค.
- ์ปดํ์ผ๋ฌ๋ฅผ ๋ง์กฑ์ํค๊ธฐ ์ํด ์์ ๋ณต์ฌ๋ฅผ ํ๊ฑฐ๋
- ์ฝ๋๋ฅผ ๋ค๋ฅธ ๋ฐฉํฅ์ผ๋ก ์์
๋ถ๋ณ๊ฐ์ ์์ ์์ค์ ๋ถ๋ณ๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ ์๋ฐ์คํฌ๋ฆฝํธ์ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ด๋ฏธ ์ ์๋ ๋ฐฉ๋ฒ์ผ๋ก ๊ตฌํํ ์ ์๋ค.
- ๊ฐ์ฒด:
Object.assign({}, obj)
{...obj}
- ๋ฐฐ์ด:
arr.slice()
,[...arr]
๋ฆฌํฉํ ๋ง์
type User = {
id: string
groupIds: string[]
}
const mutableAppendGroupsToUser = (groupIds: string[], user: User): User => {
user.groupIds = Array.from(new Set([...user.groupIds, ...groups]))
return user
}
๋ฆฌํฉํ ๋งํ
type ReadonlyUser = Readonly<{
id: string
groupIds: ReadonlyArray<string>
}>
// ์ด์ ํจ์๋ ์ค์ง ๋ถ๋ณ ํ์
๋ง ๋ฐ๋๋ค.
const immutableAppendGroupsToUser = (
groupIds: ReadonlyArray<string>,
user: ReadonlyUser,
): ReadonlyUser => {
// ๋ ์ด์ `user.groupIds`๋ฅผ ์ง์ ์์ ํ์ง ์๋๋ค.
const newGroupIds = Array.from(new Set([...user.groupIds, ...groupIds]))
// ํจ์๊ฐ ์์ ํ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ๋ค.
return Object.assign({}, user, {groupIds: newGroupIds})
}
๊ฐ๋ฐ์๋ค์ด ํฐ ๊ฐ์ฒด์ ๋ํ ๊น์ ๋ณต์ฌ๋ฅผ ํ ๋ ์ฑ๋ฅ์์ ๋ฌธ์ ๋ฅผ ์กฐ์ฌํด์ผ ํ๋ค. ๋ํ ๋ถ๋ณ์ฑ์ ๋์ ํ๋ฉด, ์ปดํ์ผ๋ฌ์ ๋์์ด ์๋ ์๋ ๊ฐ์ ์ด์ ๋ถํฐ ์์๋ ๋ฒ๊ทธ๊ฐ ์๋ฉด์๋ก ๋ ์ค๋ฅด๋ ์ผ์ด ๋ํ๋ ์ ์๋ค. ์ด๋ค ํ๋ก์ ํธ๋์ง, ํฉ๋ฆฌ์ ์ธ ํ ์คํธ๋ฅผ ๊ฑฐ์ณ์ผ๋ง ์ต์ข ์ฌ์ฉ์์๊ฒ ํ๋ฅญํ ๊ฒฝํ์ ๋ณด์ฅํด์ค๋ค.
https://levelup.gitconnected.com/the-complete-guide-to-immutability-in-typescript-99154f859fdb