๐Ÿ“– ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ(feat. ๋‚ด๋ถ€ ์Šฌ๋กฏ, ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ)

๊ธฐ๋ก์ผ๊ธฐ๐Ÿ“ซยท2020๋…„ 12์›” 16์ผ
3

Javascript ๊ฐœ๋…์ •๋ฆฌ

๋ชฉ๋ก ๋ณด๊ธฐ
6/15

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

์ด ํฌ์ŠคํŒ…์€ ์ด์˜น๋ชจ๋‹˜์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ deep dive 16์žฅ์„ ์ฐธ์กฐํ•˜์—ฌ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋ณธ๋ฌธ ์ค‘ ํ‹€๋ฆฐ ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€์„ ํ†ตํ•ด ์•Œ๋ ค์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Š


๋‚ด๋ถ€ ์Šฌ๋กฏ , ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ

ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์— ๋Œ€ํ•ด ์–˜๊ธฐ ํ•˜๊ธฐ ์ „์—, ์›ํ™œํ•œ ์ดํ•ด๋ฅผ ์œ„ํ•ด ๋จผ์ € ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋‚ด๋ถ€ ์Šฌ๋กฏ๊ณผ ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด์ž.๐Ÿ˜๐Ÿ˜

๋‚ด๋ถ€ ์Šฌ๋กฏ๊ณผ ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ECMAScript์—์„œ ์ •์˜ํ•œ ์˜์‚ฌ ํ”„๋กœํผํ‹ฐ(pseudo property)์™€ ์˜์‚ฌ ๋ฉ”์„œ๋“œ(pseudo method)์ด๋‹ค.

์ฆ‰ ECMAScript ์‚ฌ์–‘์— ๋“ฑ์žฅํ•˜๋Š” [[...]]๋กœ ๊ฐ์‹ผ ์ด๋ฆ„๋“ค์ด ๋‚ด๋ถ€ ์Šฌ๋กฏ๊ณผ ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ์ด๋‹ค.

์กฐ๊ธˆ ์‰ฝ๊ฒŒ ์ด์•ผ๊ธฐ ํ•˜๋ฉด ECMAScript ๋ฌธ์„œ์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋‚ด๋ถ€ ๋™์ž‘์˜ ์„ค๋ช…์„ ์œ„ํ•ด ์ •์˜ํ•ด ๋†“์€ ๊ฐ€์ƒ ๋ฉ”์†Œ๋“œ๋ผ๊ณ  ์ดํ•ดํ•˜๋ฉด ๋  ๋“ฏ ํ•˜๋‹ค.

They are defined by this specification purely for expository purposes.

However, each object within an implementation of ECMAScript must behave as specified by the internal methods associated with it.

The exact manner in which this is accomplished is determined by the implementation.

ECMAScript ๋ฌธ์„œ์—์„œ ๋ฐœ์ทŒํ•œ ๋‚ด๋ถ€ ์Šฌ๋กฏ ์ •์˜์ธ๋ฐ, ํ•ด์„ํ•ด ๋ณด๋ฉด '๋‚ด๋ถ€ ์Šฌ๋กฏ์€ ์„ค๋ช…์„ ๋ชฉ์ ์œผ๋กœ ์ •์˜๋˜์—ˆ์ง€๋งŒ ์‹ค์ œ๋กœ ๋‚ด๋ถ€์—์„œ ๊ด€๋ จ ๋ฉ”์„œ๋“œ์— ์˜ํ•ด ๋ช…์‹œ๋œ ๋Œ€๋กœ ๋™์ž‘ํ•œ๋‹ค' ๋ผ๊ณ  ์จ์žˆ๋‹ค.

๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ์‹ค์ œ๋กœ๋Š” ์—†์ง€๋งŒ ๋น„์Šทํ•œ๊ฑด ์žˆ๋Š”( ๐Ÿคทโ€โ™‚๏ธ ?) ์กด์žฌ๋ผ๊ณ  ์ดํ•ดํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.


๋‚ด๋ถ€ ์Šฌ๋กฏ๊ณผ ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์˜ ๋‚ด๋ถ€ ๋กœ์ง์ด๋ฏ€๋กœ ์ง์ ‘์ ์œผ๋กœ ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๊ฒƒ์ด ์›์น™์ด๋‚˜, [[prototype]]๊ณผ ๊ฐ™์€ ์ผ๋ถ€ ๋‚ด๋ถ€ ์Šฌ๋กฏ๊ณผ ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ์— ํ•œํ•˜์—ฌ ๊ฐ„์ ‘์ ์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋‹จ์„ ์ œ๊ณตํ•œ๋‹ค. (ex : object.__proto__)


