TIL 1

๐Ÿ“Œ Q1. ์™œ var ๋Œ€์‹  let๊ณผ const๋ฅผ ๊ถŒ์žฅํ• ๊นŒ?

  • var๋Š” ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„๋ฅผ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋ธ”๋ก ์•ˆ์—์„œ ์„ ์–ธํ•ด๋„ ์ „์—ญ/ํ•จ์ˆ˜ ๋ฐ–์—์„œ๋„ ์ „์ฒด์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.
  • ๋˜ํ•œ var๋Š” ์žฌ์„ ์–ธ์ด ๊ฐ€๋Šฅํ•˜๊ณ  ํ˜ธ์ด์ŠคํŒ…์‹œ ์ดˆ๊ธฐ์— undefined๋กœ ํ• ๋‹น๋˜์–ด ์˜ˆ์ธกํ•˜๊ธฐ ์–ด๋ ค์šด ๋™์ž‘์„ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.
  • let๊ณผ const๋Š” ๋ธ”๋ก์Šค์ฝ”ํ”„๋ฅผ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋ธ”๋ก ์•ˆ์—์„œ ์žฌ์„ ์–ธ ํ•  ์ˆ˜ ์—†๋‹ค.
  • ํ˜ธ์ด์ŠคํŒ…์ด ๋˜๋”๋ผ๋„ Temporal Dead Zone (TDZ)๋•Œ๋ฌธ์— ๋ธ”๋ก ๋ฐ–์—์„œ์˜ ์ ‘๊ทผํ•  ๊ฒฝ์šฐ์—๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
    • ๋ณ€์ˆ˜๊ฐ€ ํ˜ธ์ด์ŠคํŒ…์€ ๋˜์—ˆ์ง€๋งŒ, ์•„์ง ์ดˆ๊ธฐํ™”๋˜๊ธฐ ์ „ ์ƒํƒœ์— ์žˆ๋Š” ๊ตฌ๊ฐ„์„ TDZ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
    • ์ด ๊ตฌ๊ฐ„์—์„œ๋Š” ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋ ค ํ•˜๋ฉด ReferenceError๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ฝ”๋“œ ์˜ˆ์‹œ

// var ์˜ˆ์‹œ: ๊ฐ™์€ ์Šค์ฝ”ํ”„์—์„œ ์žฌ์„ ์–ธ ๊ฐ€๋Šฅ
var name = 'Alice';
var name = 'Bob';
console.log(name); // Bob

// let ์˜ˆ์‹œ: ๊ฐ™์€ ์Šค์ฝ”ํ”„์—์„œ ์žฌ์„ ์–ธ ๋ถˆ๊ฐ€
let age = 20;
// let age = 30; // SyntaxError: Identifier 'age' has already been declared

// var ํ˜ธ์ด์ŠคํŒ…
console.log(a); // undefined (ํ˜ธ์ด์ŠคํŒ…๋จ)
var a = 10;

// let ํ˜ธ์ด์ŠคํŒ… (TDZ)
console.log(b); // ReferenceError
let b = 20;

let๊ณผ const ์ค‘์—์„œ๋Š” ์–ด๋–ค ๊ฒƒ์„ ๊ธฐ๋ณธ์œผ๋กœ ์“ฐ๋Š”๊ฒŒ ์ข‹์„๊นŒ?

  • const๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. let์€ ์žฌํ• ๋‹น์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๊ณ  const๋ฅผ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ’์ด ๋ณ€ํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์˜๋„์ ์œผ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์–ด ํ˜‘์—…์‹œ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ์ข‹์•„์ง„๋‹ค.

const๋กœ ์„ ์–ธํ•œ ๊ฐ์ฒด์˜ ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

  • const๋Š” ์ฐธ์กฐ๊ฐ’ ์ฆ‰ ๋ฉ”๋ชจ์ง€ ์ฃผ์†Œ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ๋ชปํ•  ๋ฟ ๊ฐ์ฒด ์ž์ฒด๋ฅผ ๋ถˆ๋ณ€์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.
  • ์ƒํƒœ ๊ด€๋ฆฌ ์‹œ ์ฐธ์กฐํ˜• ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผ ํ•˜๊ณ , ํ•„์š”ํ•˜๋‹ค๋ฉด Object.freeze๋‚˜ Immer.js ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•ด ๋ถˆ๋ณ€์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

Object.freeze

์ •์˜: ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฐ์ฒด๋ฅผ ๋™๊ฒฐ(freeze) ์‹œ์ผœ ์ˆ˜์ • ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฉ”์„œ๋“œ.

ํŠน์ง•:

  • ์†์„ฑ ์ถ”๊ฐ€ โŒ
  • ์†์„ฑ ์‚ญ์ œ โŒ
  • ์†์„ฑ ๊ฐ’ ๋ณ€๊ฒฝ โŒ
  • ์†์„ฑ ์žฌ์ •์˜ โŒ
  • ์–•์€ ๋™๊ฒฐ(shallow freeze)๋งŒ ์ง€์› โ†’ ์ค‘์ฒฉ ๊ฐ์ฒด๋Š” ์—ฌ์ „ํžˆ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
