1. 문법적 차이점
함수 상속 (프로토타입 체인 + 생성자 조합
함수 상속은 함수와 프로토타입을 활용하여 객체지향 상속을 구현하는 전통적인 방식입니다. 자바스크립트의 프로토타입 체인 메커니즘을 직접 활용하여 부모 객체의 메서드를 자식 객체가 상속받을 수 있도록 합니다.
구현 원리: 생성자 함수를 통해 객체를 생성하고, 프로토타입을 통해 메서드를 공유합니다. 속성은 생성자 내부에서 정의하고, 메서드는 프로토타입에 추가하여 메모리를 효율적으로 사용합니다.
// 부모 생성자
function Vehicle(model) {
this.model = model;
}
// 프로토타입에 메서드 정의
Vehicle.prototype.drive = function() {
return `${this.model}이(가) 주행 중입니다.`;
};
// 자식 생성자
function Car(model, doorCount) {
// 부모 생성자 호출하여 속성 상속
Vehicle.call(this, model);
this.doorCount = doorCount;
}
// 프로토타입 체인 연결
Car.prototype = Object.create(Vehicle.prototype);
Car.prototype.constructor = Car;
// 자식 클래스 고유 메서드
Car.prototype.honk = function() {
return `${this.model}이(가) 경적을 울립니다.`;
};
const myCar = new Car("Tesla", 4);
console.log(myCar.drive()); // "Tesla이(가) 주행 중입니다."
console.log(myCar.honk()); // "Tesla이(가) 경적을 울립니다."
클래스 상속 (ES6)
ES6에서 도입된 클래스 문법은 기존 프로토타입 기반 상속을 더 명확하고 직관적인 문법으로 감싸았습니다. extends 키워드를 사용하여 상속 관계를 명시적으로 표현합니다.
구현 원리: 클래스는 프로토타입 기반 상속의 문법적 설탕(syntactic sugar)입니다. 내부적으로는 여전히 프로토타입 체인을 사용하지만, 개발자는 더 깔끔한 문법으로 코드를 작성할 수 있습니다.
// 부모 클래스
class Vehicle {
constructor(model) {
this.model = model;
}
drive() {
return `${this.model}이(가) 주행 중입니다.`;
}
}
// 자식 클래스
class Car extends Vehicle {
constructor(model, doorCount) {
super(model); // 부모 클래스 생성자 호출
this.doorCount = doorCount;
}
honk() {
return `${this.model}이(가) 경적을 울립니다.`;
}
}
const myCar = new Car("Tesla", 4);
console.log(myCar.drive()); // "Tesla이(가)주행 중입니다."
console.log(myCar.honk()); // "Tesla이(가) 경적을 울립니다."
핵심 차이: 함수 상속은 프로토타입 체인과 call/apply를 직접 조작해야 하지만, 클래스 상속은 extends와 super 키워드로 상속 관계를 간단히 표현할 수 있습니다.
2. 내부 구현 메커니즘
함수 상속의 구현 방식:
- 프로토타입 체인: 생성자의 prototype 속성을 직접 수정하여 부모 메서드 상속
- 생성자 빌림: call() 또는 apply()를 사용하여 부모 생성자 실행
- 조합 상속: 프로토타입 체인과 생성자 호출을 결합하여 속성과 메서드 모두 상속
클래스 상속의 구현 방식:
- 문법적 설탕: 클래스는 실제 함수로 변환되어 프로토타입 기반으로 동작
- extends 키워드: 자식 클래스의 프로토타입을 자동으로 부모 클래스에 연결
- super 키워드: 부모 클래스의 생성자나 메서드를 명시적으로 호출
3. 부모 메서드 호출 방식
함수 상속에서 부모 메서드 호출:
// 자식 프로토타입에서 부모 메서드 수동 호출
Car.prototype.driveFaster = function() {
const baseDrive = Vehicle.prototype.drive.call(this);
return `${baseDrive} 빠르게行驶합니다!`;
};
클래스 상속에서 부모 메서드 호출:
class Car extends Vehicle {
driveFaster() {
const baseDrive = super.drive();
return `${baseDrive} 빠르게 주행합니다!`;
}
}
비고: 클래스 상속에서는 super 키워드를 통해 부모 메서드를 간단하게 호출할 수 있지만, 함수 상속에서는 프로토타입을 직접 참조하고 call()을 사용해야 합니다.
4. 실제 사용 시나리오
함수 상속이 적합한 경우:
- 레거시 프로젝트 유지보수
- ES5 호환성이 필요한 환경
- 프로토타입 체인을 세밀하게 제어해야 하는 상황
클래스 상속이 적합한 경우:
- 현대적인 자바스크립트 프로젝트
- 가독성과 유지보수성이 중요한 코드베이스
- ES6 이상 환경
5. 비교 요약
| 구분 |
함수 상속 |
클래스 상속 |
| 문법 복잡도 |
높음 - 프로토타입 수동 관리 |
낮음 - 키워드로 간소화 |
| 코드 가독성 |
중간 - 프로토타입 조작 복잡 |
높음 - 구조 명확 |
| 브라우저 지원 |
모든 환경 |
ES6+ 또는 트랜스파일 필요 |
| 유연성 |
높음 - 커스터마이징 자유로움 |
보통 - 클래스 문법 제약 |
| 성능 |
유사 |
유사 |
결론: modern 자바스크립트 개발에서는 클래스 상속을 사용하는 것이 일반적입니다. 그러나 함수 상속의 원리를 이해하는 것은 자바스크립트의 프로토타입 체인 메커니즘을 파악하는 데 필수적입니다.