To mutate, or not to mutate, in JavaScript - Lee-hyuna/33-js-concepts-kr GitHub Wiki

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฐ€๋ณ€์ด๊ฑฐ๋‚˜ ๋ถˆ๋ณ€์ด๊ฑฐ๋‚˜

์›๋ฌธ : https://slemgrim.com/mutate-or-not-to-mutate/

mutable: ๊ฐ€๋ณ€

immutable: ๋ถˆ๋ณ€

primitive: ์›์‹œ ํƒ€์ž…

https://ko.wikipedia.org/wiki/%EB%B6%88%EB%B3%80%EA%B0%9D%EC%B2%B4

๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ๋ถˆ๋ณ€์„ฑ์— ๋Œ€ํ•œ ๊ฐ€์žฅ ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์— ๋Œ€ํ•ด ๋…ผ์˜๋ฅผ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ ๋ถˆ๋ณ€์„ฑ์€ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์‹œ์Šคํ…œ์ด๋‚˜ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋žด๋ฐ์—์„œ์˜ ๊ฐ€์žฅ ํฐ ๋ถ€๋ถ„์ด ์•„๋‹ˆ๋ผ๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๊ตฌ๊ธ€์—์„œ ์ฐพ๋Š”๋‹ค๋ฉด(๊ตฌ๊ธ€๋ง์„ ํ•œ๋‹ค๋ฉด), ๋ถˆ๋ณ€์„ฑ์ด ๋ฌด์—‡์ธ์ง€ ์„ค๋ช…ํ•˜๋Š” ์ˆ˜ ๋งŽ์€ ์˜๊ฒฌ๊ณผ ๊ธฐ์‚ฌ๋“ค์„ ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๊ธ€์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š” ์‚ฌ๋ก€๋ฅผ ์ง‘์ค‘์ ์œผ๋กœ ๋‹ค๋ฃฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์‚ฌํ•ญ

์ˆ˜ ๋งŽ์€ ๋‹ค๋ฅธ ์–ธ์–ด์—์„œ ์ฒ˜๋Ÿผ ์›์‹œ ํƒ€์ž…๋“ค์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋ถˆ๋ณ€์ž…๋‹ˆ๋‹ค. ์ด ์˜๋ฏธ๋Š” ์›์‹œํƒ€์ž…์€ ์–ธ์ œ๋‚˜ ๋ณ€๊ฒฝ์ด ๋  ์ˆ˜ ์žˆ๊ณ  ์ด ์›์‹œํƒ€์ž…์ด ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// Strings
let str = "Hello world!";
let res = str.slice(1,5); //ello

// Numbers
let number = 10;
number += 15;

๋ถˆ๋ณ€์€ ๋งŽ์€ ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • ๋™์‹œ์„ฑ
  • ์ธ์Šคํ„ด์Šค๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ์œ„ํ•ด ์ €์žฅ
  • ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ์—†์Œ
  • ์ผ์‹œ์ ์ธ ์ปคํ”Œ๋ง์ด ์—†์Œ
  • ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ
  • ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋น„ ๊ฐ์†Œ
  • ์บ์‹œํ•˜๊ธฐ ์‰ฌ์›€
  • ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์‰ฌ์›€

ELM ๊ทธ๋ฆฌ๊ณ  ํ•˜์Šค์ผˆ๊ณผ ๊ฐ™์€ ์–ด๋– ํ•œ ๊ฐ’์„ ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ์ˆœ์ˆ˜ํ•œ ํ•จ์ˆ˜ ์–ธ์–ด์— ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๊ทธ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฐ์ฒด๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ€๋ณ€์ž…๋‹ˆ๋‹ค. ๊ฐ€๋ณ€์„ ์‚ฌ์šฉํ•˜์ž๋งˆ์ž ๋ถˆ๋ณ€์ด ๊ฐ€์ง„ ์žฅ์ ๋“ค์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ€๋ณ€์ ์ธ ๊ฒƒ์„ ๋ถˆ๋ณ€์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ˆ˜๋™์ ์ธ ๋ฐฉ์‹

๋น„๋ก ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์ง€๋งŒ ๋Œ€๋ถ€๋ถ„ ๊ฐ€๋ณ€์„ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•จ์ˆ˜์—์„œ ๊ฐ์ฒด๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€๋งˆ์„ธ์š”.

์ฃผ์–ด์ง„ ์˜ค๋ธŒ์ ํŠธ์˜ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋Œ€์‹ ์— ๋ณ€๊ฒฝ๋œ ๋ณต์‚ฌ๋ณธ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

//bad
function save(object){
    object.saved = true;
    return object;
}