const obj = { name: 'Alice', info: { age: 20 } };
Object.freeze(obj);

obj.name = 'Bob'; // โŒ ๋ฌด์‹œ๋จ
obj.info.age = 25; // โญ• ๊ฐ€๋Šฅ (์–•์€ freeze๋ผ์„œ ๋‚ด๋ถ€ ๊ฐ์ฒด๋Š” ๋ฐ”๋€œ)

console.log(obj); // { name: "Alice", info: { age: 25 } }

Immer.js

์ •์˜: ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋ถˆ๋ณ€์„ฑ(immutability)์„ ๊ฐ„๋‹จํžˆ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

๋™์ž‘ ์›๋ฆฌ:

  • Immer๋Š” draft๋ผ๋Š” ํ”„๋ก์‹œ(proxy) ๊ฐ์ฒด๋ฅผ ์ œ๊ณต
  • draft๋ฅผ ์ž์œ ๋กญ๊ฒŒ ๋ณ€๊ฒฝํ•˜๋ฉด, Immer๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•ด์คŒ
  • React + Redux ํ™˜๊ฒฝ์—์„œ ํŠนํžˆ ๋งŽ์ด ์‚ฌ์šฉ๋ผ์š”.
import { produce } from 'immer';

const state = { todos: [{ text: '๊ณต๋ถ€ํ•˜๊ธฐ', done: false }] };

const nextState = produce(state, (draft) => {
  draft.todos[0].done = true; // ๋งˆ์น˜ ๊ฐ€๋ณ€์ฒ˜๋Ÿผ ์ž‘์„ฑ
});

console.log(state.todos[0].done); // false (์›๋ณธ ์œ ์ง€)
console.log(nextState.todos[0].done); // true (์ƒˆ๋กœ์šด ๋ถˆ๋ณ€ ๊ฐ์ฒด)

๋ถˆ๋ณ€์„ฑ์€ ์™œ ์ค‘์š”ํ• ๊นŒ?

๋ถˆ๋ณ€์„ฑ์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋ฐฉ์‹์œผ๋กœ ์œ ์ง€๋˜๋„๋ก ๋ณด์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ค‘์š”ํ•˜๋‹ค.

๋งŒ์•ฝ ๊ฐ์ฒด๊ฐ€ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๋ผ๋ฉด, ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ๊ฐ™์€ ์ฐธ์กฐ๋ฅผ ๊ณต์œ ํ•  ๋–„ ์˜๋„์น˜ ์•Š๊ฒŒ ๊ฐ’์ด ๋ฐ”๋€Œ์–ด์„œ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ๋ฐœ์ƒ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ฆ‰, ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด ์ถ”์ ์ด ํ›จ์’ผ ์‰ฌ์›Œ์ง„๋‹ค.

ํŠนํžˆ React ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ๋Š” ์ƒํƒœ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•  ๋•Œ ์ฐธ์กฐ ๋น„๊ต(shallow compare) ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๊ฐ์ฒด๊ฐ€ ๋ถˆ๋ณ€์ด๋ฉด === ๋น„๊ต๋งŒ์œผ๋กœ๋„ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ์‰ฝ๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์–ด, ๋ Œ๋”๋ง ์„ฑ๋Šฅ ์ตœ์ ํ™”์—๋„ ํฐ ๋„์›€์ด ๋œ๋‹ค.

์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ: ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์–ด๋–ค ํ•จ์ˆ˜๋‚˜ ์ฝ”๋“œ๊ฐ€ ์ž๊ธฐ ์˜์—ญ ๋ฐ”๊นฅ์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜, ์™ธ๋ถ€ ํ™˜๊ฒฝ์— ์˜ํ–ฅ์„ ์ฃผ๋Š”๊ฑธ ๋งํ•œ๋‹ค.

๐Ÿ“Œ Q2. == vs ===

==

  • ๋‘ ๊ฐ’์„ ๋น„๊ตํ•  ๋•Œ, ํƒ€์ž…์ด ๋‹ค๋ฅด๋ฉด ๊ฐ•์ œ ํ˜•๋ณ€ํ™˜์„ ํ•˜๊ณ  ๋น„๊ตํ•œ๋‹ค.

  • ์˜ˆ์‹œ:

    1 == '1'; // true (๋ฌธ์ž์—ด "1" โ†’ ์ˆซ์ž 1๋กœ ๋ณ€ํ™˜ ํ›„ ๋น„๊ต)
    0 == false; // true (false โ†’ 0์œผ๋กœ ๋ณ€ํ™˜)
    null == undefined; // true (ํŠน๋ณ„ ๊ทœ์น™)

===

  • ๊ฐ’๋ฟ ์•„๋‹ˆ๋ผ ํƒ€์ž…๊นŒ์ง€ ๋™์ผํ•ด์•ผ true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • ์˜ˆ์‹œ:

    1 === '1'; // false (์ˆซ์ž vs ๋ฌธ์ž์—ด)
    0 === false; // false (์ˆซ์ž vs ๋ถˆ๋ฆฌ์–ธ)
    null === undefined; // false (ํƒ€์ž… ๋‹ค๋ฆ„)