์ด์ œ ์‚ฌ์ „์ง€์‹์„ ํ•™์Šตํ–ˆ์œผ๋‹ˆ, ๋ณธ๊ฒฉ์ ์œผ๋กœ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž!

ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ

๊ฐ์ฒด๊ฐ€ ๊ฐ–๋Š” ํ”„๋กœํผํ‹ฐ์˜ ์ข…๋ฅ˜๋Š” ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ, ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋กœ ๋‘๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ž€ ์ด๋Ÿฌํ•œ ๊ฐ์ฒด ๋‚ด๋ถ€์˜ ๊ฐ๊ฐ์˜ ํ”„๋กœํผํ‹ฐ๋“ค์— ๋Œ€ํ•ด์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ๊ด€๋ฆฌํ•˜๋Š” ์†์„ฑ๊ฐ’์ด๋‹ค.

ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๊ฐ€ ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ๋ƒ, ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋ƒ์— ๋”ฐ๋ผ ์—ฐ๊ด€๋œ ๋‚ด๋ถ€ ์Šฌ๋กฏ์ด ๋‹ฌ๋ผ์ง„๋‹ค.

๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ(Data property)

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์€ ๊ฐ์ฒด์˜ ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ƒ์„ฑ๋ ๋•Œ ์ž๋™์œผ๋กœ ํ”„๋กœํผํ‹ฐ์˜ ์†์„ฑ๊ฐ’๋“ค์„ ์ •์˜ํ•œ๋‹ค.

๊ตฌ์ฒด์ ์ธ ๊ฐ’์œผ๋กœ๋Š” ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•ด ๊ฐ’์„ ๊ฐฑ์‹  ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•  ๊ฒƒ์ธ์ง€([[writable]]), ์—ด๊ฑฐ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•  ๊ฒƒ์ธ์ง€([[enumarable]]), ์žฌ์ •์˜ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•  ๊ฒƒ์ธ์ง€([[configurable]])๊ฐ€ ์žˆ๋‹ค.

๋ง๋กœ ์„ค๋ช…ํ•ด ๋†“์œผ๋‹ˆ ์ข€ ์–ด๋ ค์šด๋ฐ, Object.getOwnPropertyDescriptor ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ„์ ‘์ ์œผ๋กœ ํ™•์ธ ํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์‚ดํŽด๋ณด์ž.


const person = {
  name: "Lee",
};

console.log(Object.getOwnPropertyDescriptor(person, "name"));
// { value: 'Lee', writable: true, enumerable: true, configurable: true }

์œ„ ์ฝ”๋“œ์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด person ๊ฐ์ฒด์— name ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ๋ฅผ ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค. (์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ์ž๋™์ ์œผ๋กœ value, writable, enmuerable, configurable attribute๋ฅผ ์ •์˜ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค๋„ ๊ฐ™์ด ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค!)

๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๊ฐ€ ๊ฐ–๋Š” ๊ฐ๊ฐ์˜ ์†์„ฑ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Object.defineProperty๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•œ ์†์„ฑ๊ฐ’์„ ์ง์ ‘ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์ •๋ง ์ˆ˜์ •์ด๋‚˜ ์‚ญ์ œ๊ฐ€ ์•ˆ๋˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š”์ง€ ํ•œ๋ฒˆ ์‹คํ—˜ํ•ด๋ณด์ž!

const test = {};

Object.defineProperty(test, "cannotEdit", {
  value: "cannotEdit",
  writable: false,
  enumerable: true,
  configurable: false,
});

console.log(test); // { cannotEdit: 'cannotEdit' }

test.cannotEdit = "try edit..."; // ๋ณ€๊ฒฝ ์‹œ๋„
console.log(test); // { cannotEdit: 'cannotEdit' }

delete test.cannotEdit; // ์‚ญ์ œ ์‹œ๋„
console.log(test); // { cannotEdit: 'cannotEdit' }

์œ„์™€ ๊ฐ™์ด ์‹ค์ œ๋กœ writable์„ false๋กœ ์ •์˜ํ•˜๋ฉด, cannnotEdit์ด๋ž€ property์˜ value๋ฅผ ์ˆ˜์ •ํ•ด๋„ ์ˆ˜์ •๋˜์–ด์ง€์ง€ ์•Š๊ณ  ๋ฌด์‹œ๋œ๋‹ค.