//better
function save(object){
    let newObject = object.clone();
    newObject.saved = true;
    return newObject;
}

์ƒ์„ฑ์ž ์ดํ›„์— ๊ฐ์ฒด๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ๋งˆ์„ธ์š”.

๊ฐ์ฒด๋Š” ์ฐธ์กฐ ์ž…๋‹ˆ๋‹ค. ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์œผ๋ฉด ๋ช…ํ™•ํ•˜์ง€ ์•Š์€ ์ƒํƒœ์˜ ์ƒํ™ฉ์„ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์™„์„ฑ๋œ ์ฝ”๋“œ๋Š” ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ๊ฐ€ ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค.

let request = {
    method: "GET",
    uri: "http://slemgrim.com"
}

// don't do this
request.method = "POST"

๋น„์šฉ์ด ๋งŽ์ด ๋“ค๋”๋ผ๋„ setter์€ ํ”ผํ•˜์„ธ์š”.

setter์€ ๋‘ ๊ฐ€์ง€ ์‚ฌํ•ญ์— ์ค‘๋ณต์ด ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ setter์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๊ฐ์ฒด๋ฅผ ๋ณ€๊ฒฝ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ setter์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋ณ€์ด๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ง€๋ฃจํ•œ ์ž‘์—…๋“ค์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋ถˆ๋ณ€ํ•œ ๊ฐ์ฒด๊ฐ€ ๋นŒํŠธ์ธ์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์€ ์ž‘์—…์ž๋ฅผ ํž˜๋“ค๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋„์›€์„ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Immutable.js

ํŽ˜์ด์Šค๋ถ์˜ Immutable.js๋Š” ์ƒํƒœ ๋ถˆ๋ณ€์„ ์œ ์ง€ํ•˜๋Š”๋ฐ ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž…๋‹ˆ๋‹ค. ๋น„์Šทํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ(Mori, seamless-immutable ) ์™€ ๊ฐ™์€ ๊ฐ๊ฐ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ ํ•ด๋‹น ๊ธ€์—์„œ๋Š” Immutable.js์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ž์„ธํ•œ ๋‚ด์šฉ์€documentation์— ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ข€ ๋” ์ž์„ธํ•œ ์„ค๋ช…์„ ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ •๋ง ๊ฐ„๋‹จํ•˜์ง€๋งŒ ๋งˆ๋ฌด๋ฆฌ๋Š” :

Immutable.js๋Š” List, Stack, Map, OrderedMap, Set, OrderedSet and Record์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ์˜ ๋ถˆ๋ณ€์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋˜๋Š” ์ฝ”๋“œ์˜ ํผ์—์„œ:

import Map from 'immutable';
var request = Map({method: 'GET', uri: 'http://slemgrim.com'});
var post = request.set('method', 'POST');
request.get('method'); // GET
post.get('method'); // POST

๋น„๋ก ๊ฐ์ฒด ์†์„ฑ์— ๋Œ€ํ•œ ์ง์ ‘์ ์ธ ์ ‘๊ทผ์„ ํ•  ์ˆ˜ ์—†์ง€๋งŒ, ๊ฐ€๋ณ€๊ฐ์ฒด์— ๋ถ€๋”ชํžˆ๋Š” ๋Œ€์‹ ์— ๋ณธ์—ฐ์˜ ๋ชฉ์ ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ESLint ๊ฐ€๋ณ€

eslint-plugin-immutable ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋ชจ๋“  ๊ฐ€๋ณ€์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฆฌ๋“œ๋ฏธ์— ๋ฆฌ์•กํŠธ, ๋ฆฌ๋•์Šค๋ฅผ ์–ธ๊ธ‰ํ•˜์ง€๋งŒ ์ด ๋‘๊ฐœ์˜ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ œ์™ธํ•˜๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ธ๊ฐ€์ง€ ๊ทœ์น™์„ ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:

  • no-let: let๋Œ€์‹ ์— const๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • no-this: ES6 class ์‚ฌ์šฉ์„ ๊ธˆ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • no-mutation: ๋ฉค๋ฒ„ ํ‘œํ˜„์‹์˜ ๊ฒฐ๊ณผ์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์„ ๊ธˆ์ง€ํ•ฉ๋‹ˆ๋‹ค.

์–ธ์ œ ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋‚˜์š”?

๋™์‹œ์„ฑ

