티스토리 뷰
프로토타입(Prototype)
자바스크립트는 prototype 기반의 객체지향 프로그래밍 언어이다.
프로토타입의 직역은 '원형'입니다.
이름 그대로 프로토타입은 다른 객체로부터 상속을 받는 객체의 원형을 나타냅니다.
만들어진 객체는 또 다른 프로토타입으로 다른 객체의 원형으로 사용될 수 있죠.
[[Prototype]]
자바스크립트의 모든 객체는 내부슬롯 [[Prototype]]을 가지는데요.
여기에는 해당 객체의 프로토타입에 대한 참조가 저장됩니다.
참조될 프로토타입이 없다면? null이 할당됩니다.
[[Prototype]]은 개발자가 명시적으로 선언하지 않아도 객체 생성 시 자바스크립트 엔진이 알아서 할당해 줍니다! ✌️
내부슬롯?
자바스크립트 엔진이 객체의 내부 상태를 관리하기 위해 사용하는 비공개 슬롯입니다.
내부 슬롯은 자바스크립트 코드에서 직접 접근할 수 없으며, 대부분의 경우 자바스크립트 엔진 내부에서만 관리됩니다.
프로토타입 체이닝
프로토타입 체이닝은 자바스크립트 상속의 주요 동작입니다.
자바스크립트에서 어떠한 객체의 프로퍼티(메서드를 포함)에 접근하려고 할 때, 해당 객체에 프로퍼티가 존재하지 않는다면
[[Prototype]] 내부 슬롯의 참조를 따라 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색하게 됩니다.
이처럼 프로퍼티를 찾기 위해 발생하는 검색 매커니즘을 프로토타입 체이닝이라 합니다.
아래 예시를 살펴보겠습니다.
// 부모 객체
var parent = {
greet: function() {
return 'Hello!';
}
};
// 자식 객체
var child = Object.create(parent);
// 자식 객체에서 부모의 메소드 사용
console.log(child.greet()); // Hello!
실행하면 Hello! 라는 출력 결과를 확인할 수 있습니다.
코드에서 parent 객체는 greet라는 프로퍼티를 가지고 있습니다. great는 'Hello!'라는 문자열을 반환하는 함수네요.
Object.create()는 지정된 프로토타입 객체 및 프로퍼티를 가진 새 객체를 생성하는 메서드입니다.
프로토타입을 parent로 지정해서 child 객체를 생성했습니다.
마지막 줄인 console.log(child.greet()); 를 실행하기 위해 자바스크립트는 child 객체에 greet 프로퍼티를 찾습니다.
child 내부에는 존재하지 않을겁니다. 명시적으로 추가하지 않았으니까요. 이때 프로토타입 체이닝이 일어납니다.
부모인 parent를 조회하는 거죠. 따라서 parent에 존재하는 greet를 확인하고,
함수가 실행되어 'Hello!'라는 문자열이 반환된 것입니다.
__proto__과 [[Prototype]]의 차이?
둘 다 객체의 프로토타입에 대한 참조를 나타내는 데 사용되고 기능적으로 거의 동일합니다.
__proto__은 이제 더 이상 권장되지 않나요?
네! ECMAScript 2015(ES6)부터는 공식적으로 폐지되었습니다. 💡
__proto__는 프로토타입 참조에 대한 getter, setter 역할을 했었는데요. 지금은 사용이 권장되지 않습니다!
대신 Object.getPrototypeOf()와 Object.setPrototypeOf() 메서드를 사용하여 프로토타입을 설정하거나 가져올 수 있습니다.
이제 자바스크립트에서 말하는 프로토타입이 무엇인지는 감이 오는 듯합니다.
근데 이거... 다른 언어의 클래스 역할과 유사하지 않나요?
왜 자바스크립트는 클래스가 아니라 프로토타입을 사용하죠? 🤔
자바스크립트와 프로토타입
그 이유는 자바스크립트가 접근한 철학적 사고방식에서 기원합니다.💡
클래스와 프로토타입은 객체를 바라보는 관점에 차이가 있습니다.
플라톤과 클래스
클래스 기반 객체지향 언어(Java, C# 등)에는 플라톤 철학이 녹아있습니다.
플라톤은 현실 세계에 존재하는 모든 것에는 반드시 본질(이데아)이 존재한다고 주장했습니다.
의자를 예로 들어보겠습니다. 우리 주위에는 수많은 형태 의자가 존재하죠.
나무 의자, 다리가 3개인 의자, 바퀴가 달린 의자 등등...
플라톤의 철학에서는 이런 의자들의 본질적인 '무언가'가 존재한다고 말합니다.
그리고 이 본질들의 세계를 이데아라고 했구요. 즉, 우리가 보고 있는 의자들은 이데아의 '의자'를 모방한 의자라는 거죠.
아리스토텔레스의 분류론
이러한 플라톤의 이데아 이론은 그의 제자 아리스토텔레스에 의해서 '분류(classification) 론'으로 정립되었습니다.
아리스토텔레스는 세상에 존재하는 모든 사물들을 사물끼리 서로 공유하는 속성들을 기준으로 분류하였습니다.
예를 들면 아래와 같습니다.
살아 움직이는 동물 중에서도, '물속에서 헤엄을 치고 공기 없이도 호흡이 가능한 동물들'은 '어류'에 해당된다.
'부리가 있고 날개가 있는 동물들'은 '조류'에 해당된다고 볼 수 있다.
즉, 유사한 속성(프로퍼티)을 공유하는 개체들을 일반화를 통해 클래스로 추상화될 수 있다고 보는 겁니다.
비트겐슈타인과 프로토타입
비트겐슈타인은 이러한 분류법, 개체들 사이에 공유되는 속성을 기반으로 분류를 시도하는
행위 자체에 근본적인 한계가 있다고 보았습니다.
조류로 예를 들어보겠습니다.
조류를 단순히 '부리가 있고 날개가 있는 동물들'로 볼 경우, 날개가 없는 키위새는 조류가 아니게 됩니다.
생물학자들이 키위새를 조류에 포함시키기 위해선 조류에 대한 분류법을 수정했어야겠죠?
이처럼 분류법은 예외가 발생할 때마다 공유 속성을 수정해야 했습니다.
비트겐슈타인은 이런 상황을 맹점으로 본 것이죠.
공유 속성의 관점에서 정의하기 어려운 개념이 있다(사실상 올바른 분류란 없다) — 비트겐슈타인
대신 비트겐슈타인은 가족유사성(family resemblance)에 기반을 둔 분류를 주장했습니다.
가족유사성 이론은 '개체들 사이에 존재하는 전형적인(typical) 속성들을 통해 이들을 동일한 범주로 간주할 수 있다'는 이론입니다.
따라서 하나의 범주 내에는 이러한 전형적인 속성을 유난히 많이 지닌 개체도 존재할 수 있고,
유난히 덜 지닌 개체도 존재할 수 있다고 보는 것이죠.
로쉬의 프로토타입 이론
이러한 관점을 발전시킨 것이 로쉬의 프로토타입 이론입니다.
로쉬는 사람들이 사물을 가족유사성이 높은 대로 등급을 매겨 분류한다고 설명하였습니다.
그리고 특정 범주의 모든 사물들 중 가장 전형적인 사물이 바로 해당 범주의 원형(prototype)이 된다는 거죠.
앞선 조류를 예로 좀 더 설명해 보겠습니다.
분류론에서는 '키위새'가 공유 속성에 맞지 않는다면, 조류가 아닌 것으로 분류를 해야했죠.
즉 '조류인가? 조류가 아닌가?' 하는 이분법적인 구조를 따라야 했습니다.
하지만 프로토타입에서는 다릅니다.
이분법적인 구조에서 벗어나 동일 범주 내에서 '얼마나 조류스러운가'의 측면으로 대상을 단계로 범주화 하는 거니까요.
'참새'를 조류의 범주를 대표할 만한 가장 전형적인 대상, 원형(prototype)으로 간주해 보면,
'키위새'는 '원형'에서 멀리 떨어진, 비전형적인 대상이 될 뿐입니다.
프로토타입 이론에서 중요한 다른 한 가지는 맥락(context)입니다.
조류학자가 보는 '참새'와 '키위새'는 명확하게 조류에 속할 겁니다.
아이가 볼 때도 그럴까요? 아이한테는 '키위새'가 더더욱 비전형적으로 느껴질 수 있겠죠.
즉, 같은 단어라 할지라도 누가 어떤 상황에서 접했나에 따라 의미가 달라진다는 것입니다.
정리
자바스크립트는 프로토타입 기반의 객체지향 프로그래밍 언어입니다.
프로토타입 이론이 언어의 핵심에 고스란히 녹아있죠.
프로토타입 기반 언어에서는 객체의 생성과 관련하여 분류(Classification)를 우선시하지 않습니다.
대신 이미 존재하는 객체를 기반으로 새로운 객체를 생성하며, 이를 통해 유사성을 정의합니다. ⭐
이는 프로토타입 체인을 통해 객체 간의 상속 관계를 구축하고, 객체를 확장하거나 수정할 수 있는 유연성을 제공합니다.
자바스크립트에서 어휘(lexical)와 쓰임새(usage)는 맥락에 따라 평가됩니다.
변수나 함수 등의 식별자는 렉시컬 스코프(lexical scope)에 따라 해석되며, 이는 코드 상 위치에 따라 결정됩니다.
또한 클로저, this, 호이스팅 등의 특징은 모두 실행 컨텍스트(Execution Context)와 스코프 체인과 관련된 개념입니다.
이들은 자바스크립트의 어휘와 쓰임새를 평가하는 맥락을 설명하고 이해하는 데 중요한 역할을 합니다.
이러한 특징들은 자바스크립트를 유연하고 강력한 프로그래밍 언어로 만들어주며,
객체지향 프로그래밍 패러다임을 다양한 방식으로 활용할 수 있도록 도와줍니다.
[참고자료]
감사합니다.
공부한 내용을 복습/기록하기 위해 작성한 글이므로 내용에 오류가 있을 수 있습니다.
'JS | Node.js' 카테고리의 다른 글
[JS] 자바스크립트의 변수 복사 (feat. 얕은복사, 깊은복사) (0) | 2024.03.13 |
---|---|
[JS] 자바스크립트가 데이터를 할당하는 방법 (feat. 불변성, 가변성) (0) | 2024.03.10 |
[JS] 함수형 프로그래밍(FP : Functional Programming) (0) | 2023.11.24 |
[JS]JavaScript와 Node.js (0) | 2023.11.07 |
[Node.js] npm과 package.json (0) | 2023.11.03 |