📘 16.2.3 상속 구현하기 - 부모님의 능력을 물려받기
프로그래밍을 배우는 여러분께 조용히 전해드립니다. 혹시 부모님과 닮은 점이 있나요? 눈이 아버지를 닮았거나, 목소리가 어머니를 닮았다는 이야기를 들어본 적이 있을 것입니다.
프로그래밍에서도 이처럼 부모의 특징을 자식이 물려받는 방법이 있습니다. 이것을 상속이라고 합니다. 오늘은 간단한 방법부터 차근차근 알아보겠습니다.
🧠 새로운 단어들과 친해지기
단어 | 쉬운 설명 |
---|---|
상속 | 부모가 가진 능력과 특징을 자식이 그대로 물려받는 것 |
부모 생성자 | 자신의 능력을 다른 생성자에게 물려주는 원본 |
자식 생성자 | 부모 생성자로부터 능력을 물려받는 새로운 생성자 |
프로토타입 연결 | 부모와 자식을 이어주는 특별한 연결고리 |
상속은 영어로 "Inheritance"라고 합니다. "Inherit"는 "물려받다"라는 뜻입니다. 마치 부모님의 유산을 물려받는 것처럼, 부모 객체의 능력을 자식 객체가 물려받는다는 의미를 담고 있습니다.
✨ 상속이 뭐예요?
상속은 부모가 가진 모든 것을 자식이 물려받는 것입니다. 하지만 자식은 부모의 것을 물려받으면서도 자신만의 새로운 능력을 추가할 수 있습니다.
예를 들어, 아버지가 운전을 할 수 있으면 자녀도 운전을 배울 수 있습니다. 거기에 더해서 자녀는 컴퓨터도 잘 다룰 수 있게 되는 것이지요.
마음속에 그려보는 이야기: 가족의 특기 물려받기
김씨 가문 이야기를 들려드리겠습니다.
할아버지는 농사짓기를 아주 잘했습니다. 아버지는 할아버지에게서 농사짓기를 배웠고, 거기에 더해서 기계 수리도 잘하게 되었습니다.
아들은 아버지에게서 농사짓기와 기계 수리를 모두 배웠고, 거기에 더해서 컴퓨터 프로그래밍도 배웠습니다.
- 할아버지 = 기본 생성자 (농사짓기)
- 아버지 = 첫 번째 상속 (농사짓기 + 기계 수리)
- 아들 = 두 번째 상속 (농사짓기 + 기계 수리 + 프로그래밍)
이처럼 각 세대가 이전 세대의 능력을 모두 물려받으면서 새로운 능력을 추가하는 것이 상속입니다.
🎯 왜 상속을 사용할까요?
1. 코드를 다시 사용할 수 있습니다
한 번 만든 좋은 기능을 여러 곳에서 사용할 수 있습니다. 마치 가족의 레시피를 대대로 물려받는 것처럼요.
2. 시간을 절약할 수 있습니다
처음부터 모든 것을 만들 필요가 없으니까 더 빠릅니다. 이미 있는 좋은 기능을 그대로 사용하면 되거든요.
3. 관리하기 쉽습니다
공통된 기능을 한 곳에서만 관리하면 됩니다. 할아버지의 농사 방법이 바뀌면 모든 후손이 자동으로 새로운 방법을 알게 되는 것처럼요.
4. 체계적으로 정리할 수 있습니다
비슷한 것들끼리 그룹을 만들어서 더 깔끔하게 정리할 수 있습니다.
⚙️ 간단한 상속 만드는 방법
먼저 가장 간단한 방법으로 상속을 만들어보겠습니다:
// 1단계: 부모 생성자 만들기
function Animal(name) {
this.name = name;
this.energy = 100;
}
// 2단계: 부모 메서드 추가하기
Animal.prototype.eat = function() {
this.energy += 10;
return this.name + "이(가) 먹어요. 에너지: " + this.energy;
};
Animal.prototype.sleep = function() {
this.energy += 20;
return this.name + "이(가) 자요. 에너지: " + this.energy;
};
// 3단계: 자식 생성자 만들기
function Dog(name, breed) {
this.name = name; // 부모와 같은 속성
this.energy = 100; // 부모와 같은 속성
this.breed = breed; // 자식만의 속성
}
// 4단계: 간단한 방법으로 부모와 자식 연결하기
Dog.prototype = Animal.prototype;
// 5단계: 자식만의 메서드 추가하기
Dog.prototype.bark = function() {
this.energy -= 5;
return this.name + "이(가) 멍멍! 에너지: " + this.energy;
};
// 사용해보기
let myDog = new Dog("바둑이", "진돗개");
console.log(myDog.eat()); // "바둑이이(가) 먹어요. 에너지: 110"
console.log(myDog.sleep()); // "바둑이이(가) 자요. 에너지: 130"
console.log(myDog.bark()); // "바둑이이(가) 멍멍! 에너지: 125"
🧪 실제 예제로 연습하기
🔹 탈것과 자동차 예제
// 부모: 탈것
function Vehicle(brand) {
this.brand = brand;
this.speed = 0;
this.fuel = 100;
}
// 모든 탈것이 할 수 있는 일
Vehicle.prototype.start = function() {
return this.brand + "이(가) 시동을 걸어요";
};
Vehicle.prototype.accelerate = function(amount) {
this.speed += amount;
this.fuel -= 2;
return `속도: ${this.speed}km/h, 연료: ${this.fuel}%`;
};
Vehicle.prototype.stop = function() {
this.speed = 0;
return this.brand + "이(가) 멈췄어요";
};
// 자식: 자동차
function Car(brand, model, color) {
this.brand = brand; // 부모와 같은 속성
this.speed = 0; // 부모와 같은 속성
this.fuel = 100; // 부모와 같은 속성
this.model = model; // 자동차만의 속성
this.color = color; // 자동차만의 속성
}
// 간단한 상속 연결
Car.prototype = Vehicle.prototype;
// 자동차만 할 수 있는 일
Car.prototype.honk = function() {
return `${this.color} ${this.brand} ${this.model}이(가) 빵빵!`;
};
Car.prototype.getInfo = function() {
return `${this.color} ${this.brand} ${this.model} - 속도: ${this.speed}km/h`;
};
// 사용해보기
let myCar = new Car("현대", "소나타", "빨강");
console.log(myCar.start()); // "현대이(가) 시동을 걸어요"
console.log(myCar.accelerate(30)); // "속도: 30km/h, 연료: 98%"
console.log(myCar.honk()); // "빨강 현대 소나타이(가) 빵빵!"
console.log(myCar.getInfo()); // "빨강 현대 소나타 - 속도: 30km/h"
console.log(myCar.stop()); // "현대이(가) 멈췄어요"
🔹 게임 캐릭터 예제
// 부모: 게임 캐릭터
function GameCharacter(name) {
this.name = name;
this.level = 1;
this.hp = 100;
this.exp = 0;
}
// 모든 캐릭터가 할 수 있는 일
GameCharacter.prototype.levelUp = function() {
this.level += 1;
this.hp += 20;
return `${this.name}이(가) ${this.level}레벨이 되었어요! HP: ${this.hp}`;
};
GameCharacter.prototype.heal = function() {
this.hp = 100;
return `${this.name}의 체력이 완전히 회복되었어요!`;
};
GameCharacter.prototype.getStatus = function() {
return `${this.name} - 레벨: ${this.level}, HP: ${this.hp}, 경험치: ${this.exp}`;
};
// 자식: 전사
function Warrior(name, weapon) {
this.name = name; // 부모와 같은 속성
this.level = 1; // 부모와 같은 속성
this.hp = 100; // 부모와 같은 속성
this.exp = 0; // 부모와 같은 속성
this.weapon = weapon; // 전사만의 속성
this.strength = 10; // 전사만의 속성
}
// 간단한 상속 연결
Warrior.prototype = GameCharacter.prototype;
// 전사만 할 수 있는 일
Warrior.prototype.attack = function() {
let damage = this.strength * this.level;
return `${this.name}이(가) ${this.weapon}로 ${damage}의 피해를 주었어요!`;
};
Warrior.prototype.powerUp = function() {
this.strength += 5;
return `${this.name}의 힘이 증가했어요! 힘: ${this.strength}`;
};
// 자식: 마법사
function Wizard(name, magic) {
this.name = name; // 부모와 같은 속성
this.level = 1; // 부모와 같은 속성
this.hp = 100; // 부모와 같은 속성
this.exp = 0; // 부모와 같은 속성
this.magic = magic; // 마법사만의 속성
this.mana = 50; // 마법사만의 속성
}
// 간단한 상속 연결
Wizard.prototype = GameCharacter.prototype;
// 마법사만 할 수 있는 일
Wizard.prototype.castSpell = function() {
if (this.mana >= 10) {
this.mana -= 10;
let damage = this.level * 8;
return `${this.name}이(가) ${this.magic} 마법으로 ${damage}의 피해를 주었어요! 마나: ${this.mana}`;
} else {
return "마나가 부족해요!";
}
};
Wizard.prototype.restoreMana = function() {
this.mana = 50;
return `${this.name}의 마나가 회복되었어요!`;
};
// 사용해보기
let warrior = new Warrior("용감한 기사", "검");
let wizard = new Wizard("현명한 마법사", "불");
console.log(warrior.attack()); // "용감한 기사이(가) 검로 10의 피해를 주었어요!"
console.log(warrior.getStatus()); // "용감한 기사 - 레벨: 1, HP: 100, 경험치: 0"
console.log(wizard.castSpell()); // "현명한 마법사이(가) 불 마법으로 8의 피해를 주었어요! 마나: 40"
console.log(wizard.levelUp()); // "현명한 마법사이(가) 2레벨이 되었어요! HP: 120"
🔹 학용품 예제
// 부모: 학용품
function SchoolSupply(name, color) {
this.name = name;
this.color = color;
this.condition = 100; // 사용 상태 (100이 새것)
}
// 모든 학용품이 할 수 있는 일
SchoolSupply.prototype.use = function() {
this.condition -= 10;
if (this.condition < 0) this.condition = 0;
return `${this.color} ${this.name}을(를) 사용했어요. 상태: ${this.condition}%`;
};
SchoolSupply.prototype.repair = function() {
this.condition = 100;
return `${this.name}을(를) 새것처럼 수리했어요!`;
};
// 자식: 연필
function Pencil(color, hardness) {
this.name = "연필"; // 부모와 같은 속성
this.color = color; // 부모와 같은 속성
this.condition = 100; // 부모와 같은 속성
this.hardness = hardness; // 연필만의 속성 (H, HB, B 등)
this.length = 100; // 연필만의 속성
}
// 간단한 상속 연결
Pencil.prototype = SchoolSupply.prototype;
// 연필만 할 수 있는 일
Pencil.prototype.write = function(text) {
this.condition -= 5;
this.length -= 1;
return `${this.hardness} ${this.color} 연필로 "${text}"를 썼어요. 길이: ${this.length}mm`;
};
Pencil.prototype.sharpen = function() {
this.length -= 5;
return `연필을 깎았어요! 이제 더 뾰족해졌어요. 길이: ${this.length}mm`;
};
// 자식: 지우개
function Eraser(color, softness) {
this.name = "지우개"; // 부모와 같은 속성
this.color = color; // 부모와 같은 속성
this.condition = 100; // 부모와 같은 속성
this.softness = softness; // 지우개만의 속성
this.size = 100; // 지우개만의 속성
}
// 간단한 상속 연결
Eraser.prototype = SchoolSupply.prototype;
// 지우개만 할 수 있는 일
Eraser.prototype.erase = function() {
this.condition -= 8;
this.size -= 2;
return `${this.softness} ${this.color} 지우개로 지웠어요. 크기: ${this.size}%`;
};
// 사용해보기
let myPencil = new Pencil("노랑", "HB");
let myEraser = new Eraser("분홍", "부드러운");
console.log(myPencil.write("안녕하세요")); // "HB 노랑 연필로 "안녕하세요"를 썼어요. 길이: 99mm"
console.log(myPencil.sharpen()); // "연필을 깎았어요! 이제 더 뾰족해졌어요. 길이: 94mm"
console.log(myEraser.erase()); // "부드러운 분홍 지우개로 지웠어요. 크기: 98%"
console.log(myPencil.use()); // "노랑 연필을(를) 사용했어요. 상태: 90%"
🚨 간단한 상속 방법의 주의점
우리가 지금까지 사용한 Dog.prototype = Animal.prototype
방식은 간단하지만 한 가지 문제가 있습니다:
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function() {
return this.name + "이(가) 먹어요";
};
function Dog(name) {
this.name = name;
}
// 간단한 연결
Dog.prototype = Animal.prototype;
// 강아지에게만 추가하려고 했는데...
Dog.prototype.bark = function() {
return this.name + "이(가) 멍멍!";
};
// 문제 발생: 동물도 짖을 수 있게 되었어요!
let animal = new Animal("동물");
console.log(animal.bark()); // "동물이(가) 멍멍!" - 이상하죠?
해결책: 이 문제는 나중에 더 안전한 방법을 배우면서 해결할 수 있습니다. 지금은 이런 문제가 있다는 것만 알아두세요.
✏️ 단계별 연습 문제
지금까지 차근차근 쌓아온 지식들을 바탕으로, 작은 문제들을 하나씩 풀어보는 시간을 가져보겠습니다. 혹시 어려우시더라도 걱정하지 마세요. 마치 새로운 언어를 배울 때 천천히 단어를 익혀가는 것처럼, 우리도 천천히 진행해보겠습니다.
🔸 기초 연습 1: 사람과 학생 만들기
// 부모: 사람
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.introduce = function() {
return `안녕하세요! 저는 ${this.age}살 ${this.name}이에요`;
};
Person.prototype.grow = function() {
this.age += 1;
return `${this.name}이(가) ${this.age}살이 되었어요`;
};
// 자식: 학생 (완성해보세요!)
function Student(name, age, grade, school) {
this.name = name; // 부모와 같은 속성
this.age = age; // 부모와 같은 속성
this.grade = grade; // 학생만의 속성
this.school = school; // 학생만의 속성
}
// 상속 연결하기
Student.prototype = Person.prototype;
// 학생만의 메서드 추가해보세요!
Student.prototype.study = function(subject) {
return `${this.name}이(가) ${subject}를 열심히 공부해요`;
};
Student.prototype.goToSchool = function() {
return `${this.name}이(가) ${this.school}에 등교해요`;
};
// 테스트
let student = new Student("철수", 10, 4, "햇살초등학교");
console.log(student.introduce()); // "안녕하세요! 저는 10살 철수이에요"
console.log(student.study("수학")); // "철수이(가) 수학를 열심히 공부해요"
console.log(student.goToSchool()); // "철수이(가) 햇살초등학교에 등교해요"
🔸 기초 연습 2: 악기와 피아노 만들기
// 부모: 악기
function Instrument(name, material) {
this.name = name;
this.material = material;
this.volume = 50;
}
Instrument.prototype.play = function() {
return `${this.material}로 만든 ${this.name}을(를) 연주해요`;
};
Instrument.prototype.adjustVolume = function(level) {
this.volume = level;
return `음량을 ${level}로 조절했어요`;
};
// 자식: 피아노 (완성해보세요!)
function Piano(material, keyCount) {
this.name = "피아노"; // 부모와 같은 속성
this.material = material; // 부모와 같은 속성
this.volume = 50; // 부모와 같은 속성
this.keyCount = keyCount; // 피아노만의 속성
}
// 상속 연결
Piano.prototype = Instrument.prototype;
// 피아노만의 메서드
Piano.prototype.playMelody = function(song) {
return `${this.keyCount}개 건반으로 "${song}"을(를) 연주해요`;
};
let myPiano = new Piano("나무", 88);
console.log(myPiano.play()); // "나무로 만든 피아노을(를) 연주해요"
console.log(myPiano.playMelody("엘리제를 위하여")); // "88개 건반으로 "엘리제를 위하여"을(를) 연주해요"
📚 복습하기 - 15단원 클래스와 비교해보기
지난 시간에 배운 클래스에서도 상속을 할 수 있습니다. 어떻게 다른지 비교해보며 복습해보겠습니다!
복습 문제 1: 클래스 상속 vs 프로토타입 상속
클래스 방식 (15단원에서 배운 방법):
class Animal {
constructor(name) {
this.name = name;
this.energy = 100;
}
eat() {
this.energy += 10;
return this.name + "이(가) 먹어요. 에너지: " + this.energy;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 부모 생성자 호출
this.breed = breed;
}
bark() {
return this.name + "이(가) 멍멍!";
}
}
let dog = new Dog("바둑이", "진돗개");
console.log(dog.eat()); // "바둑이이(가) 먹어요. 에너지: 110"
console.log(dog.bark()); // "바둑이이(가) 멍멍!"
프로토타입 방식 (오늘 배운 방법):
function Animal(name) {
this.name = name;
this.energy = 100;
}
Animal.prototype.eat = function() {
this.energy += 10;
return this.name + "이(가) 먹어요. 에너지: " + this.energy;
};
function Dog(name, breed) {
this.name = name; // 부모 속성을 직접 설정
this.energy = 100; // 부모 속성을 직접 설정
this.breed = breed;
}
Dog.prototype = Animal.prototype; // 간단한 상속 연결
Dog.prototype.bark = function() {
return this.name + "이(가) 멍멍!";
};
let dog = new Dog("바둑이", "진돗개");
console.log(dog.eat()); // "바둑이이(가) 먹어요. 에너지: 110"
console.log(dog.bark()); // "바둑이이(가) 멍멍!"
차이점 정리:
특징 | 클래스 방식 | 프로토타입 방식 |
---|---|---|
키워드 | class , extends |
function |
부모 호출 | super() |
직접 설정 |
상속 연결 | 자동으로 처리됨 | 수동으로 연결 |
코드 길이 | 더 짧고 간단함 | 더 길고 복잡함 |
결과 | 똑같음! | 똑같음! |
복습 문제 2: 어떤 방법이 더 좋을까요?
질문: 클래스와 프로토타입 중 어떤 방법이 더 좋을까요?
답:
- 클래스는 더 간단하고 읽기 쉽습니다.
extends
와super
키워드가 상속을 명확하게 표현해줍니다. - 프로토타입은 더 기본적인 방법이고, 자바스크립트의 동작 원리를 더 잘 이해할 수 있습니다.
- 초보자에게는 클래스가 더 이해하기 쉽습니다.
- 결과는 완전히 똑같습니다! 둘 다 같은 방식으로 작동합니다.
- 최근에는 클래스를 더 많이 사용하지만, 프로토타입을 이해하면 자바스크립트를 더 깊이 알 수 있습니다!
📝 정리하기
오늘은 간단한 상속에 대해 배웠습니다:
- 상속은 부모의 능력을 자식이 물려받는 것입니다
자식.prototype = 부모.prototype
로 간단하게 연결할 수 있습니다- 자식은 부모의 속성을 직접 설정하고, 자신만의 새로운 것을 추가할 수 있습니다
- 클래스 상속보다는 조금 복잡하지만 같은 결과를 만듭니다
- 간단한 방법에는 약간의 문제점이 있지만, 나중에 더 안전한 방법을 배울 수 있습니다
상속을 잘 사용하면 더 효율적이고 체계적인 코드를 만들 수 있습니다!
✅ 학습 완료 체크리스트
학습 내용 | 이해했나요? |
---|---|
상속의 기본 개념 | ✅ |
간단한 프로토타입 연결 방법 | ✅ |
부모 속성 설정 방법 | ✅ |
클래스 상속과의 비교 | ✅ |
간단한 방법의 장단점 | ✅ |
실용적인 예제 이해 | ✅ |
📂 마무리 정보
오늘 배운 16.2.3
내용이 여러분의 자바스크립트 지식 상자에 잘 저장되었나요? 다음 시간에는 더 재미있는 내용으로 만나요!
기억할 점: 상속은 부모의 좋은 것들을 자식이 물려받는 것입니다. 마치 가족의 특기를 대대로 물려받는 것처럼 말이에요.
무료 JavaScript 학습 플랫폼에서 단계별 학습과 실시간 코드 실행을 통해
더욱 효과적이고 재미있게 학습하실 수 있습니다.
'16. 프로토타입과 상속의 비밀 > 16.2 생성자 함수 상속' 카테고리의 다른 글
16.2.2 프로토타입으로 메서드 추가하기 - 모두가 함께 쓰는 공통 기능 (0) | 2025.07.24 |
---|---|
16.2.1 생성자 함수로 객체 만들기 - 나만의 공장 세우기 (0) | 2025.07.24 |