์ด๊ฒƒ์€ ๋ถˆ๋ณ€์„ฑ์ด ํƒ€๋‹นํ•œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ด์œ  ์ž…๋‹ˆ๋‹ค. ์Šค๋ ˆ๋“œ๋กœ๋ถ€ํ„ฐ ์•ˆ์ „ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ณ€๊ฒฝ๋˜์ง€ ์•Ÿ๋Š” ํ•ญ๋ชฉ์„ ์ž ๊ทธ์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. JS์—์„œ๋Š” ์‹ค์ œ ๋™์‹œ์„ฑ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  Event Loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๊ฒƒ์„ ์žŠ์–ด๋ฒ„๋ ค๋„ ์ข‹์Šต๋‹ˆ๋‹ค.

์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋ฅผ ํ”ผํ•˜์„ธ์š”.

๊ฐ์ฒด์˜ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ๊ฐ€๋ณ€์ ์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐ€๋ณ€์€ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ์— ์˜ํ•ด ์ •์˜ ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋ฅผ ํ”ผํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ์—†๋‹ค๋ฉด ํ•จ์ˆ˜์˜ ๊ตฌํ˜„์„ ๋“ค์—ฌ๋‹ค๋ณผ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋Š” ์ถ”๋ก ํ•˜๊ธฐ ์‰ฌ์šฐ๋ฉฐ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ณ  ๋” ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ

๊ฐ’ ๋˜๋Š” ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋‹ค๋ฃจ๊ณ  ์žˆ๋Š” ์ง€์— ๋Œ€ํ•œ ์ƒ๊ฐ์€ ๋ฉˆ์ถฐ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ถˆ๋ณ€์˜ ๊ฐ์ฒด๋Š” ํ•ญ์ƒ ๊ฐ’์ž…๋‹ˆ๋‹ค .์ด๊ฒƒ์€ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ•ต์‹ฌ ์›๋ฆฌ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜์— ๊ฐ’ใ…‡๋ฅด ์ „๋‹ฌํ•˜๋ฉด ํ”„๋กœ๋ฏธ์Šค๋ฅผ ์˜์›ํžˆ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ธ์ œ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„๊นŒ์š”?

์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š” ์†์„ฑ

์‹ค์ œ๋กœ ์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฐ์ฒด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ชจ๋“  ๋ณ€๊ฒฝ์— ๋Œ€ํ•ด ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค. ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ฒŒ์ž„๊ณผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์—์„œ ํŠนํžˆ ๋‘๋ฒˆ ๋ฐ˜๋ณต๋˜๋Š” ๊ฒฝ์šฐ์— ํ•ด๋‹น๋ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์ด ๊ฒŒ์ž„์—์„œ ๋ถˆ๋ณ€์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๋ง์€ ์•„๋‹ˆ์ง€๋งŒ, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋ณด๋‹ค ์„ฑ๋Šฅ ๋ฌธ์ œ์— ๋น ์ง€๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

๊ฑฐ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ

์ •๋ง ๊ฑฐ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ํŠธ๋ฆฌ๊ฐ€ ๋ถˆ๋ณ€ ์ปจํ…Œ์ด๋„ˆ๋กœ ์ €์žฅ๋˜์–ด ์žˆ๋‹ค๋ฉด, ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋น„๋Ÿ‰์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๊ฐ€๋น„์ง€ ์ˆ˜์ง‘์€ ๋ชจ๋“  ์˜ค๋ž˜๋œ ๊ฐ์ฒด๋ฅผ ์ฃฝ์ผ ๊ฒƒ์ด์ง€๋งŒ ํฐ ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ๊ฒƒ์€ ์—ฌ์ „ํžˆ ๋น„์šฉ์ด ๋“ญ๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

์ผ๋ฐ˜์ ์œผ๋กœ ๋ถˆ๋ณ€์˜ ํƒ€์ž…์„ ๊ณ ์ˆ˜ํ•˜๋Š” ๊ฒƒ์€ ๊ฝค ํ•ฉ๋ฆฌ์ ์ธ ์–ธ์–ด ๋””์ž์ธ์˜ ์„ ํƒ์ž…๋‹ˆ๋‹ค. ์‹ฌ์ง€์–ด ๋ชจ๋“  ๊ฒƒ์ด ๋ถˆ๋ณ€ ์ผ ๋•Œ ๋ฉ‹์ง€๊ฒŒ ๋ชจ๋ธ๋งํ•˜์ง€ ์•Š๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ๋ถˆ๋ณ€ ํ˜•์˜ ์žฅ์ ์€ ๋‹จ์ ๋ณด๋‹ค ํ›จ์”ฌ ์ค‘์š”ํ•˜๋ฉฐ ๋Œ€์•ˆ๋ณด๋‹ค ๋›ฐ์–ด๋‚˜๊ณ  ๋” ๋‚˜์€ ์ฝ”๋“œ์™€ ๋” ๋น ๋ฅธ ์‹คํ–‰ ํŒŒ์ผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