16. 프로토타입과 상속의 비밀/16.2 생성자 함수 상속

16.2.1 생성자 함수로 객체 만들기 - 나만의 공장 세우기

thejavascript4kids 2025. 7. 24. 03:49

📘 16.2.1 생성자 함수로 객체 만들기 - 나만의 공장 세우기

프로그래밍을 배우는 여러분께 조용히 전해드립니다. 지금까지 우리는 객체를 하나씩 정성스럽게 만드는 방법을 배웠습니다. 하지만 만약 비슷한 객체를 100개 만들어야 한다면 어떨까요? 하나씩 만들기에는 너무나 긴 여정이 되겠지요.

그래서 오늘은 생성자 함수라는 특별한 방법을 함께 나누려 합니다. 이것은 마치 같은 모양의 쿠키를 만들 때 쿠키 틀을 사용하는 것과 같습니다. 한 번 틀을 정성스럽게 만들어 놓으면 쿠키를 몇 개든 자연스럽게 만들 수 있으니까요.

🧠 새로운 단어들과 친해지기

단어 쉬운 설명
생성자 함수 똑같은 형태의 객체를 여러 개 만들어주는 특별한 함수
인스턴스 생성자 함수로 만들어진 실제 객체
new 연산자 "새로운 객체 하나 만들어주세요"라고 부드럽게 요청하는 키워드

생성자 함수는 영어로 "Constructor Function"이라고 합니다. "Constructor"는 "만드는 사람", "건설하는 사람"이라는 뜻입니다. 마치 집을 정성스럽게 짓는 건축가처럼 객체를 만드는 특별한 함수라는 의미를 담고 있습니다.

✨ 생성자 함수가 뭐예요?

생성자 함수는 비슷한 객체를 부드럽게 여러 개 만들어주는 함수입니다. 일반 함수와 비슷하지만 몇 가지 특별한 점이 있습니다:

생성자 함수의 특별한 규칙들:

  1. 함수 이름을 대문자로 시작합니다 (예: Dog, Student, Car)
  2. new 키워드와 함께 사용해야 합니다
  3. this를 사용해서 새로운 객체의 속성을 만듭니다
  4. return을 쓰지 않아도 자동으로 새 객체를 돌려줍니다

마음속에 그려보는 이야기: 빵 만드는 틀

생성자 함수를 빵을 만드는 특별한 틀이라고 상상해보세요.

빵집에서 같은 모양의 빵을 여러 개 만들려면 어떻게 할까요? 빵 반죽을 손으로 하나씩 만들 수도 있지만, 빵 틀을 사용하면 훨씬 부드럽고 자연스럽게 만들 수 있습니다. 틀에 반죽을 넣고 구우면 똑같은 모양의 빵이 여러 개 나오지요.

생성자 함수도 마찬가지입니다:

  • 빵 틀 = 생성자 함수
  • 반죽 재료 = 함수에 전달하는 값들 (이름, 나이 등)
  • 구워진 빵 = 만들어진 객체 (인스턴스)
  • new 키워드 = "빵 하나 구워주세요" 하는 따뜻한 주문

⚙️ 기본 사용법

생성자 함수 만들기:

function Student(name, grade) {
    this.name = name;     // 학생 이름
    this.grade = grade;   // 학년
    this.school = "햇살초등학교";  // 모든 학생이 같은 학교

    this.study = function() {
        return this.name + "이(가) 열심히 공부해요";
    };

    this.introduce = function() {
        return "안녕하세요! " + this.grade + "학년 " + this.name + "이에요";
    };
}

객체 만들기:

let student1 = new Student("민지", 3);
let student2 = new Student("철수", 4);
let student3 = new Student("영희", 3);

console.log(student1.name);           // "민지"
console.log(student2.study());        // "철수이(가) 열심히 공부해요"
console.log(student3.introduce());    // "안녕하세요! 3학년 영희이에요"

🎯 실제 예제로 연습하기

