C
JavaScript/고급/Lesson 20

프로토타입 — *JS 의 객체지향*

45분·theory
이 챕터
2/2

프로토타입 — *JS 의 객체지향*

🎯 이 lesson 을 읽고 나면

이 lesson 을 다 읽고 나면 아래 3가지를 자신 있게 할 수 있습니다.

  • ✅ prototype chain + __proto__ 의 동작
  • ✅ class 가 prototype 의 syntactic sugar 인 이유
  • ✅ Object.create vs new 키워드 비교

학습 목표를 체크리스트로 두고 다 답할 수 있게 되면 lesson 을 닫으세요.

프로토타입이 뭐냐

핵심 한 줄

JS 의 객체지향은 클래스 기반이 아닌 프로토타입 기반. 모든 객체는 자기 부모 객체 (프로토타입) 를 가지고, 메서드를 상속 받습니다.

다른 언어와 다른 점

python
# Python (클래스 기반)
class Animal:
    def speak(self): print("소리")

class Dog(Animal):
    pass

d = Dog()
d.speak()   # "소리" (Animal 에서 상속)
javascript
// JS (프로토타입 기반)
const animal = {
    speak() { console.log("소리"); }
};

const dog = Object.create(animal);   // animal 을 프로토타입으로
dog.speak();   // "소리" (animal 에서 찾음)

객체가 다른 객체를 직접 상속. 클래스라는 템플릿 단계 가 없습니다.

프로토타입 체인

javascript
const a = { x: 1 };               // 최상위 부모 — x 보유
const b = Object.create(a);        // b 의 부모 = a
const c = Object.create(b);        // c 의 부모 = b

console.log(c.x);   // 1
//
// 🔎 c.x 를 어떻게 찾았나? 위로 올라가며 탐색:
//   ① c 자기 자신 → x 없음
//   ② c 의 부모 b → x 없음
//   ③ b 의 부모 a → x = 1 발견! ✅
//
// 💡 이게 "프로토타입 체인" — JS 가 속성을 찾는 방식

요청하면 위로 올라가며 찾습니다. 이게 프로토타입 체인.

class 문법 — 겉치레

ES6 (2015) 부터 class 키워드 지원. 하지만 내부는 여전히 프로토타입.

javascript
class Animal {
    speak() { console.log("소리"); }
}

class Dog extends Animal {        // Animal 을 상속
    bark() { console.log("멍멍"); }
}

const d = new Dog();
d.speak();   // "소리"   ← Dog 에 없음 → Animal 에서 발견
d.bark();    // "멍멍"   ← Dog 에 있음 → 바로 사용

클래스 기반 언어 스타일 로 작성 가능. 하지만 알고 보면:

javascript
Dog.prototype.__proto__ === Animal.prototype;   // true
d.__proto__ === Dog.prototype;                   // true

프로토타입 체인 그대로.

자주 보는 프로토타입 메서드

javascript
const arr = [1, 2, 3];

// 🔎 arr 의 부모가 누구냐?
console.log(arr.__proto__ === Array.prototype);   // true
console.log(arr.map(x => x * 2));                 // [2, 4, 6]
//             ↑ map 은 arr 본인이 아닌 Array.prototype 에 정의됨!

const s = "hello";
console.log(s.__proto__ === String.prototype);    // true
console.log(s.toUpperCase());                     // "HELLO"
//             ↑ toUpperCase 도 String.prototype 에 정의돼서 공유됨

// 💡 모든 배열·문자열이 메서드를 "공유" → 각 인스턴스에 복사 X → 메모리 효율 ↑

모든 내장 메서드 (map·filter·toUpperCase 등) 가 프로토타입 에 정의돼 있어서 모든 배열·문자열이 공유. 메모리 효율 ↑.

직접 만들기

javascript
function Animal(name) {
    this.name = name;
}
Animal.prototype.speak = function() {
    console.log(`${this.name}: 소리`);
};

const a = new Animal("멍멍이");
a.speak();   // "멍멍이: 소리"

생성자 함수 방식. 지금은 class 문법이 더 깔끔 — 거의 항상 class 사용.

흔한 함정

1. arrow function 은 prototype 없음:

javascript
const Foo = () => {};
new Foo();   // ❌ TypeError

2. __proto__ 직접 조작 위험:

javascript
obj.__proto__ = anotherObj;   // 가능하지만 성능 ↓
// 대신 Object.create() 또는 Object.setPrototypeOf()

3. for...in 의 의외 동작:

javascript
for (const key in obj) { ... }
// 자신의 + *상속받은* 속성 모두 순회
// 자기 것만: Object.keys(obj) 또는 obj.hasOwnProperty(key)

한 번 정리

  • JS = 프로토타입 기반 객체지향
  • 모든 객체는 부모 (프로토타입) 보유
  • class문법 설탕 — 내부는 프로토타입
  • 상속·메서드 공유의 메커니즘

⚡ 직접 해보기 — class 상속 + 프로토타입 체인

클래스 상속이 내부적으로는 프로토타입 체인임을 직접 확인.
✏️ JS 코드
📟 콘솔 출력
▶ 실행 버튼을 눌러보세요
⚠️ 브라우저 샌드박스에서 실행 — console.log()만 지원, alert/fetch 불가

🤖 AI 에게 이렇게 요청해보세요

이 lesson 의 개념을 알면 AI 에게 구체적으로 지시할 수 있습니다. 막연한 "고쳐줘" 가 아니라 어휘를 가진 요청 — 그게 토큰 절약의 출발점입니다.

  • "이 변수에 적절한 TypeScript 타입 어노테이션 붙여줘"
  • "이 === 와 == 혼용을 === 로 통일하고 의도 명확히 해줘"
  • "이 코드의 JSON.parse 결과에 unknown 타입 + 타입 가드 추가해줘"

왜 이게 토큰을 줄이나

개념을 모를 땐 AI 답변을 받고도 "그게 뭐예요?" 를 다시 물어야 합니다. 그 "다시 물음" 이 토큰을 잡아먹습니다. 개념 한 번 익혀두면 대화가 한 번에 끝납니다.

프로토타입 - JavaScript