์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ(Accessor property)

๋‘๋ฒˆ์งธ๋กœ ์‚ดํŽด๋ณผ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋Š” ์ ‘๊ทผ์ž ํ•จ์ˆ˜๋กœ ๊ตฌ์„ฑ๋œ ํ”„๋กœํผํ‹ฐ๋กœ, ์ž์ฒด์ ์œผ๋กœ๋Š” ๊ฐ’์„ ๊ฐ–์ง€ ์•Š์œผ๋ฉฐ ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ์ฝ๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋„ ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ์˜ set๊ณผ get์„ ์ง์ ‘ ์ •์˜ํ•ด์„œ ์‚ฌ์šฉํ•ด๋ณด๋ฉฐ ์ดํ•ดํ•ด๋ณด์ž!

test = {
  first: "java",
  second: "script",

  get firstPlusSecond() {
    // get์„ ์ง์ ‘ ์ •์˜
    return `${this.first}${this.second}`;
  },

  set firstPlusSecond(name) {
    // set์„ ์ง์ ‘ ์ •์˜
    [this.first, this.second] = name.split(" ");
  },
};

descriptor = Object.getOwnPropertyDescriptor(test, "firstPlusSecond");
console.log("firstPlusSecond", descriptor);

/* firstPlusSecond {
  get: [Function: get firstPlusSecond],
  set: [Function: set firstPlusSecond],
  enumerable: true,
  configurable: true
} */

console.log(test.firstPlusSecond); 
// [[get]]์ด ํ˜ธ์ถœ๋˜์–ด javascript๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

test.firstPlusSecond = "Type script";
// [[set]]์ด ํ˜ธ์ถœ๋˜์–ด first์™€ second์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•œ๋‹ค.

console.log(test.firstPlusSecond); 
// [[get]]์ด ํ˜ธ์ถœ๋˜์–ด Typescript๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ get๊ณผ set์„ ์ •์˜ํ•˜์—ฌ first์™€ second์— ์ง์ ‘ ์ ‘๊ทผํ•ด ๋ณด๊ณ  ๋ณ€๊ฒฝํ•ด๋ณด์•˜๋‹ค.

์ด์ฒ˜๋Ÿผ ๊ฐ์ฒด์— ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ ํ•จ์ˆ˜์ธ get๊ณผ set์„ ์ •์˜ํ•ด ๋†“์œผ๋ฉด, ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ์— ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ๋•Œ๋Š” get ์„ ํ˜ธ์ถœํ•˜๊ณ , ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ์— ๊ฐ’์„ ์ €์žฅํ• ๋•Œ๋Š” set์„ ํ˜ธ์ถœ ํ•œ๋‹ค!

์ •๋ฆฌ

๋‚ด๋ถ€ ์Šฌ๋กฏ & ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ๋ถ€ํ„ฐ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๊นŒ์ง€ ๋‚ด์šฉ์ด ์ข€ ๋งŽ์•˜๋‹ค.
๋งˆ์ง€๋ง‰์œผ๋กœ ํ•œ๋ฒˆ ์ •๋ฆฌํ•ด๋ณด์ž.

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

๋งˆ์น˜๋ฉฐ

์ด๋ฒˆ ํฌ์ŠคํŒ…์€ ๋‚ด๋ถ€ ์Šฌ๋กฏ, ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋“ฑ ์ƒ์†Œํ•œ ๊ฐœ๋…์ด ๋‚˜์™€์„œ ์กฐ๊ธˆ ์ดํ•ด๊ฐ€ ์–ด๋ ค์› ๋‹ค.
๊ทธ๋ž˜๋„ ํฌ์ŠคํŒ…์„ ์ž‘์„ฑํ•˜๋ฉด์„œ ํ—ท๊ฐˆ๋ ธ๋˜ ๋‚ด์šฉ๋“ค์ด ์กฐ๊ธˆ ์ •๋ฆฌ๊ฐ€ ๋œ ๊ธฐ๋ถ„์ด๋‹ค!

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํ•ต์‹ฌ์ธ ๊ฐ์ฒด์ธ ๋งŒํผ ์ˆจ๊ฒจ์ง„ ๊ฐœ๋…๋“ค์ด ๋งŽ์€ ๊ฒƒ ๊ฐ™๋‹ค. ์ฐจ๊ทผ์ฐจ๊ทผ ๊ณต๋ถ€ํ•˜๋ฉฐ ์ •๋ณตํ•ด ๋ด์•ผ์ง€.

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