📘 16.2.1 생성자 함수로 객체 만들기 - 나만의 공장 세우기
프로그래밍을 배우는 여러분께 조용히 전해드립니다. 지금까지 우리는 객체를 하나씩 정성스럽게 만드는 방법을 배웠습니다. 하지만 만약 비슷한 객체를 100개 만들어야 한다면 어떨까요? 하나씩 만들기에는 너무나 긴 여정이 되겠지요.
그래서 오늘은 생성자 함수라는 특별한 방법을 함께 나누려 합니다. 이것은 마치 같은 모양의 쿠키를 만들 때 쿠키 틀을 사용하는 것과 같습니다. 한 번 틀을 정성스럽게 만들어 놓으면 쿠키를 몇 개든 자연스럽게 만들 수 있으니까요.
🧠 새로운 단어들과 친해지기
단어 | 쉬운 설명 |
---|---|
생성자 함수 | 똑같은 형태의 객체를 여러 개 만들어주는 특별한 함수 |
인스턴스 | 생성자 함수로 만들어진 실제 객체 |
new 연산자 | "새로운 객체 하나 만들어주세요"라고 부드럽게 요청하는 키워드 |
생성자 함수는 영어로 "Constructor Function"이라고 합니다. "Constructor"는 "만드는 사람", "건설하는 사람"이라는 뜻입니다. 마치 집을 정성스럽게 짓는 건축가처럼 객체를 만드는 특별한 함수라는 의미를 담고 있습니다.
✨ 생성자 함수가 뭐예요?
생성자 함수는 비슷한 객체를 부드럽게 여러 개 만들어주는 함수입니다. 일반 함수와 비슷하지만 몇 가지 특별한 점이 있습니다:
생성자 함수의 특별한 규칙들:
- 함수 이름을 대문자로 시작합니다 (예:
Dog
,Student
,Car
) new
키워드와 함께 사용해야 합니다this
를 사용해서 새로운 객체의 속성을 만듭니다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: 어떤 방법이 더 좋을까요?
질문: 클래스와 생성자 함수 중 어떤 방법이 더 좋을까요?
답:
- 클래스는 더 깔끔하고 읽기 쉽습니다. 메서드가 따로 정리되어 있어서 코드가 더 정돈된 느낌입니다.
- 생성자 함수는 더 기본적인 방법이고, 오래된 브라우저에서도 잘 작동합니다.
- 둘 다 같은 일을 하므로, 상황에 맞게 선택하면 됩니다!
- 최근에는 클래스를 더 많이 사용하는 추세입니다.
📝 정리하기
오늘은 생성자 함수에 대해 배웠습니다:
- 생성자 함수는 비슷한 객체를 여러 개 쉽게 만들어주는 특별한 함수입니다
- 대문자로 시작하고
new
키워드와 함께 사용해야 합니다 this
를 사용해서 새 객체의 속성과 메서드를 정의합니다- 클래스와 비슷한 일을 하지만 문법이 조금 다릅니다
- 각 객체는 독립적으로 작동합니다
생성자 함수를 잘 사용하면 같은 형태의 객체를 효율적으로 여러 개 만들 수 있어서 코드가 훨씬 깔끔해집니다!
✅ 학습 완료 체크리스트
학습 내용 | 이해했나요? |
---|---|
생성자 함수의 기본 개념 | ✅ |
new 연산자의 역할 | ✅ |
this 키워드 사용법 | ✅ |
클래스와의 차이점 | ✅ |
자주 하는 실수들 | ✅ |
독립적인 객체 생성 | ✅ |
📂 마무리 정보
오늘 배운 16.2.1
내용이 여러분의 자바스크립트 지식 상자에 잘 저장되었나요? 다음 시간에는 더 재미있는 내용으로 만나요!
기억할 점: 생성자 함수는 객체를 만드는 공장과 같습니다. 한 번 만들어 두면 똑같은 형태의 객체를 몇 개든 자연스럽게 만들 수 있습니다.
무료 JavaScript 학습 플랫폼에서 단계별 학습과 실시간 코드 실행을 통해
더욱 효과적이고 재미있게 학습하실 수 있습니다.
'16. 프로토타입과 상속의 비밀 > 16.2 생성자 함수 상속' 카테고리의 다른 글
16.2.3 상속 구현하기 - 부모님의 능력을 물려받기 (0) | 2025.07.24 |
---|---|
16.2.2 프로토타입으로 메서드 추가하기 - 모두가 함께 쓰는 공통 기능 (0) | 2025.07.24 |