[JS ν”„λ‘œν† νƒ€μž…] μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν”„λ‘œν† νƒ€μž… 훑어보기

    [JS ν”„λ‘œν† νƒ€μž…] μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν”„λ‘œν† νƒ€μž… 훑어보기


    이번 ν¬μŠ€νŒ…μ—μ„œλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ(JavaScript)ν•˜λ©΄ 빠질 수 μ—†λŠ” ν”„λ‘œν† νƒ€μž…(Prototype)에 λŒ€ν•΄μ„œ ν•œλ²ˆ 이야기해보렀고 ν•œλ‹€.

    ν”„λ‘œν† νƒ€μž…μ€ μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό ES5 μ‹œμ ˆλΆ€ν„° μ‚¬μš©ν•΄μ˜€λ˜ λΆ„λ“€μ—κ²ŒλŠ” 맀우 μ΅μˆ™ν•˜μ§€λ§Œ ES6λΆ€ν„° μ‹œμž‘ν•˜μ‹  뢄듀은 λŒ€λΆ€λΆ„ 클래슀λ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— μ΅μˆ™ν•œ κ°œλ…μ€ 아닐 것이라고 μƒκ°ν•œλ‹€.

    ν•„μžκ°€ 처음 ν”„λ‘ νŠΈμ—”λ“œ κ°œλ°œμ„ μ‹œμž‘ν–ˆμ„λ•ŒλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ES5 λ²„μ „μ—μ„œ 막 ES6둜 λ„˜μ–΄κ°€κ³  있던 μ‹œμ ˆμ΄μ—ˆλŠ”λ°, κΈ°μ‘΄μ—λŠ” μžλ°”(Java)λ₯Ό 주둜 μ‚¬μš©ν•˜κ³  있던 ν•„μžκ°€ ν”„λ‘ νŠΈμ—”λ“œ 개발둜 λ„˜μ–΄μ˜€λ©΄μ„œ 제일 μ• λ¨Ήμ—ˆλ˜ 뢀뢄이 λ°”λ‘œ 이 ν”„λ‘œν† νƒ€μž…μ΄μ—ˆλ‹€.(λ¬Όλ‘  μ• λ¨ΉλŠ” 건 ν˜„μž¬μ§„ν–‰ν˜•μ΄λ‹€)

    λ¬Όλ‘  μ§€κΈˆμ€ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μœ„μƒμ΄ 많이 μ˜¬λΌκ°€λ©΄μ„œ ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ— λŒ€ν•œ 관심도 λ§Žμ•„μ§€κΈ° μ‹œμž‘ν–ˆμ§€λ§Œ, κ·Έλž˜λ„ λ‹Ήμ‹œλ‚˜ μ§€κΈˆμ΄λ‚˜ μ—¬μ „νžˆ μ£Όλ₯˜λŠ” C 계열 μ–Έμ–΄λ‚˜ Javaμ—μ„œ μ‚¬μš©ν•˜λŠ” 클래슀λ₯Ό κΈ°λ°˜μœΌλ‘œν•œ 객체 생성 방식이닀.

    κ·Έλž˜μ„œ μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό 처음 μ ‘ν•˜λŠ” κ°œλ°œμžμ—κ²Œ ν”„λ‘œν† νƒ€μž… 기반 ν”„λ‘œκ·Έλž˜λ°μ€ μƒλŒ€μ μœΌλ‘œ λ‚―μ„  방식일 수 밖에 μ—†κ³ , 이둜 인해 κΈ°μ‘΄ κ°œλ°œμžλ“€μ΄ μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ μ§„μž…ν•˜λŠ”λ° 어렀움이 μžˆμ—ˆλ‹€. 그런 이유둜 ES6μ—μ„œλŠ” class μ˜ˆμ•½μ–΄κ°€ λ“±μž₯ν•œ 것이닀.

    사싀 ν•„μžλ„ 아직 클래슀 기반의 객체 생성 방식이 μ΅μˆ™ν•˜κΈ° λ•Œλ¬Έμ— ν”„λ‘œν† νƒ€μž…μ— λŒ€ν•œ 곡뢀가 더 ν•„μš”ν•˜λ‹€.

    κ·Έλž˜μ„œ 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ΄ 무엇인지, μžλ°”μŠ€ν¬λ¦½νŠΈ λ‚΄μ—μ„œ ν”„λ‘œν† νƒ€μž…μ΄ μ–΄λ–€ λ°©μ‹μœΌλ‘œ μ‚¬μš©λ˜κ³  μžˆλŠ”μ§€μ— μ§‘μ€‘ν•΄μ„œ ν•œλ²ˆ 이야기해보렀고 ν•œλ‹€.

    ES6λΆ€ν„° 클래슀λ₯Ό μ§€μ›ν•˜λŠ”λ°λ„ ν”„λ‘œν† νƒ€μž…μ„ ꡳ이 μ•Œμ•„μ•Ό ν•˜λ‚˜μš”?

    μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ES6λΆ€ν„° class ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 클래슀λ₯Ό μ§€μ›ν•˜κ³  μžˆλ‹€. μ •ν™•νžˆ λ§ν•˜λ©΄ ν”„λ‘œν† νƒ€μž…μœΌλ‘œ 클래슀λ₯Ό ν‰λ‚΄λ‚΄μ„œ κ΅¬ν˜„ν•œ 것이라고 λ§ν•˜λŠ” 것이 λ§žλ‹€.

    그런 이유둜 λ§Žμ€ κ°œλ°œμžλ“€μ΄ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 클래슀λ₯Ό λ‹¨μˆœν•œ 문법 섀탕(Syntactic Sugar)라고 μ΄μ•ΌκΈ°ν•˜μ§€λ§Œ, 사싀 개인적으둜 μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν΄λž˜μŠ€λŠ” ES5 μ‹œμ ˆ ν”„λ‘œν† νƒ€μž…μ„ μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό μƒμ„±ν–ˆλ˜ 방법보닀 더 μ—„κ²©ν•œ μ œμ•½μ„ 가지고 있기 λ•Œλ¬Έμ— λ‹¨μˆœν•œ 문법 μ„€νƒ•μ΄λΌκΈ°λ³΄λ‹€λŠ” μƒμœ„ μš”μ†Œ(Superset)라고 ν•˜λŠ”κ²Œ λ§žμ§€ μ•Šλ‚˜ μ‹Άλ‹€.

    그러면 κ·Έλƒ₯ 클래슀λ₯Ό μ“°λ©΄ λ˜λŠ”λ° μ™œ ν”„λ‘œν† νƒ€μž…μ„ μ•Œμ•„μ•Ό ν•˜λŠ” κ²ƒμΌκΉŒ?

    κ·Έ μ΄μœ λŠ” ES6μ—μ„œ class ν‚€μ›Œλ“œλ₯Ό 톡해 클래슀λ₯Ό μ§€μ›ν•˜κ³  μžˆκΈ°λŠ” ν•˜μ§€λ§Œ, 이건 μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ 클래슀 기반 μ–Έμ–΄κ°€ λ˜μ—ˆλ‹€λŠ” μ˜λ―ΈλŠ” μ•„λ‹ˆκΈ° λ•Œλ¬Έμ΄λ‹€. κ²°κ΅­ μžλ°”μŠ€ν¬λ¦½νŠΈ μ•ˆμ—μ„œμ˜ ν΄λž˜μŠ€λŠ” 클래슀의 νƒˆμ„ μ“΄ ν”„λ‘œν† νƒ€μž…μ΄λ‹€.

    그리고 μ˜ˆμ „μ— μž‘μ„±λœ λ ˆκ±°μ‹œ ν”„λ‘ νŠΈμ—”λ“œ μ½”λ“œμ˜ κ²½μš°μ—λŠ” ES5둜 μž‘μ„±λœ 것도 많기 λ•Œλ¬Έμ— μ•„μ§κΉŒμ§€ ν”„λ‘ νŠΈμ—”λ“œ κ°œλ°œμžλ“€μ€ ES5λ₯Ό λ§Œμ Έμ•Όν•˜λŠ” κ²½μš°κ°€ μ™•μ™• μžˆλŠ” 것이 ν˜„μ‹€μ΄λ‹€. λ¬Όλ‘  ES5λ₯Ό ES6 μ΄μƒμ˜ λ²„μ „μœΌλ‘œ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ν•˜λ €κ³  해도 기쑴의 ν”„λ‘œν† νƒ€μž… 기반의 객체 μƒμ„±μ΄λ‚˜ 상속이 κ΅¬ν˜„λœ μ½”λ“œλ₯Ό 이해할 수 μ—†λ‹€λ©΄ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ λ˜ν•œ λΆˆκ°€λŠ₯ν•˜λ‹€.

    ν”„λ‘œν† νƒ€μž…μ€ λ””μžμΈ νŒ¨ν„΄μ΄λ‹€

    ν”„λ‘œν† νƒ€μž…μ΄λΌκ³  ν•˜λ©΄ 일반적으둜 μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό λ– μ˜¬λ¦¬μ§€λ§Œ, 사싀 ν”„λ‘œν† νƒ€μž…μ€ μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλ§Œ μ‚¬μš©λ˜λŠ” 것은 μ•„λ‹ˆκ³ , κ·Έλƒ₯ μΌμ’…μ˜ λ””μžμΈ νŒ¨ν„΄ 쀑 ν•˜λ‚˜μ΄λ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈ 뿐만 μ•„λ‹ˆλΌ ActionScript, Lua, Perl λ“± ν”„λ‘œν† νƒ€μž… 기반 ν”„λ‘œκ·Έλž˜λ°μ„ μ§€μ›ν•˜λŠ” λ‹€λ₯Έ 언어도 λ§Žλ‹€.

    κ·Έλž˜μ„œ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν”„λ‘œν† νƒ€μž…μ„ μžμ„Ένžˆ μ•Œμ•„λ³΄κΈ° 전에 λ””μžμΈ νŒ¨ν„΄μœΌλ‘œμ¨μ˜ ν”„λ‘œν† νƒ€μž…μ„ λ¨Όμ € μ•Œμ•„λ³ΌκΉŒ ν•œλ‹€.

    ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ€ 객체λ₯Ό 효율적으둜 μƒμ„±ν•˜λŠ” 방법을 λ‹€λ£¨λŠ” νŒ¨ν„΄ 쀑 ν•˜λ‚˜μΈλ°, 주둜 객체λ₯Ό μƒμ„±ν•˜λŠ” λΉ„μš©μ΄ 클 λ•Œ 이λ₯Ό νšŒν”Όν•˜κΈ° μœ„ν•΄ μ‚¬μš©λœλ‹€.

    객체λ₯Ό 생성할 λ•Œμ˜ λΉ„μš©μ΄ ν¬λ‹€λŠ” 말은, 말 κ·ΈλŒ€λ‘œ 객체λ₯Ό 생성할 λ•Œλ§ˆλ‹€ λ­”κ°€ 일을 많이 ν•΄μ•Όν•œλ‹€λŠ” λœ»μ΄λ‹€.

    예λ₯Ό λ“€μ–΄ RPG κ²Œμž„μ˜ 캐릭터λ₯Ό ν•˜λ‚˜ κ΅¬ν˜„ν•΄λ³Έλ‹€κ³  μƒκ°ν•΄λ³΄μž. 이 μΊλ¦­ν„°λŠ” μ—¬λŸ¬κ°€μ§€ μž₯λΉ„λ₯Ό μž₯μ°©ν•  수 μžˆλŠ” κΈ°λŠ₯을 가지고 μžˆλŠ”λ°, 처음 캐릭터가 생성될 λ•Œ λ”Έλž‘ 맨 λͺΈμœΌλ‘œ μ‹œμž‘ν•˜λ©΄ μœ μ €λ“€μ΄ μ‹«μ–΄ν•  것 κ°™μœΌλ‹ˆ 기본적인 μž₯λΉ„ λͺ‡ 가지λ₯Ό μž₯μ°©ν•œ μƒνƒœλ‘œ 생성될 수 μžˆλ„λ‘ λ§Œλ“€μ–΄μ£Όλ €κ³  ν•œλ‹€.

    // Player.java
    class Weapon {}
    class Armor {}
    class BasicSward extends Weapon {}
    class BasicArmor extends Armor {}
    
    class Player {
        public Weapon weapon;
        public Armor armor;
    
        public Player() {
            this.weapon = new BasicSward(); // μ΄ˆμ‹¬μžμ˜ λͺ©λ„
            this.armor = new BasicArmor(); // 초보자용 κ°‘μ£Ό
        }
    }

    κ°„λ‹¨ν•˜κ²Œ λ§Œλ“€μ–΄λ³΄λ©΄ λŒ€μΆ© 이런 λŠλ‚Œμ΄λ‹€. Player κ°μ²΄λŠ” μžμ‹ μ΄ 생성될 λ•Œ BasicSward 객체와 BasicArmor κ°μ²΄κΉŒμ§€ ν•¨κ»˜ μƒμ„±ν•΄μ•Όν•œλ‹€.

    이런 경우 κ·Έλƒ₯ Player 객체만 μƒμ„±ν•˜λŠ” μƒν™©λ³΄λ‹€λŠ” 객체의 생성 λΉ„μš©μ΄ λ†’λ‹€κ³  ν•  수 μžˆλ‹€. κ²Œλ‹€κ°€ 캐릭터 생성 μ‹œ 처음 λΆ€μ—¬ν•˜λŠ” μ•„μ΄ν…œμ˜ μ’…λ₯˜κ°€ λ§Žμ•„μ§ˆμˆ˜λ‘ Player의 객체의 생성 λΉ„μš© λ˜ν•œ 계속 λ†’μ•„μ§ˆ 것이닀.

    μŒβ€¦ 근데 곰곰히 μƒκ°ν•΄λ³΄λ‹ˆ 캐릭터가 처음 μƒμ„±λ˜λ©° 가지고 μžˆλŠ” μ•„μ΄ν…œμ΄ 항상 κ°™λ‹€λŠ” μ „μ œ 쑰건이 μžˆλ‹€λ©΄ 생성 λΉ„μš©μ΄ 높은 Player객체λ₯Ό λ”± ν•œλ²ˆλ§Œ μƒμ„±ν•˜κ³  κ·Έ λ‹€μŒλΆ€ν„°λŠ” μƒμ„±λœ 객체λ₯Ό λ³΅μ‚¬ν•΄μ„œ μ‚¬μš©ν•΄λ„ 될 것 κ°™λ‹€λŠ” 생각이 λ“ λ‹€.

    // 이건 λ„ˆλ¬΄ 객체 생성 λΉ„μš©μ΄ λ†’μœΌλ‹ˆκΉŒ...
    Player evan = new Player();
    Player john = new Player();
    Player wilson = new Player();
    
    // 이런 λ°©λ²•μœΌλ‘œ μ ‘κ·Όν•΄λ³΄λŠ” 것은 μ–΄λ–¨κΉŒ?
    Player player = new Player();
    Player evan = player.clone();
    Player john = player.clone();
    Player wilson = player.clone();

    이런 κ΄€μ μœΌλ‘œ μ ‘κ·Όν•˜λŠ” 것이 λ°”λ‘œ ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ΄λΌκ³  ν•  수 μžˆλ‹€. ν”„λ‘œν† νƒ€μž…, 즉 원본 객체가 μ‘΄μž¬ν•˜κ³  κ·Έ 객체λ₯Ό λ³΅μ œν•΄μ„œ μƒˆλ‘œμš΄ 객체λ₯Ό μƒμ„±ν•˜λŠ” 방법인 것이닀.

    μ‹€μ œλ‘œ μžλ°”μ—μ„œ ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ„ μ‚¬μš©ν• λ•Œ, 볡제 λŒ€μƒμ΄ λ˜λŠ” ν΄λž˜μŠ€λŠ” 보톡 Cloneable μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•œλ‹€. Cloneable μΈν„°νŽ˜μ΄μŠ€μ—λŠ” clone λ©”μ†Œλ“œκ°€ μ •μ˜λ˜μ–΄ 있기 λ•Œλ¬Έμ—, 이 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” ν΄λž˜μŠ€λŠ” λ°˜λ“œμ‹œ clone λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”©ν•΄μ„œ κ΅¬ν˜„ν•΄μ•Όν•œλ‹€.

    class Player implements Cloneable {
        //...
        @Override
        public Player clone () throws CloneNotSupportedException {
          return (Player)super.clone();
        }
    }

    clone λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•˜κ³ λ‚˜λ©΄ 이제 Player κ°μ²΄λŠ” 볡사 κ°€λŠ₯ν•œ 객체가 λœλ‹€. 즉, λ‹€λ₯Έ κ°μ²΄λ“€μ˜ 원본 객체가 될 수 μžˆλŠ” κΈ°λŠ₯을 κ°€μ§€κ²Œ λ˜μ—ˆλ‹€λŠ” 것이닀.

    μ΄μ œλΆ€ν„°λŠ” Player 객체λ₯Ό μΆ”κ°€λ‘œ μƒμ„±ν•˜κ³  싢을 λ•ŒλŠ” 기쑴에 μƒμ„±λ˜μ–΄ 있던 객체λ₯Ό κ·ΈλŒ€λ‘œ λ³΅μ‚¬ν•˜λ©΄ 되기 λ•Œλ¬Έμ— 높은 객체 생성 λΉ„μš©μ΄ λ“œλŠ” 것을 ν”Όν•  수 μžˆλ‹€.

    Player evan = new Player();
    Player evanClone = evan.clone();

    λ˜ν•œ Player κ°μ²΄λŠ” λ³΅μ‚¬λ˜μ–΄ μƒˆλ‘œμš΄ λ©”λͺ¨λ¦¬ 곡간을 ν• λ‹Ήλ°›μ§€λ§Œ, κΉŠμ€ 볡사λ₯Ό ν•˜μ§€ μ•ŠλŠ” 이상 Player객체가 가지고 μžˆλŠ” BasicSward 객체와 BasicArmor κ°μ²΄λŠ” μƒˆλ‘­κ²Œ μƒμ„±λ˜μ§€ μ•Šκ³  기쑴에 이 객체듀이 ν• λ‹Ήλœ λ©”λͺ¨λ¦¬ 곡간을 μ°Έμ‘°ν•˜κΈ°λ§Œ ν•œλ‹€.

    즉, 잘만 μ“΄λ‹€λ©΄ λ©”λͺ¨λ¦¬ 곡간을 μ•„λ‚„ μˆ˜λ„ μžˆλ‹€λŠ” 것이닀. μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ μ›μ‹œ μžλ£Œν˜•μ€ Call by value, κ·Έ μ™Έ μžλ£Œν˜•μ€ Call by referenceλ₯Ό μ‚¬μš©ν•˜λŠ” 것과 λ™μΌν•œ 원리이닀.

    μ—¬κΈ°κΉŒμ§€ λ“£κ³  λ‚˜μ„œ μ˜ˆμƒν•˜μ‹  뢄듀도 μžˆκ² μ§€λ§Œ, κ·Έ 말인 μ¦‰μŠ¨ 잠깐 정신쀄 놓고 μ½”λ”©ν•˜λ‹€λ³΄λ©΄ 이런 μŠ¬ν”ˆ 상황도 λ°œμƒν•  수 μžˆλ‹€λŠ” λœ»μ΄λ‹€.

    Player evan = new Player();
    try {
        Player evanClone = evan.clone();
        evanClone.weapon.attackPoint = 40;
    
        System.out.println("μ—λ°˜ 무기 곡격λ ₯ -> " + evan.weapon.attackPoint);
        System.out.println("μ—λ°˜ 볡사본 무기 곡격λ ₯ -> " + evanClone.weapon.attackPoint);
    }
    catch (Exception e) {
        System.err.println(e);
    }
    μ—λ°˜ 무기 곡격λ ₯ -> 40
    μ—λ°˜ 볡사본 무기 곡격λ ₯ -> 40
    overtime work 디버깅 지옥이 펼쳐진다...

    μ •λ¦¬ν•΄λ³΄μžλ©΄ ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ΄λž€, 객체λ₯Ό 생성할 λ•Œ 원본이 λ˜λŠ” 객체λ₯Ό λ³΅μ‚¬ν•΄μ„œ μƒμ„±ν•˜λŠ” νŒ¨ν„΄μ΄λΌκ³  ν•  수 μžˆλ‹€.

    λ¬Όλ‘  μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν”„λ‘œν† νƒ€μž…μ€ λ‹¨μˆœνžˆ λͺ‡ 개의 객체가 볡제 관계λ₯Ό κ°€μ§€λŠ” 것이 μ•„λ‹ˆλΌ, μžλ°”μŠ€ν¬λ¦½νŠΈ λ‚΄μ˜ λͺ¨λ“  객체 전체가 볡제 κ΄€κ³„λ‘œ μ–½ν˜€μžˆκΈ° λ•Œλ¬Έμ— μ΄κ²ƒλ³΄λ‹€λŠ” μ•½κ°„ 더 λ³΅μž‘ν•˜κΈ΄ ν•˜μ§€λ§Œ, 근본적인 원리 μžμ²΄λŠ” ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ„ 따라간닀.

    그럼 이제 μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ 객체λ₯Ό 생성할 λ•Œ ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ„ μ–΄λ–€ μ‹μœΌλ‘œ μ‚¬μš©ν•˜κ³  μžˆλŠ” 지 ν•œλ²ˆ μ•Œμ•„λ³΄λ„λ‘ ν•˜μž.

    μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν”„λ‘œν† νƒ€μž…

    μ•žμ„œ μ„€λͺ…ν–ˆλ“―이 ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ€ 객체λ₯Ό 생성할 λ•Œ μ‚¬μš©ν•˜λŠ” νŒ¨ν„΄μ΄λ‹€. ν•„μžκ°€ μœ„μ—μ„œ μ˜ˆμ‹œλ‘œ μ‚¬μš©ν•œ 언어인 μžλ°”λŠ” 클래슀 기반 ν”„λ‘œκ·Έλž˜λ°μ„ μ§€μ›ν•˜κΈ° λ•Œλ¬Έμ—, νŠΉμˆ˜ν•œ νŒ¨ν„΄μ„ μ‚¬μš©ν•΄μ•Όμ§€λ§Œ ν”„λ‘œν† νƒ€μž…μ΄λΌλŠ” κ°œλ…μ„ μ‚¬μš©ν•  수 μžˆλ‹€.

    κ·ΈλŸ¬λ‚˜ μ• μ΄ˆμ— ν”„λ‘œν† νƒ€μž… 기반 ν”„λ‘œκ·Έλž˜λ°μ„ μ§€μ›ν•˜λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ κ²½μš°μ—λŠ” μ• μ΄ˆμ— λͺ¨λ“  객체λ₯Ό 생성할 λ•Œ ν”„λ‘œν† νƒ€μž…μ„ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ—, 객체λ₯Ό μƒμ„±ν•˜κΈ°λ§Œ 해도 μœ„μ—μ„œ ν•„μžκ°€ μ„€λͺ…ν•œ ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ΄ μ μš©λœλ‹€.

    κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μš°μ„  μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ λ§ν•˜λŠ” 객체(Object)κ°€ 무엇인지, 그리고 κ·Έ 객체가 μƒμ„±λœλ‹€λŠ” 것이 무엇을 μ˜λ―Έν•˜λŠ” 것인지 μ•Œμ•„λ³Ό ν•„μš”κ°€ μžˆλ‹€.

    μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ 객체λ₯Ό μƒμ„±ν•˜λŠ” 방법

    컴퓨터 κ³΅ν•™μ—μ„œμ˜ 객체(Object)λŠ” ν˜„μ‹€μ˜ 사물을 ν”„λ‘œκ·Έλž¨μ— λ°˜μ˜ν•œ 것이닀. 즉, μ—¬λŸ¬ 개의 ν”„λ‘œνΌν‹°(νŠΉμ§•)와 λ©”μ†Œλ“œ(ν–‰μœ„)λ₯Ό 가지고 ν˜„μ‹€μ˜ 사물을 ν‰λ‚΄λ‚΄λŠ” 쑴재인 것이닀.

    클래슀 기반 μ–Έμ–΄μ—μ„œλŠ” 클래슀λ₯Ό μƒμ„±ν•˜κ³  κ·Έ 클래슀λ₯Ό μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό μƒμ„±ν•΄μ•Όν•˜μ§€λ§Œ, μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” κ°„λ‹¨ν•œ λ¬Έλ²•λ§ŒμœΌλ‘œ 객체λ₯Ό 생성할 수 μžˆλ‹€.

    const evan = {
      name: 'Evan',
      age: 29,
      say: function () {
        console.log(`Hi, I am ${this.name}!`);
      }
    };

    이런 방식을 μš°λ¦¬λŠ” λ¦¬ν„°λŸ΄(Literal)둜 객체λ₯Ό μ„ μ–Έν•œλ‹€κ³  ν•œλ‹€. λ¦¬ν„°λŸ΄μ€ μ†ŒμŠ€ μ½”λ“œμ˜ κ³ μ •λœ 값을 λŒ€ν‘œν•˜λŠ” μΌμ’…μ˜ 단좕어 같은 κ°œλ…μ΄κΈ° λ•Œλ¬Έμ—, μš°λ¦¬λŠ” κ°„λ‹¨ν•œ λ¬Έλ²•λ§ŒμœΌλ‘œ 객체λ₯Ό μƒμ„±ν–ˆλ‹€κ³  λŠλΌμ§€λ§Œ λ‚΄λΆ€μ μœΌλ‘œλŠ” 객체λ₯Ό μƒμ„±ν•˜λŠ” 일련의 λ§€μ»€λ‹ˆμ¦˜μ΄ μž‘λ™ν•˜κ³  μžˆλ‹€.

    예λ₯Ό λ“€μ–΄, λ‹€λ₯Έ μ–Έμ–΄μ—μ„œλŠ” 이런 λ¦¬ν„°λŸ΄ 문법을 μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό 생성할 λ•Œ λ‚΄λΆ€μ μœΌλ‘œ 클래슀λ₯Ό μ‚¬μš©ν•˜κ²Œλœλ‹€. 파이썬 같은 경우, λ”•μ…”λ„ˆλ¦¬λ₯Ό λ¦¬ν„°λŸ΄λ‘œ μ„ μ–Έν•˜κ³  νƒ€μž…μ„ 찍어보면 dict ν΄λž˜μŠ€κ°€ 좜λ ₯λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€.

    my_dict = {
        'name': 'Evan',
        'age': 29
    }
    type(my_dict)
    <class 'dict'>

    μš°λ¦¬λŠ” dict({ 'name': 'Evan', 'age': 29 })와 같이 클래슀λ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ‚¬μš©ν•˜μ§€μ•Šκ³  λ¦¬ν„°λŸ΄λ‘œ λ”•μ…”λ„ˆλ¦¬λ₯Ό μƒμ„±ν–ˆμ§€λ§Œ λ‚΄λΆ€μ μœΌλ‘œλŠ” μ œλŒ€λ‘œ dict 클래슀λ₯Ό μ‚¬μš©ν•΄μ„œ 객체λ₯Ό μƒμ„±ν–ˆλ‹€λŠ” 것이닀.

    μžλ°” λ˜ν•œ λ¦¬ν„°λŸ΄ 문법을 μ§€μ›ν•˜λŠ” λ°°μ—΄(Array)을 μ„ μ–Έν•œ ν›„ 좜λ ₯해보면 κ²°κ΅­ 클래슀λ₯Ό 기반으둜 λ°°μ—΄ 객체λ₯Ό μƒμ„±ν•œλ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€.

    String[] array = {"Evan", "29"};
    System.out.println(array);
    [Ljava.lang.String;@7852e922

    이 말인 μ¦‰μŠ¨, λ‹€λ₯Έ 언어와 λ§ˆμ°¬κ°€μ§€λ‘œ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 객체도 κ°‘μžκΈ° ν˜Όμžμ„œ λΏ… ν•˜κ³  μƒμ„±λ˜λŠ” 것이 μ•„λ‹ˆλΌ λΆ„λͺ…νžˆ λ­”κ°€λ₯Ό μ‚¬μš©ν•΄μ„œ λ§Œλ“€μ–΄λ‚΄κ³  μžˆλ‹€λŠ” 말이닀.

    ν•˜μ§€λ§Œ μžλ°”μŠ€ν¬λ¦½νŠΈμ—λŠ” ν΄λž˜μŠ€λΌλŠ” κ°œλ… μžμ²΄κ°€ μ—†λŠ”λ° 뭘 μ‚¬μš©ν•΄μ„œ 객체λ₯Ό λ§Œλ“€μ–΄λ‚΄κ³  μžˆλŠ” κ²ƒμΌκΉŒ?

    닡은 λ°”λ‘œ ν•¨μˆ˜(Function)이닀.

    μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ 객체가 μƒμ„±λ˜λŠ” 원리λ₯Ό 쑰금 더 νŒŒν—€μ³λ³΄κΈ° μœ„ν•΄μ„œ μœ„μ—μ„œ λ¦¬ν„°λŸ΄λ‘œ μ„ μ–Έν–ˆλ˜ evan 객체λ₯Ό μ΄λ²ˆμ—λŠ” λ‹€λ₯Έ λ°©λ²•μœΌλ‘œ 선언해보도둝 ν•˜κ² λ‹€.

    const evan = new Object({
      name: 'Evan',
      age: 29,
    });

    왠지 클래슀 기반 μ–Έμ–΄μ—μ„œ 클래슀λ₯Ό μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό μƒμ„±ν•˜λŠ” 것과 μœ μ‚¬ν•œ 문법이 λ‚˜νƒ€λ‚¬λ‹€. 이런 방식을 μƒμ„±μž(Constructor)λ₯Ό μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό μƒμ„±ν•œλ‹€κ³  ν•œλ‹€.

    클래슀 기반 언어라면 ObjectλŠ” ν΄λž˜μŠ€κ² μ§€λ§Œ, μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” ν΄λž˜μŠ€κ°€ μ•„λ‹Œ ν•¨μˆ˜μ΄λ‹€.

    즉, μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œμ˜ μƒμ„±μžλŠ” ν•¨μˆ˜κ°€ 가지고 μžˆλ‹€λŠ” 것이닀. μ €κ²Œ μ§„μ§œ ν•¨μˆ˜μΈμ§€ μ•Œκ³  μ‹ΆμœΌλ‹ˆ, λΈŒλΌμš°μ € μ½˜μ†” 창을 μ—΄κ³  Objectλ₯Ό ν•œλ²ˆ 좜λ ₯해보도둝 ν•˜κ² λ‹€.

    console.log(Object);
    console.log(typeof Object);
    Ζ’ Object() { [native code] }
    "function"

    음, μ½˜μ†”λ‘œ μ°μ–΄λ³΄λ‹ˆ ObjectλŠ” ν™•μ‹€ν•˜κ²Œ λΉΌλ°•μΊ”νŠΈ ν•¨μˆ˜κ°€ λ§žλ‹€.

    ν•„μžκ°€ 처음 μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•˜κΈ° μ‹œμž‘ν–ˆμ„ λ•Œ 받아듀이기 μ–΄λ €μ› λ˜ 뢀뢄이 λ°”λ‘œ 이 λΆ€λΆ„μ΄μ—ˆλ‹€.

    클래슀 기반 ν”„λ‘œκ·Έλž˜λ°μ— μ΅μˆ™ν–ˆλ˜ ν•„μžμ—κ²Œ new ν‚€μ›Œλ“œμ™€ μƒμ„±μžλŠ” 클래슀만 κ°€μ§ˆ 수 μžˆλŠ” κ²ƒμ΄μ—ˆλŠ”λ° κ°‘μžκΈ° λœ¬κΈˆμ—†μ΄ ν•¨μˆ˜κ°€ λ‚˜μ™€λ²„λ¦¬λ‹ˆ 받아듀이기 νž˜λ“€μ—ˆλ˜ 것 κ°™λ‹€.(λ¨Έλ¦¬λ‘œλŠ” μ•Œκ² λŠ”λ° λ§ˆμŒμ΄β€¦)

    μ–΄μ¨Œλ“  이제 μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ 객체λ₯Ό 생성할 λ•Œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œ μƒμ„±ν•œλ‹€λŠ” 것을 μ•Œκ²Œλ˜μ—ˆλ‹€. μ§€κΈˆκΉŒμ§€ μ•Œμ•„λ‚Έ λ‚΄μš©μ„ μ •λ¦¬ν•΄λ³΄μžλ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

    1. ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ΄λž€ 객체λ₯Ό 생성할 λ•Œ 원본 객체λ₯Ό λ³΅μ œν•˜μ—¬ μƒμ„±ν•˜λŠ” 방법이닀.
    2. μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 객체λ₯Ό 생성할 λ•Œ ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ„ μ‚¬μš©ν•œλ‹€.
    3. μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 객체λ₯Ό 생성할 λ•Œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œλ‹€.

    κ·Έλ ‡λ‹€λŠ” 것은 μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό 생성할 λ•Œ λ­”κ°€λ₯Ό μ°Έμ‘°ν•˜κ³  λ³΅μ œν•΄μ„œ 객체λ₯Ό μƒμ„±ν•œλ‹€λŠ” 말이닀. μ΄μ œλΆ€ν„° κ·Έ λ­”κ°€λ₯Ό μ•Œμ•„ λ³Ό μ‹œκ°„μ΄λ‹€.

    λ„λŒ€μ²΄ 뭘 λ³΅μ œν•΄μ„œ 객체λ₯Ό λ§Œλ“œλŠ” 걸까?

    사싀 λ””μžμΈ νŒ¨ν„΄μœΌλ‘œμ¨μ˜ ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ€ 생각보닀 κ·Έλ ‡κ²Œ 어렡지 μ•Šλ‹€. κ·Έμ € 객체λ₯Ό 생성할 λ•Œ 원본 객체λ₯Ό λ³΅μ œν•΄μ„œ μƒμ„±ν•œλ‹€λŠ” κ°œλ…μ΄κΈ° λ•Œλ¬Έμ΄λ‹€.

    λ§ˆμ°¬κ°€μ§€λ‘œ μžλ°”μŠ€ν¬λ¦½νŠΈ λ˜ν•œ λ­”κ°€λ₯Ό λ³΅μ œν•΄μ„œ μƒˆλ‘œμš΄ 객체λ₯Ό μƒμ„±ν•˜κ³  μžˆλ‹€. 그럼 이제 μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ λ„λŒ€μ²΄ 뭘 λ³΅μ œν•΄μ„œ 객체λ₯Ό μƒμ„±ν•˜κ³  μžˆλŠ” 것인지 μ•Œμ•„λ³΄κΈ° μœ„ν•΄ κ°„λ‹¨ν•œ ν•¨μˆ˜λ₯Ό ν•˜λ‚˜ 선언해보도둝 ν•˜κ² λ‹€.

    function User () {}
    
    const evan = new User();
    
    console.log(evan);
    console.log(typeof evan);
    User { __proto__: Object }
    object

    μœ„μ—μ„œ μ΄μ•ΌκΈ°ν–ˆλ“―μ΄ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό μƒμ„±ν•˜κΈ° λ•Œλ¬Έμ—, μ΄λ ‡κ²Œ 클래슀λ₯Ό μ‚¬μš©ν•˜λŠ” 것과 μœ μ‚¬ν•œ λŠλ‚ŒμœΌλ‘œ 객체λ₯Ό 생성할 수 μžˆλ‹€.

    κ·Έλ ‡λ‹€λ©΄ evan κ°μ²΄λŠ” λ¬΄μ—‡μœΌλ‘œλΆ€ν„° 볡제된 κ²ƒμΌκΉŒ? κ°„λ‹¨ν•˜κ²Œ μƒκ°ν•˜λ©΄ User ν•¨μˆ˜λΌκ³  μƒκ°ν•΄λ³Όμˆ˜ μžˆκ² μ§€λ§Œ, 사싀은 User ν•¨μˆ˜λ₯Ό λ³΅μ œν•œ 것이 μ•„λ‹ˆλΌ User ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž… 객체λ₯Ό λ³΅μ œν•œ 것이닀.

    surprise 이렇게 갑자기 프로토타입이 나온다고...?

    λœ¬κΈˆμ—†μ–΄μ„œ λ°”λ‘œ 이해가 μ•ˆλ  μˆ˜λ„ μžˆκ² μ§€λ§Œ, λ‹¨μˆœν•˜κ²Œ 생각해보면 쉽닀. λ§Œμ•½ 객체λ₯Ό μƒμ„±ν•˜λ©΄μ„œ ν•¨μˆ˜λ₯Ό λ³΅μ œν–ˆλ‹€λ©΄ μƒμ„±λœ κ°μ²΄λŠ” object νƒ€μž…μ΄ μ•„λ‹ˆλΌ function νƒ€μž…μ΄μ–΄μ•Ό ν•˜μ§€ μ•Šκ² λŠ”κ°€?

    ν•˜μ§€λ§Œ evan κ°μ²΄λŠ” object νƒ€μž…μ„ 가지고 μžˆλ‹€. 즉, 이 ν•¨μˆ˜ μžμ²΄κ°€ μ•„λ‹ˆλΌ λ‹€λ₯Έ 객체 νƒ€μž…μ˜ 무언가λ₯Ό λ³΅μ œν–ˆλ‹€λŠ” 것이고, κ·Έ 원본 객체가 User ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž… 객체인 것이닀.

    ν•„μžλŠ” User ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž…μ„ λͺ…μ‹œμ μœΌλ‘œ μ„ μ–Έν•˜μ§€ μ•Šμ•˜μ§€λ§Œ, μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν•¨μˆ˜κ°€ 생성될 λ•Œ μžλ™μœΌλ‘œ κ·Έ ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž… 객체(Prototype Object)도 ν•¨κ»˜ μƒμ„±ν•˜κ³  ν•΄λ‹Ή ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°μ— μ—°κ²°ν•΄λ‘”λ‹€.

    function User () {}
    
    console.log(User.prototype);
    console.log(typeof User.prototype);
    { constructor: f User(), __proto__: Object }
    object

    λΆ„λͺ…νžˆ ν•„μžλŠ” ν•¨μˆ˜λ§Œ μ„ μ–Έν–ˆλŠ”λ°, User.prototype ν”„λ‘œνΌν‹°μ— λ­”κ°€ 이것저것 가지고 μžˆλŠ” 객체 녀석이 1+1으둜 λΆ™μ–΄λ‚˜μ™”λ‹€. ν•¨μˆ˜λ₯Ό μƒμ„±ν•˜λ©΄ 무쑰건 κ·Έ ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž… 객체도 ν•¨κ»˜ μƒμ„±λœλ‹€λŠ” 것이 ν‚€ν¬μΈνŠΈλ‹€.

    그리고 이 ν”„λ‘œν† νƒ€μž… κ°μ²΄λŠ” ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œ μƒˆλ‘œμš΄ 객체λ₯Ό 생성할 λ•Œ 원본 객체 역할을 해쀄 객체λ₯Ό μ˜λ―Έν•œλ‹€.

    즉, new User()λΌλŠ” 문법을 μ‚¬μš©ν•˜μ—¬ μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“€κ²Œ 되면 User ν•¨μˆ˜ μžμ²΄κ°€ μ•„λ‹ˆλΌ User ν•¨μˆ˜κ°€ 생성될 λ•Œ ν•¨κ»˜ μƒμ„±λœ User ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž… 객체λ₯Ό λ³΅μ œν•΄μ„œ μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“ λ‹€λŠ” 것이닀.

    prototype evan 객체야, 내가 아니라 내 프로토타입 객체를 복제하렴

    μ΄λ•Œ User ν•¨μˆ˜κ°€ μƒμ„±λ˜λ©° ν•¨κ»˜ μƒμ„±λœ User ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž… 객체λ₯Ό ν”„λ‘œν† νƒ€μž… ν”„λ‘œνΌν‹°(Prototype Property)라고 ν•œλ‹€.

    그럼 이 ν”„λ‘œν† νƒ€μž… 객체가 가지고 μžˆλŠ” ν”„λ‘œνΌν‹°μΈ constructor와 __proto__λŠ” 뭘 μ˜λ―Έν•˜λŠ” 걸까?

    constructor

    ν•¨μˆ˜κ°€ μƒμ„±λ˜λ©° ν•¨κ»˜ μƒμ„±λœ ν”„λ‘œν† νƒ€μž… κ°μ²΄λŠ” λͺ¨λ‘ constructorλΌλŠ” ν”„λ‘œνΌν‹°λ₯Ό 가지고 μžˆλ‹€. 그리고 이 ν”„λ‘œνΌν‹°μ—λŠ” 이 ν”„λ‘œν† νƒ€μž… 객체가 생성될 λ•Œ μ„ μ–Έν–ˆλ˜ ν•¨μˆ˜κ°€ λ“€μ–΄μžˆλ‹€.

    console.log(User.prototype);
    {
      constructor: f User(),
      __proto__: Object
    }

    ν•¨μˆ˜λ₯Ό μ„ μ–Έν•˜λ©΄ ν•¨μˆ˜μ™€ ν•¨κ»˜ ν•΄λ‹Ή ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž… 객체도 ν•¨κ»˜ μƒμ„±λ˜λ©° 이 λ‘˜μ„ μ—°κ²°ν•˜κ²Œ λœλ‹€. μ΄λ•Œ ν•¨μˆ˜λŠ” ν”„λ‘œν† νƒ€μž… 객체의 constructor ν”„λ‘œνΌν‹°λ‘œ μ—°κ²°λ˜κ³ , ν”„λ‘œν† νƒ€μž… κ°μ²΄λŠ” ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°λ‘œ μ—°κ²°λ˜λŠ” 것이닀.

    prototype connection 함수와 프로토타입 객체는 서로 연결되어있다
    console.log(User.prototype.constructor === User);
    true

    이 μƒμ„±μž ν”„λ‘œνΌν‹°λŠ” 이 ν•¨μˆ˜λ₯Ό 톡해 μƒμ„±λœ 객체 μž…μž₯μ—μ„œ λ³΄μ•˜μ„ λ•Œ λ‚˜λ₯Ό λ§Œλ“€ λ•Œ μ–΄λ–€ ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜μ—ˆλƒ?λ₯Ό μ˜λ―Έν•œλ‹€. λ§Œμ•½ 이 연결이 μ—†λ‹€λ©΄ μƒˆλ‘œ μƒμ„±λœ κ°μ²΄λŠ” μžμ‹ μ„ λ§Œλ“€ λ•Œ μ–΄λ–€ μƒμ„±μž ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜μ—ˆλŠ”μ§€ μ•Œ μˆ˜κ°€ μ—†λ‹€.

    μƒˆλ‘­κ²Œ μƒμ„±λœ κ°μ²΄λŠ” μžμ‹ μ„ 생성할 λ•Œ μ–΄λ–€ 원본 객체λ₯Ό λ³΅μ‚¬ν–ˆλŠ”μ§€μ— λŒ€ν•œ λ§ν¬λŠ” 가지고 μžˆμ§€λ§Œ μ–΄λ–€ μƒμ„±μžκ°€ ν˜ΈμΆœλ˜μ—ˆλŠ”μ§€μ— λŒ€ν•œ λ§ν¬λŠ” 가지고 μžˆμ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€.

    ν•˜μ§€λ§Œ 원본 객체의 constuctor ν”„λ‘œνΌν‹°μ— μƒμ„±μž ν•¨μˆ˜κ°€ μ—°κ²°λ˜μ–΄μžˆκΈ° λ•Œλ¬Έμ— μƒˆλ‘­κ²Œ λ§Œλ“€μ–΄μ§„ κ°μ²΄λŠ” μžμ‹ μ˜ 원본 객체에 μ ‘κ·Όν•΄μ„œ 이 ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•¨μœΌλ‘œμ¨ μžμ‹ μ΄ λ§Œλ“€μ–΄μ§ˆλ•Œ μ–΄λ–€ μƒμ„±μž ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜μ—ˆλŠ”μ§€λ₯Ό μ•Œ 수 μžˆλ‹€.

    const evan = new User();
    console.log(evan.__proto__.constructor === User);
    true

    μ΄λ•Œ μƒμ„±λœ 객체가 μžμ‹ μ˜ 원본 객체에 μ ‘κ·Όν•  수 μžˆλŠ” ν”„λ‘œνΌν‹°κ°€ λ°”λ‘œ __proto__ ν”„λ‘œνΌν‹°μ΄λ‹€.

    __proto__

    방금 μƒμ„±μžλ₯Ό μ„€λͺ…ν•˜λ©΄μ„œ ν•¨μˆ˜λ₯Ό 톡해 μƒˆλ‘­κ²Œ μƒμ„±λœ κ°μ²΄λŠ” 원본 κ°μ²΄μ™€μ˜ 연결을 가지고 μžˆλ‹€κ³  ν–ˆλ‹€. μ΄λ•Œ 이 연결을 ν”„λ‘œν† νƒ€μž… 링크(Prototype Link)라고 ν•œλ‹€.

    Object.prototype을 μ œμ™Έν•œ μžλ°”μŠ€ν¬λ¦½νŠΈ λ‚΄μ˜ λͺ¨λ“  κ°μ²΄λŠ” 원본 객체λ₯Ό 기반으둜 λ³΅μ‚¬λ˜μ–΄ μƒμ„±λ˜μ—ˆκΈ° λ•Œλ¬Έμ—, μžμ‹ μ˜ 원본 객체둜 μ—°κ²°λ˜μ–΄μžˆλŠ” ν”„λ‘œν† νƒ€μž… 링크 λ˜ν•œ λͺ¨λ“  객체가 가지고 μžˆλ‹€. μ΄λ•Œ 이 링크가 λ‹΄κΈ°λŠ” ν”„λ‘œνΌν‹°κ°€ __proto__ ν”„λ‘œνΌν‹°μ΄λ‹€.

    Object.prototype.__proto__κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μ΄μœ λŠ” λ°‘μ—μ„œ ν›„μˆ ν•˜λ„λ‘ ν•˜κ² λ‹€. μš°μ„ μ€ 객체듀이 μžμ‹ μ˜ 원본 객체둜 ν†΅ν•˜λŠ” ν”„λ‘œν† νƒ€μž… 링크λ₯Ό 가지고 μžˆλ‹€λŠ” μ‚¬μ‹€μ—λ§Œ μ§‘μ€‘ν•˜μž.

    이 ν¬μŠ€νŒ…μ—μ„œλŠ” 이해λ₯Ό λ•κΈ°μœ„ν•΄ __proto__ ν”„λ‘œνΌν‹°λ₯Ό κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜κ³  μžˆλ‹€. κ·ΈλŸ¬λ‚˜ ν•΄λ‹Ή ν”„λ‘œνΌν‹°λŠ” ECMAScript 2015μ—μ„œλŠ” ν‘œμ€€μ΄μ—ˆμ§€λ§Œ ν˜„μž¬λŠ” ν‘œμ€€μ΄ μ•„λ‹ˆλ―€λ‘œ Object.getPrototypeOf()λ₯Ό μ‚¬μš©ν•˜λŠ” 것을 μΆ”μ²œν•œλ‹€.

    즉 User ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μƒμ„±ν•œ κ°μ²΄λŠ” User.prototype 객체λ₯Ό λ³΅μ‚¬ν•˜μ—¬ μƒμ„±λœ 객체이기 λ•Œλ¬Έμ—, 이 객체듀은 원본인 User.prototype 객체λ₯Ό μžμ‹ μ˜ __proto__ ν”„λ‘œνΌν‹°μ— μ—°κ²°ν•΄λ‘λŠ” 것이닀.

    function User () {}
    const evan = new User();
    console.log(evan.__proto__ === User.prototype);
    true

    κ·Έλ ‡λ‹€λ©΄ 이 ν”„λ‘œν† νƒ€μž… 링크λ₯Ό μ‚¬μš©ν•΄μ„œ 계속 ν•΄μ„œ 원본 객체λ₯Ό μΆ”μ ν•˜λ‹€λ³΄λ©΄, 결ꡭ은 μžλ°”μŠ€ν¬λ¦½νŠΈ λ‚΄μ˜ λͺ¨λ“  객체듀이 μ΅œμ’…μ μœΌλ‘œ μ–΄λ–€ 원본 객체λ₯Ό λ³΅μ‚¬ν•΄μ„œ μƒμ„±λœ 것인지 μ•Œ 수 μžˆμ§€ μ•Šμ„κΉŒ?

    ν”„λ‘œν† νƒ€μž… 체인

    μžλ°”μŠ€ν¬λ¦½νŠΈ λ‚΄μ˜ μ‚¬μš©λ˜λŠ” λͺ¨λ“  객체듀은 μ „λΆ€ 이런 ν”„λ‘œν† νƒ€μž… 기반 λ°©μ‹μœΌλ‘œ μ •μ˜λ˜κ³  μƒμ„±λœλ‹€. 즉, String, Boolean, Array와 같이 μš°λ¦¬κ°€ 일반적으둜 μ‚¬μš©ν•˜κ³  μžˆλŠ” 빌트인 객체듀도 λͺ¨λ‘ 같은 방식을 μ‚¬μš©ν•΄μ„œ λ§Œλ“€μ—ˆλ‹€λŠ” 것이닀.

    κ·Έλ ‡λ‹€λ©΄ 이 객체듀은 μ–΄λ–€ ν”„λ‘œν† νƒ€μž… 객체λ₯Ό λ³΅μ‚¬ν•΄μ„œ λ§Œλ“€μ–΄μ§„ κ²ƒμΌκΉŒ?

    String, Boolean, Arrayλ“  뭐가 됐든 μžλ°”μŠ€ν¬λ¦½νŠΈ 내에 μ‘΄μž¬ν•˜λŠ” λͺ¨λ“  것듀은 λ°”λ‘œ Object ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž…μΈ Object.prototype을 μ‹œμž‘μœΌλ‘œ ν•΄μ„œ λ³΅μ œλœλ‹€.

    μœ„μ—μ„œ __proto__λ₯Ό μ„€λͺ…ν•˜λ©΄μ„œ Object.prototype κ°μ²΄λŠ” ν”„λ‘œν† νƒ€μž… 링크, 즉 원본 객체둜 ν†΅ν•˜λŠ” 링크가 μ—†λ‹€κ³  μ΄μ•ΌκΈ°ν–ˆμ—ˆλŠ”λ°, κ·Έ μ΄μœ λŠ” λ°”λ‘œ Object.prototype이 λͺ¨λ“  κ°μ²΄λ“€μ˜ μ‘°μƒλ‹˜μ΄κΈ° λ•Œλ¬Έμ΄λ‹€.

    이게 정말인지 확인해보고 μ‹Άλ‹€λ©΄, 아무 κ°μ²΄λ‚˜ κ³¨λΌμž‘μ•„μ„œ κ·Έ 객체의 __proto__ ν”„λ‘œνΌν‹°λ₯Ό 톡해 μ­‰μ­‰ μ˜¬λΌκ°€λ³΄λ©΄ λœλ‹€.

    일단 λ§Œλ§Œν•œ String을 μ‚¬μš©ν•΄μ„œ 쑰상을 좔적해보렀고 ν•˜λŠ”λ°, String 객체λ₯Ό μƒμ„±ν•˜λŠ” ν•¨μˆ˜λΆ€ν„° μΆœλ°œν•  것인지, String ν•¨μˆ˜λ₯Ό 톡해 μƒμ„±λœ 객체뢀터 μΆœλ°œν•  것인지에 따라 μ‘°μƒκΉŒμ§€ μ˜¬λΌκ°€λŠ” 길이 달라진닀.

    String ν•¨μˆ˜μ™€ String κ°μ²΄λŠ” λ‹Ήμ—°νžˆ 원본이 λ˜λŠ” 객체도 λ‹€λ₯΄κΈ° λ•Œλ¬Έμ΄λ‹€. ν•„μžλŠ” κ·Έ 쀑 String 객체λ₯Ό 생성할 수 μžˆλŠ” String μƒμ„±μž ν•¨μˆ˜λ₯Ό μ„ νƒν–ˆλ‹€.

    const first = String.__proto__;
    const second = first.__proto__;
    
    console.log('첫번째 쑰상 -> ', first.constructor.name);
    console.log('λ‘λ²ˆμ§Έ 쑰상 -> ', second.constructor.name);
    첫 번째 쑰상 -> Function
    두 번째 쑰상 -> Object

    μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ λͺ¨λ“  ν•¨μˆ˜λŠ” μžμ‹ μ˜ μ›λ³ΈμœΌλ‘œ Function.prototype 객체λ₯Ό μ›λ³ΈμœΌλ‘œ 가진닀. 그리고 Function.prototype은 κ²°κ΅­ 객체이기 λ•Œλ¬Έμ—, λ‹Ήμ—°νžˆ μ›λ³ΈμœΌλ‘œ Object.prototype 객체λ₯Ό μ›λ³ΈμœΌλ‘œ 가진닀.

    그럼 μ—¬κΈ°μ„œ ν•œλ²ˆ 더 μ˜¬λΌκ°€λ©΄ μ–΄λ–»κ²Œ 될까?

    const third = second.__proto__;
    console.log(third.constructor.name);
    Uncaught TypeError: Cannot read property 'constructor' of null at <anonymous>:1:28

    μ•—, TypeErrorκ°€ λ°œμƒν–ˆλ‹€. μ—λŸ¬λ©”μ„Έμ§€λ₯Ό λ³΄μ•„ν•˜λ‹ˆ Object.prototype 객체의 원본 객체인 Object.prototype.__proto__λŠ” null인 λͺ¨μ–‘이닀.

    즉, Object의 μœ„λ‘œλŠ” 더 이상 쑰상이 μ—†λŠ” 것이닀. μ§€κΈˆ μ‚΄νŽ΄λ³Έ 이 관계λ₯Ό κ°„λ‹¨ν•œ λ‹€μ΄μ–΄κ·Έλž¨μœΌλ‘œ λ‚˜νƒ€λ‚΄μ–΄λ³΄λ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

    prototype chain

    λ­”κ°€ λ³΅μž‘ν•΄λ³΄μ΄μ§€λ§Œ 별 것 μ—†λ‹€. String ν•¨μˆ˜μ˜ 원본 κ°μ²΄λŠ” Function.prototype이닀. 그리고 const a = 'evan'κ³Ό 같이 μ„ μ–Έλœ String κ°μ²΄λŠ” μžμ‹ μ„ μƒμ„±ν•œ String ν•¨μˆ˜μ˜ String.prototype을 μ›λ³ΈμœΌλ‘œ κ°€μ§ˆ 것이고, String.prototype은 객체이기 λ•Œλ¬Έμ— λ‹Ήμ—°νžˆ Object.prototype을 μ›λ³ΈμœΌλ‘œ κ°€μ§€λŠ” 것이닀.

    μ΄λ ‡κ²Œ ν”„λ‘œν† νƒ€μž…μœΌλ‘œ 이루어진 κ°μ²΄λ“€μ˜ 관계λ₯Ό ν”„λ‘œν† νƒ€μž… 체인(Prototype Chain)이라고 ν•œλ‹€.

    마치며

    사싀 ν•„μžκ°€ ν”„λ‘œν† νƒ€μž…μ— λŒ€ν•œ ν¬μŠ€νŒ…μ„ μ“°λ €κ³  ν–ˆλ˜ μ΄μœ λŠ” μ–Όλ§ˆ μ „ λ©΄μ ‘μ—μ„œ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν”„λ‘œν† νƒ€μž…μ„ μ‚¬μš©ν•˜μ—¬ Private Static λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•˜λΌλŠ” 문제λ₯Ό λ°›μ•˜λ‹€κ°€ κ²°κ΅­ λͺ» ν’€μ—ˆκΈ° λ•Œλ¬Έμ΄λ‹€.

    μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν΄λ‘œμ €μ™€ ν”„λ‘œν† νƒ€μž…μ„ ν™œμš©ν•˜μ—¬ ν’€μ–΄μ•Όν•˜λŠ” λ¬Έμ œμ˜€λŠ”λ°, ν•„μžλŠ” κΈ°λ³ΈκΈ°κ°€ λΆ€μ‘±ν•œ λ‚˜λ¨Έμ§€ 풀어내지 λͺ»ν–ˆλ‹€.

    κ·Έλž˜μ„œ μ›λž˜λŠ” ν”„λ‘œν† νƒ€μž…μ„ μ‚¬μš©ν•œ λ‹€μ–‘ν•œ 상속 기법듀과 ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•œ λ©€λ²„μ˜ 은닉 등도 ν•¨κ»˜ μ†Œκ°œν•΄λ³΄λ €κ³  ν–ˆμ§€λ§Œ, 늘 κ·Έλ ‡λ“― λΆ„λŸ‰ 쑰절 μ‹€νŒ¨λ‘œ 인해 λ‹€λ₯Έ ν¬μŠ€νŒ…μ—μ„œ λ³„λ„λ‘œ 닀뀄야할 것 κ°™λ‹€.

    no think 사실 애초에 분량 조절 따위를 생각하고 쓰지 않는다

    ν•„μžμ²˜λŸΌ 기쑴의 클래슀 기반 객체 생성방식에 μ΅μˆ™ν•œ κ°œλ°œμžλ“€μ—κ²Œ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν”„λ‘œν† νƒ€μž…μ€ κ½€λ‚˜ λ³΅μž‘ν•˜κ²Œ λŠκ»΄μ§„λ‹€. λ””μžμΈ νŒ¨ν„΄μœΌλ‘œμ¨μ˜ ν”„λ‘œν† νƒ€μž…μ€ λ‹¨μˆœνžˆ 객체λ₯Ό λ³΅μ œν•΄μ„œ μƒˆλ‘œμš΄ 객체λ₯Ό μƒμ„±ν•œλ‹€λŠ” μ •λ„μ˜ κ°œλ…μ— κ·ΈμΉ˜μ§€λ§Œ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν”„λ‘œν† νƒ€μž… 체인은 그것보닀 훨씬 더 λ³΅μž‘ν•˜κ²Œ μ—°κ²°λ˜μ–΄μžˆκΈ° λ•Œλ¬Έμ΄λ‹€.

    ν•˜μ§€λ§Œ ν”„λ‘œν† νƒ€μž… μ²΄μΈμ΄λ‚˜ ν”„λ‘œν† νƒ€μž…μ„ μ‚¬μš©ν•œ 각쒅 상속 기법은 μ–΄λ ΅κ²Œ 느껴질 수 μžˆμ–΄λ„, ν”„λ‘œν† νƒ€μž…μ˜ λΌˆλŒ€ μžμ²΄λŠ” κ·Έλ ‡κ²Œ 어렡지 μ•Šλ‹€κ³  μƒκ°ν•œλ‹€.

    1. κ°μ²΄λŠ” ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œ λ§Œλ“€μ–΄μ§€κ³ , κ°μ²΄λŠ” ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž… 객체λ₯Ό λ³΅μ œν•˜μ—¬ μƒμ„±λœλ‹€.
    2. λͺ¨λ“  κ°μ²΄λŠ” μžμ‹ μ΄ μ–΄λ–€ 원본 객체λ₯Ό λ³΅μ œν•˜μ—¬ μƒμ„±λœ 것인지에 λŒ€ν•œ 정보λ₯Ό 가지고 μžˆλ‹€.

    λ¬Όλ‘  원본 객체에 λŒ€ν•œ 정보λ₯Ό λŸ°νƒ€μž„μ— λ™μ μœΌλ‘œ λ³€κ²½ν•  수 μžˆλŠ” λ“± λ³€νƒœκ°™μ€ 짓듀이 κ°€λŠ₯ν•˜κΈ°λ„ ν•˜κ³ , 이λ₯Ό μ‚¬μš©ν•œ λ‹€μ–‘ν•œ 기법듀도 μžˆκΈ°λŠ” ν•˜μ§€λ§Œ 기본은 κ²°κ΅­ μ € 두 가지라고 ν•  수 μžˆμ„ 것 κ°™λ‹€. λ‹€μŒ ν¬μŠ€νŒ…μ—μ„œλŠ” 본격적으둜 ν”„λ‘œν† νƒ€μž…μ„ μ‚¬μš©ν•œ 상속 기법과 객체의 ν”„λ‘œνΌν‹°λ₯Ό νƒμƒ‰ν•˜λŠ” 방법인 ν”„λ‘œν† νƒ€μž… 룩업 등에 λŒ€ν•΄μ„œ μ„€λͺ…ν•˜λ„λ‘ ν•˜κ² λ‹€.

    μ΄μƒμœΌλ‘œ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν”„λ‘œν† νƒ€μž… 훑어보기 ν¬μŠ€νŒ…μ„ λ§ˆμΉœλ‹€.

    Evan Moon

    🐒 거뢁이처럼 μ‚΄μž

    κ°œλ°œμ„ μž˜ν•˜κΈ° μœ„ν•΄μ„œκ°€ μ•„λ‹Œ κ°œλ°œμ„ 즐기기 μœ„ν•΄ λ…Έλ ₯ν•˜λŠ” κ°œλ°œμžμž…λ‹ˆλ‹€. μ‚¬μ†Œν•œ 생각 정리뢀터 νŠœν† λ¦¬μ–Ό, μ‚½μ§ˆκΈ° 정도λ₯Ό 주둜 끄적이고 μžˆμŠ΅λ‹ˆλ‹€.