🔹 강아지 객체 만들기

function Dog(name, breed, age) {
    this.name = name;      // 강아지 이름
    this.breed = breed;    // 품종
    this.age = age;        // 나이
    this.energy = 100;     // 모든 강아지는 에너지가 가득합니다

    // 짖는 기능
    this.bark = function() {
        return this.name + "이(가) 멍멍! 짖어요";
    };

    // 자기소개 기능
    this.introduce = function() {
        return "안녕! 나는 " + this.age + "살 " + this.breed + " " + this.name + "이야!";
    };

    // 놀기 기능
    this.play = function() {
        this.energy -= 20;
        if (this.energy < 0) this.energy = 0;
        return this.name + "이(가) 신나게 놀아요! 에너지: " + this.energy;
    };
}

// 강아지들 만들기
let myDog = new Dog("뽀삐", "치와와", 2);
let friendDog = new Dog("초코", "골든리트리버", 3);

console.log(myDog.bark());              // "뽀삐이(가) 멍멍! 짖어요"
console.log(friendDog.introduce());     // "안녕! 나는 3살 골든리트리버 초코이야!"
console.log(myDog.play());              // "뽀삐이(가) 신나게 놀아요! 에너지: 80"
console.log(myDog.play());              // "뽀삐이(가) 신나게 놀아요! 에너지: 60"

🔹 간단한 게임 캐릭터 만들기

function GameCharacter(name, job) {
    this.name = name;
    this.job = job;
    this.level = 1;
    this.hp = 100;
    this.exp = 0;

    // 레벨업 기능
    this.levelUp = function() {
        this.level += 1;
        this.hp += 20;
        return this.name + "이(가) " + this.level + "레벨이 되었어요! HP: " + this.hp;
    };

    // 경험치 얻기
    this.gainExp = function(amount) {
        this.exp += amount;
        let message = this.name + "이(가) 경험치 " + amount + "를 얻었어요!";

        if (this.exp >= 100) {
            this.exp -= 100;
            message += " " + this.levelUp();
        }

        return message;
    };

    // 캐릭터 정보
    this.getInfo = function() {
        return `${this.name} (${this.job}) - 레벨: ${this.level}, HP: ${this.hp}, 경험치: ${this.exp}`;
    };
}

// 게임 캐릭터들 만들기
let warrior = new GameCharacter("용감한 민수", "전사");
let wizard = new GameCharacter("똑똑한 지영", "마법사");

console.log(warrior.getInfo());           // "용감한 민수 (전사) - 레벨: 1, HP: 100, 경험치: 0"
console.log(warrior.gainExp(50));         // "용감한 민수이(가) 경험치 50를 얻었어요!"
console.log(warrior.gainExp(60));         // "용감한 민수이(가) 경험치 60를 얻었어요! 용감한 민수이(가) 2레벨이 되었어요! HP: 120"
console.log(warrior.getInfo());           // "용감한 민수 (전사) - 레벨: 2, HP: 120, 경험치: 10"

🔹 책 관리 객체 만들기

function Book(title, author, pages) {
    this.title = title;
    this.author = author;
    this.pages = pages;
    this.currentPage = 0;
    this.isFinished = false;

    // 책 읽기
    this.read = function(readPages) {
        this.currentPage += readPages;

        if (this.currentPage >= this.pages) {
            this.currentPage = this.pages;
            this.isFinished = true;
            return "축하해요! '" + this.title + "' 책을 다 읽었어요!";
        }

        let progress = Math.round((this.currentPage / this.pages) * 100);
        return `현재 ${this.currentPage}/${this.pages}페이지 (${progress}%) 읽었어요`;
    };

    // 책 정보
    this.getInfo = function() {
        let status = this.isFinished ? "읽기 완료" : "읽는 중";
        return `"${this.title}" - ${this.author} 저 (${status})`;
    };

    // 북마크하기
    this.bookmark = function() {
        return this.title + " " + this.currentPage + "페이지에 북마크했어요";
    };
}

