207 lines
7.9 KiB
Markdown
207 lines
7.9 KiB
Markdown
# 객체 지향 프로그래밍(Object-Oriented Programming, OOP)
|
|
자바스크립트는 객체 지향 프로그래밍(OOP)의 패러다임을 지원합니다. OOP는 프로그램을 **객체(object)**라는 독립적인 단위로 나누고, 이 객체들 간의 상호작용으로 문제를 해결하는 방법론입니다. 자바스크립트는 클래스와 프로토타입 기반 객체 지향 프로그래밍을 모두 지원합니다.
|
|
|
|
## OOP
|
|
**객체 지향 프로그래밍(OOP)**의 핵심은 데이터를 **객체(object)**로 구조화하는 것입니다. 객체는 **속성(property)**과 **메서드(method)**를 가지며, 현실 세계의 개념을 코드로 추상화합니다.
|
|
|
|
### OOP의 주요 원칙
|
|
- 캡슐화 (Encapsulation): 객체 내부의 데이터를 외부로부터 숨기고, 필요한 인터페이스만 노출합니다.
|
|
- 상속 (Inheritance): 기존 객체(클래스)의 속성과 메서드를 재사용하여 새로운 객체를 생성합니다.
|
|
- 다형성 (Polymorphism): 같은 메서드 이름이 다른 객체에서 다르게 동작하도록 합니다.
|
|
- 추상화 (Abstraction): 복잡한 구현을 감추고, 필요한 핵심만 노출합니다.
|
|
|
|
### OOP의 주요 장점
|
|
- 코드 재사용성: 상속과 클래스 설계를 통해 동일한 코드를 반복하지 않고 재사용할 수 있습니다.
|
|
- 유지보수 용이성: 캡슐화와 모듈화를 통해 코드의 구조가 명확해지고 수정이 쉬워집니다.
|
|
- 확장성: 새로운 클래스나 메서드를 쉽게 추가할 수 있습니다.
|
|
- 가독성: 객체를 통해 프로그램의 논리를 현실 세계와 유사하게 표현할 수 있습니다.
|
|
|
|
### OOP와 자바스크립트의 유연성
|
|
자바스크립트는 객체 지향 프로그래밍 외에도 함수형 프로그래밍이나 절차적 프로그래밍을 지원합니다. 즉, 필요에 따라 객체 지향적인 스타일과 함수형 스타일을 혼합하여 사용할 수 있는 멀티 패러다임 언어입니다.
|
|
|
|
## 자바스크립트의 객체 지향 구현 방법
|
|
### 객체 리터럴
|
|
가장 기본적인 객체 생성 방식은 객체 리터럴을 사용하는 것입니다.
|
|
```javascript
|
|
const person = {
|
|
name: "홍길동",
|
|
age: 30,
|
|
greet: function () {
|
|
console.log(`안녕하세요, 제 이름은 ${this.name}입니다.`);
|
|
},
|
|
};
|
|
|
|
person.greet(); // 출력: 안녕하세요, 제 이름은 홍길동입니다.
|
|
```
|
|
|
|
### 생성자 함수 (Constructor Function)
|
|
생성자 함수는 객체를 생성하는 데 사용됩니다.
|
|
```javascript
|
|
function Person(name, age) {
|
|
this.name = name;
|
|
this.age = age;
|
|
this.greet = function () {
|
|
console.log(`안녕하세요, 저는 ${this.name}이고, 나이는 ${this.age}살입니다.`);
|
|
};
|
|
}
|
|
|
|
const person1 = new Person("김철수", 25);
|
|
const person2 = new Person("박영희", 28);
|
|
|
|
person1.greet(); // 출력: 안녕하세요, 저는 김철수이고, 나이는 25살입니다.
|
|
person2.greet(); // 출력: 안녕하세요, 저는 박영희이고, 나이는 28살입니다.
|
|
```
|
|
|
|
### 프로토타입 (Prototype)
|
|
자바스크립트는 프로토타입 기반 언어로, 모든 객체는 자신의 프로토타입을 참조합니다. 프로토타입은 객체가 상속받을 수 있는 속성과 메서드를 정의합니다.
|
|
```javascript
|
|
function Person(name, age) {
|
|
this.name = name;
|
|
this.age = age;
|
|
}
|
|
|
|
Person.prototype.greet = function () {
|
|
console.log(`안녕하세요, 저는 ${this.name}이고, 나이는 ${this.age}살입니다.`);
|
|
};
|
|
|
|
const person1 = new Person("김철수", 25);
|
|
const person2 = new Person("박영희", 28);
|
|
|
|
person1.greet(); // 출력: 안녕하세요, 저는 김철수이고, 나이는 25살입니다.
|
|
person2.greet(); // 출력: 안녕하세요, 저는 박영희이고, 나이는 28살입니다.
|
|
```
|
|
### 클래스 (Class)
|
|
ES6부터 클래스를 사용하여 객체 지향 프로그래밍을 더욱 간단하고 직관적으로 구현할 수 있습니다. 클래스는 생성자 함수의 문법적 설탕(Syntactic Sugar)입니다.
|
|
|
|
* 클래스를 선언하려면 class 키워드와 함께 클래스의 이름을 작성합니다.
|
|
* 클래스 선언은 let과 const처럼 블록 스코프에 선언되며, 호이스팅(hoisting)이 일어나지 않는다. 클래스는 반드시 정의한 뒤에 사용해야 합니다.
|
|
* 클래스의 메소드 안에서 super 키워드를 사용할 수 있습니다.
|
|
* static 키워드를 메소드 이름 앞에 붙여주면 해당 메소드는 정적 메소드가 됩니다.
|
|
* Getter 혹은 Setter를 정의하고 싶을 때는 메소드 이름 앞에 get 또는 set을 붙여주면 된다.
|
|
* extends 키워드를 사용하여 클래스에서 다른 클래스로 상속하면서 클래스의 기능을 확장해 나갈수 있습니다.
|
|
* 클래스에서 일반적인 방식으로 프로퍼티를 선언하고 할당하면 Public Property(공개 프로퍼티)입니다.
|
|
* 클래스에서 프로퍼티 앞에 # 키워드를 작성하여 선언하면 Private Property (비공개 프로퍼티)가 됩니다.
|
|
|
|
#### 클래스 선언
|
|
```javascript
|
|
class Person {
|
|
constructor(name, age) {
|
|
this.name = name;
|
|
this.age = age;
|
|
}
|
|
|
|
greet() {
|
|
console.log(`안녕하세요, 저는 ${this.name}이고, 나이는 ${this.age}살입니다.`);
|
|
}
|
|
}
|
|
|
|
const person1 = new Person("이철수", 40);
|
|
const person2 = new Person("한지민", 35);
|
|
|
|
person1.greet(); // 출력: 안녕하세요, 저는 이철수이고, 나이는 40살입니다.
|
|
person2.greet(); // 출력: 안녕하세요, 저는 한지민이고, 나이는 35살입니다.
|
|
```
|
|
* class 키워드: 클래스를 선언하는 데 사용됩니다.
|
|
* constructor(): 객체 생성 시 호출되는 생성자 메서드입니다.
|
|
* 메서드: 클래스 내에 정의된 함수를 의미합니다.
|
|
* new 키워드를 사용하여 클래스의 인스턴스를 생성합니다.
|
|
|
|
#### 상속 (Inheritance)
|
|
클래스 간 상속을 통해 코드를 재사용할 수 있습니다. 자바스크립트에서 클래스는 extends 키워드를 사용하여 상속을 구현합니다.
|
|
|
|
```javascript
|
|
class Animal {
|
|
constructor(name) {
|
|
this.name = name;
|
|
}
|
|
|
|
sound() {
|
|
console.log(`${this.name}가 소리를 냅니다.`);
|
|
}
|
|
}
|
|
|
|
class Dog extends Animal {
|
|
sound() {
|
|
console.log(`${this.name}가 멍멍 짖습니다.`);
|
|
}
|
|
}
|
|
|
|
const dog = new Dog("강아지");
|
|
dog.sound(); // 출력: 강아지가 멍멍 짖습니다.
|
|
```
|
|
* extends 키워드: 다른 클래스를 상속받아 새로운 클래스를 정의합니다.
|
|
* super(): 부모 클래스의 생성자를 호출합니다.
|
|
|
|
#### 다형성 (Polymorphism)
|
|
다형성은 상속 관계에서 메서드를 재정의(오버라이딩)하여 구현됩니다.
|
|
```javascript
|
|
class Animal {
|
|
speak() {
|
|
console.log("동물이 소리를 냅니다.");
|
|
}
|
|
}
|
|
|
|
class Cat extends Animal {
|
|
speak() {
|
|
console.log("고양이가 야옹합니다.");
|
|
}
|
|
}
|
|
|
|
class Dog extends Animal {
|
|
speak() {
|
|
console.log("강아지가 멍멍 짖습니다.");
|
|
}
|
|
}
|
|
|
|
const animals = [new Cat(), new Dog(), new Animal()];
|
|
|
|
animals.forEach(animal => animal.speak());
|
|
// 출력:
|
|
// 고양이가 야옹합니다.
|
|
// 강아지가 멍멍 짖습니다.
|
|
// 동물이 소리를 냅니다.
|
|
```
|
|
|
|
#### 정적 필드 / 메서드
|
|
정적 필드는 클래스 자체에 속하는 필드로, 인스턴스를 생성하지 않고도 클래스 이름으로 직접 접근할 수 있는 필드입니다.
|
|
```javascript
|
|
class MathUtils {
|
|
static PI = 3.14159;
|
|
|
|
static square(x) {
|
|
return x * x;
|
|
}
|
|
}
|
|
|
|
console.log(MathUtils.PI); // 3.14159
|
|
console.log(MathUtils.square(5)); // 25
|
|
```
|
|
|
|
#### Getter / Setter
|
|
```javascript
|
|
class Person {
|
|
#name; // private 속성
|
|
#age;
|
|
|
|
constructor(name, age) {
|
|
this.#name = name;
|
|
this.#age = age;
|
|
}
|
|
|
|
get name() {
|
|
return this.#name;
|
|
}
|
|
|
|
set name(value) {
|
|
this.#name = value;
|
|
}
|
|
}
|
|
|
|
const person1 = new Person('홍길동', 30);
|
|
console.log(person1.name); // 홍길동 (getter를 통해 접근)
|
|
console.log(person1.#name); // Error: Property '#name' is private
|
|
```
|
|
* get과 set을 사용하여 속성에 대한 접근을 제어할 수 있습니다.
|
|
|
|
|