// 책들 만들기
let book1 = new Book("모험 이야기", "김작가", 150);
let book2 = new Book("과학 탐험", "박박사", 200);

console.log(book1.read(30));        // "현재 30/150페이지 (20%) 읽었어요"
console.log(book1.bookmark());      // "모험 이야기 30페이지에 북마크했어요"
console.log(book1.read(120));       // "축하해요! '모험 이야기' 책을 다 읽었어요!"
console.log(book1.getInfo());       // "'모험 이야기' - 김작가 저 (읽기 완료)"

🚨 자주 하는 실수들

❌ 실수 1: new를 빼먹기

function Person(name) {
    this.name = name;
    this.sayHello = function() {
        return "안녕하세요, " + this.name + "이에요";
    };
}

// 잘못된 방법 - new 없이 호출
let person1 = Person("철수");
console.log(person1);  // undefined - 아무것도 안 만들어집니다!

// 올바른 방법 - new와 함께 호출
let person2 = new Person("영희");
console.log(person2.name);         // "영희" - 제대로 만들어집니다!
console.log(person2.sayHello());   // "안녕하세요, 영희이에요"

❌ 실수 2: 함수 이름을 소문자로 시작하기

// 권장하지 않음 - 소문자로 시작
function student(name) { 
    this.name = name;
}

// 권장함 - 대문자로 시작 (생성자 함수임을 명확하게 표시)
function Student(name) { 
    this.name = name;
}

❌ 실수 3: return을 잘못 사용하기

function Car(brand) {
    this.brand = brand;

    // 잘못된 방법 - 다른 값을 리턴하면 안 됩니다
    return "자동차 만들었어요";  // 이렇게 하면 문제가 생깁니다
}

// 올바른 방법 - return 없이 그냥 두기
function Car(brand) {
    this.brand = brand;
    this.start = function() {
        return this.brand + " 자동차 출발!";
    };
    // return 없음 - 자동으로 새 객체를 돌려줍니다
}

🎯 생성자 함수의 특별한 점들

특별한 점 1: 각 객체는 독립적입니다

function Counter(name) {
    this.name = name;
    this.count = 0;

    this.increase = function() {
        this.count += 1;
        return this.name + " 카운터: " + this.count;
    };
}

let counter1 = new Counter("첫번째");
let counter2 = new Counter("두번째");

console.log(counter1.increase());  // "첫번째 카운터: 1"
console.log(counter1.increase());  // "첫번째 카운터: 2"
console.log(counter2.increase());  // "두번째 카운터: 1" - 독립적으로 작동합니다!

특별한 점 2: 나중에 기능을 추가할 수 있습니다

function Robot(name) {
    this.name = name;
    this.power = 100;
}

// 로봇들 만들기
let robot1 = new Robot("R2D2");
let robot2 = new Robot("C3PO");

// 나중에 prototype에 기능 추가하기 (다음 시간에 자세히 배웁니다)
Robot.prototype.charge = function() {
    this.power = 100;
    return this.name + " 충전 완료!";
};

// 이미 만들어진 로봇들도 새 기능을 사용할 수 있습니다!
console.log(robot1.charge());  // "R2D2 충전 완료!"
console.log(robot2.charge());  // "C3PO 충전 완료!"

✏️ 직접 해보기 - 연습 문제들

이제 배운 내용을 연습문제를 통해 확실히 익혀보겠습니다.

혹시 어려우시더라도 걱정하지 마세요. 마치 처음 자전거를 탈 때 넘어져도 다시 일어나는 것처럼, 실수하면서 배우는 것이 자연스럽습니다. 지금까지 차근차근 쌓아온 지식들을 바탕으로, 작은 문제들을 하나씩 풀어보는 시간을 가져보겠습니다.

문제 1: 자동차 공장 만들기

// 자동차 생성자 함수를 완성해보세요
function Car(brand, color, fuel) {
    this.brand = brand;     // 브랜드
    this.color = color;     // 색깔
    this.fuel = fuel;       // 연료량
    this.speed = 0;         // 현재 속도

    // 시동 걸기
    this.start = function() {
        if (this.fuel > 0) {
            return this.brand + " 자동차가 부르릉~ 시동이 걸렸어요!";
        } else {
            return "연료가 없어서 시동이 안 걸려요!";
        }
    };

    // 가속하기
    this.accelerate = function() {
        if (this.fuel > 0) {
            this.speed += 10;
            this.fuel -= 1;
            return `속도: ${this.speed}km/h, 연료: ${this.fuel}L`;
        } else {
            return "연료가 부족해요!";
        }
    };

    // 주유하기
    this.refuel = function(amount) {
        this.fuel += amount;
        return `주유 완료! 현재 연료: ${this.fuel}L`;
    };
}

// 테스트
let myCar = new Car("현대", "빨강", 50);
console.log(myCar.start());           // "현대 자동차가 부르릉~ 시동이 걸렸어요!"
console.log(myCar.accelerate());      // "속도: 10km/h, 연료: 49L"
console.log(myCar.refuel(10));        // "주유 완료! 현재 연료: 59L"

문제 2: 은행 계좌 만들기

function BankAccount(owner, initialMoney) {
    this.owner = owner;           // 계좌 주인
    this.balance = initialMoney;  // 잔액
    this.history = [];            // 거래 내역

    // 입금하기
    this.deposit = function(amount) {
        this.balance += amount;
        this.history.push(`입금: +${amount}원`);
        return `${amount}원 입금됨. 잔액: ${this.balance}원`;
    };

    // 출금하기
    this.withdraw = function(amount) {
        if (this.balance >= amount) {
            this.balance -= amount;
            this.history.push(`출금: -${amount}원`);
            return `${amount}원 출금됨. 잔액: ${this.balance}원`;
        } else {
            return "잔액이 부족해요!";
        }
    };

    // 계좌 정보 보기
    this.getInfo = function() {
        return `${this.owner}님의 계좌 - 잔액: ${this.balance}원`;
    };
}

let myAccount = new BankAccount("김학생", 10000);
console.log(myAccount.deposit(5000));   // "5000원 입금됨. 잔액: 15000원"
console.log(myAccount.withdraw(3000));  // "3000원 출금됨. 잔액: 12000원"
console.log(myAccount.getInfo());       // "김학생님의 계좌 - 잔액: 12000원"

📚 복습하기 - 15단원 클래스와 비교해보기

지난 시간에 배운 클래스와 오늘 배운 생성자 함수는 비슷한 일을 합니다. 두 방법의 차이점을 알아보며 복습해보겠습니다!

복습 문제 1: 같은 일을 하는 클래스와 생성자 함수 비교

클래스 방식 (15단원에서 배운 방법):

class Animal {
    constructor(name, type) {
        this.name = name;
        this.type = type;
        this.energy = 100;
    }

    makeSound() {
        return this.name + "이(가) " + this.type + " 소리를 내요";
    }

    sleep() {
        this.energy = 100;
        return this.name + "이(가) 잠을 자서 기력이 회복되었어요";
    }
}

let cat = new Animal("야옹이", "고양이");
console.log(cat.makeSound());  // "야옹이이(가) 고양이 소리를 내요"

생성자 함수 방식 (오늘 배운 방법):

function Animal(name, type) {
    this.name = name;
    this.type = type;
    this.energy = 100;

    this.makeSound = function() {
        return this.name + "이(가) " + this.type + " 소리를 내요";
    };

    this.sleep = function() {
        this.energy = 100;
        return this.name + "이(가) 잠을 자서 기력이 회복되었어요";
    };
}

let dog = new Animal("멍멍이", "강아지");
console.log(dog.makeSound());  // "멍멍이이(가) 강아지 소리를 내요"

차이점 정리:

특징 클래스 방식 생성자 함수 방식
키워드 class function
속성 정의 constructor 안에 함수 본문에
메서드 정의 클래스 본문에 함수 본문에
사용법 둘 다 new 키워드로 객체 생성 둘 다 new 키워드로 객체 생성

복습 문제 2: 클래스를 생성자 함수로 바꿔보기

다음 클래스를 생성자 함수로 바꿔보세요:

// 클래스 버전 (15단원에서 배운 방법)
class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
        this.color = "하얀색";
    }

    getArea() {
        return this.width * this.height;
    }

    getPerimeter() {
        return (this.width + this.height) * 2;
    }

    paint(color) {
        this.color = color;
        return "사각형을 " + color + "으로 칠했어요";
    }
}

// 생성자 함수 버전으로 바꿔보세요!
function Rectangle(width, height) {
    this.width = width;
    this.height = height;
    this.color = "하얀색";

    this.getArea = function() {
        return this.width * this.height;
    };

    this.getPerimeter = function() {
        return (this.width + this.height) * 2;
    };

    this.paint = function(color) {
        this.color = color;
        return "사각형을 " + color + "으로 칠했어요";
    };
}

// 테스트 (두 방법 모두 같은 결과가 나와요)
let rect = new Rectangle(5, 3);
console.log(rect.getArea());        // 15
console.log(rect.getPerimeter());   // 16
console.log(rect.paint("빨강"));    // "사각형을 빨강으로 칠했어요"

복습 문제 3: 어떤 방법이 더 좋을까요?

질문: 클래스와 생성자 함수 중 어떤 방법이 더 좋을까요?

답:

  • 클래스는 더 깔끔하고 읽기 쉽습니다. 메서드가 따로 정리되어 있어서 코드가 더 정돈된 느낌입니다.
  • 생성자 함수는 더 기본적인 방법이고, 오래된 브라우저에서도 잘 작동합니다.
  • 둘 다 같은 일을 하므로, 상황에 맞게 선택하면 됩니다!
  • 최근에는 클래스를 더 많이 사용하는 추세입니다.

📝 정리하기

오늘은 생성자 함수에 대해 배웠습니다:

  1. 생성자 함수는 비슷한 객체를 여러 개 쉽게 만들어주는 특별한 함수입니다
  2. 대문자로 시작하고 new 키워드와 함께 사용해야 합니다
  3. this를 사용해서 새 객체의 속성과 메서드를 정의합니다
  4. 클래스와 비슷한 일을 하지만 문법이 조금 다릅니다
  5. 각 객체는 독립적으로 작동합니다

생성자 함수를 잘 사용하면 같은 형태의 객체를 효율적으로 여러 개 만들 수 있어서 코드가 훨씬 깔끔해집니다!

✅ 학습 완료 체크리스트

학습 내용 이해했나요?
생성자 함수의 기본 개념
new 연산자의 역할
this 키워드 사용법
클래스와의 차이점
자주 하는 실수들
독립적인 객체 생성

📂 마무리 정보

오늘 배운 16.2.1 내용이 여러분의 자바스크립트 지식 상자에 잘 저장되었나요? 다음 시간에는 더 재미있는 내용으로 만나요!

기억할 점: 생성자 함수는 객체를 만드는 공장과 같습니다. 한 번 만들어 두면 똑같은 형태의 객체를 몇 개든 자연스럽게 만들 수 있습니다.


🚀 더 체계적인 JavaScript 학습을 원하신다면?
이 포스팅에서 다룬 내용을 실제로 실습해보세요!
무료 JavaScript 학습 플랫폼에서 단계별 학습과 실시간 코드 실행을 통해
더욱 효과적이고 재미있게 학습하실 수 있습니다.
📝 실시간 코드 실행 📊 학습 진도 관리 👥 체계적 커리큘럼
📚 171개 체계적 학습레슨 · 📋 855개 4지선다 연습문제 · 🆓 완전 무료 · ⚡ 즉시 시작