1. 객체 지향 프로그래밍(Object-Oriented Programming, OOP) 이란?
객체 지향 프로그래밍이 있기 전 절차 지향 프로그램이라는 것이 있었다. 이는 프로그램을 순차적인 절차로 구성하는 방식인데, 작은 문제를 해결하기 위해 절차를 정의하고, 그 절차들을 조합하여 큰 문제를 해결하는 방식이다. 하지만 프로그램이 커지고 복잡해지면서 코드의 유지보수와 디버깅이 어려워지는 문제가 생겼다. 그리고 데이터와 그 데이터를 조작하는 함수들이 분리되어 있어 코드의 응집성이 떨어졌다. 이를 보완하기에 나온게 객체 지향 프로그래밍이다.
객체지향 프로그래밍은 객체라는 단위로 구성하는 방식이다. 객체는 데이터와 데이터를 조작하는 함수들을 하나의 단위로 묶어서 관리한다. 이를 통해 코드의 응집성을 높이며, 코드의 재사용과 유지보수성을 향상 시킨다.
여기서 객체란?
객체는 데이터와 그 데이터를 처리하는 메서드(함수)를 논리적으로 묶어서 구성한 개념이다. 프로그래밍에서 정보를 저장하고 조작하는 단위로 사용한다.
객체는 2가지로 구성되어 있다.
1. 상태(state)
객체가 가지고 있는 데이터를 의미한다. 예를 들어 '사람'이라는 객체가 있다면 상태는 이름, 나이, 성별 등의 속성으로 표현 될 수 있다.
function createPerson(name, age, gender) {
let person = {}; // 빈 객체 생성
// 상태 속성 추가
person.name = name;
person.age = age;
person.gender = gender;
// 상태 반환 함수
person.getState = function () {
return {
name: this.name,
age: this.age,
gender: this.gender
};
};
// 상태 변경 함수
person.setAge = function (newAge) {
this.age = newAge;
};
person.setGender = function (newGender) {
this.gender = newGender;
};
// 객체 반환
return person;
}
// Person 객체 생성
const person = createPerson("John", 25, "Male");
// 객체의 상태 출력
console.log(person.getState());
// 객체의 상태 변경
person.setAge(30);
person.setGender("Female");
// 변경된 상태 출력
console.log(person.getState());
2. 행동(Behaivor)
객체가 수행할 수 있는 동작이나 기능을 나타낸다. 위와 같은 예시로 '사람'라는 객체가 있다면, 객체의 행동 걷기, 말하기, 먹기 등 과 같은 동작으로 표현된다.
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.greet = function() {
console.log("Hello, my name is " + this.name);
};
this.incrementAge = function() {
this.age++;
console.log("My age is now " + this.age);
};
}
// Person 객체 생성
const person = new Person("John", 25, "Male");
// 객체의 메서드 호출
person.greet(); // 출력: Hello, my name is John
person.incrementAge(); // 출력: My age is now 26
객체는 프로그램에서 모듈화, 추상화, 재사용성 등을 통해 복잡한 문제를 해결하기 위한 도구로 쓰인다. 객체 지향 프로그래밍에서 객체 간의 상호작용을 통해 프로그램을 구성하고, 객체 속성과 메서드를 사용하여 원하는 작업을 수행한다. 이를 통해 코드의 가독성, 재사용성, 유지보수성을 높인다.
2. 객체의 4가지 특성
1. 캡슐화(Encapsulation)
캡슐화는 객체의 상태(속성)와 행동(메서드)를 하나로 묶는 것을 의미한다. 객체 내부적으로 데이터를 저장하고, 이 데이터에 대한 접근은 객체의 메서드를 통해서만 이뤄져야 한다. 이를 통해 객체의 상태와 행동이 외부에 의해 직접 조작되지 않고, 객체의 무결성과 안정성을 보장할 수 있다.
class Car {
constructor() {
this.engineStatus = 'stopped';
this.speed = 0;
this.fuel = 100;
}
startEngine() {
// 엔진 가동 로직
this.engineStatus = 'running';
}
stopEngine() {
// 엔진 정지 로직
this.engineStatus = 'stopped';
}
accelerate() {
// 가속 로직
this.speed += 10;
}
brake() {
// 브레이크 로직
this.speed -= 10;
}
getSpeed() {
return this.speed;
}
getFuel() {
return this.fuel;
}
}
// 자동차 사용 예시
let car = new Car();
car.startEngine();
car.accelerate();
console.log(car.getSpeed()); // 속도 출력
console.log(car.getFuel()); // 연료량 출력
위의 코드에서 Car 클래스는 자동차를 표현하고 있다. engineStatus, speed, **fuel**과 같은 데이터는 Car 클래스 내부에 존재하며, 외부에서 직접적으로 접근할 수 없다. 대신에 startEngine(), accelerate(), **getSpeed()**와 같은 메서드를 통해 데이터에 접근하고 조작할 수 있다.
이렇게 데이터와 해당 데이터를 조작하는 코드를 함께 캡슐화함으로써 데이터의 일관성을 유지할 수 있고, 외부로부터의 무분별한 접근을 제한할 수 있다. 이는 코드의 신뢰성을 높이고, 유지 보수를 용이하게 만들어준다.
2. 상속(Inheritance)
상속은 이미 정의된 클래스로부터 속성과 메서드를 상속받아 새로운 클래스를 생성하는 기능이다. 상속을 통해 코드의 재사용성을 높이고, 코드의 유지보수가 용이해진다. 상속을 받은 클래스는 기존 클래스의 특성을 확장하거나 수정하여 새로운 동작을 추가할 수 있다.
class Animal {
speak() {
console.log('Animal is speaking.');
}
}
class Cat extends Animal {
scratch() {
console.log('Cat is scratching.');
}
}
const cat = new Cat();
cat.speak(); // 출력: Animal is speaking.
cat.scratch(); // 출력: Cat is scratching.
위 예시에서 Animal 클래스는 speak 메서드를 가지고 있다. 이 클래스는 다른 클래스에서 상속받을 수 있는 기본 동작을 정의한다.
Cat 클래스는 Animal 클래스를 상속받는다. 상속을 받으면 자식 클래스는 부모 클래스의 속성과 메서드를 상속받아 사용할 수 있다. 여기서 Cat 클래스는 Animal 클래스의 speak 메서드를 상속받는다.
또한, Cat 클래스는 scratch 메서드를 추가로 가지고 있다. 이는 Cat 클래스에만 존재하는 메서드다.
그래서 cat 객체는 speak 메서드와 scratch 메서드를 모두 호출할 수 있다. cat.speak()는 Animal 클래스에서 상속받은 메서드를 실행하며, cat.scratch()는 Cat 클래스에 추가된 메서드를 실행한다.
이렇게 상속을 통해 부모 클래스의 기능을 물려받고, 자식 클래스에서 새로운 기능을 추가할 수 있다.
3. 다형성(Polymorphism)
다형성은 동일한 메서드 이름을 가진 객체가 서로 다른 방식으로 동작하는 능력을 의미한다. 다형성은 상속과 관련이 깊으며, 상위 클래스로부터 파생된 하위 클래스에서 같은 메서드를 재정의하거나, 인터페이스를 통해 다양한 객체가 동일한 메서드를 구현할 수 있다. 이를 통해 유연하고 확장성 있는 코드를 작성할 수 있다.
다형성은 다양한 형태를 가지고 동작할 수 있는 능력이다
쉽게 말해서 하나의 타입이 다른 타입으로 변환될 수 있고, 이 변환된 객체는 자신이 원래 타입에 정의된 메서드를 호출할 수 있다.
// Animal 클래스 정의
class Animal {
makeSound() {
console.log("동물 소리");
}
}
// Dog 클래스 정의
class Dog extends Animal {
makeSound() {
console.log("개 소리");
}
}
// 객체 다형성 적용
let animal = new Animal();
let dog = new Dog();
animal.makeSound(); // 동물 소리 출력
dog.makeSound(); // 개 소리 출력
위의 코드에서 Animal 클래스는 makeSound() 메서드를 정의하고 있다. 그리고 Dog 클래스는 Animal 클래스를 상속받고 makeSound() 메서드를 재정의합니다.
이제 **Animal**과 Dog 클래스의 인스턴스를 생성하고, makeSound() 메서드를 호출하면 각각의 객체에 맞는 소리가 출력된다. 이는 자바스크립트의 객체 다형성을 나타내는 예시다.
자바스크립트는 동적 타입 언어이기 때문에 클래스 상속 없이도 객체 다형성을 구현할 수 있다. 다형성은 다른 객체가 동일한 인터페이스를 사용하여 메서드를 호출할 수 있도록 함으로써 코드의 유연성을 높이는 역할을 한다.
4. 추상화(Abstraction)
추상화는 복잡한 시스템이나 개체들을 간결하고 명확한 모델로 표현한 과정이다. 이를 토애서 핵심적인 특징과 동작에 집중할 수 있으며, 불필요한 세부사항을 감추고 사용자에게 필요한 기능만 노출 시킬 수 있다.
class Car {
startEngine() {
// 엔진을 가동시키는 코드
}
stopEngine() {
// 엔진을 정지시키는 코드
}
accelerate() {
// 가속하는 코드
}
brake() {
// 브레이크를 밟는 코드
}
}
// 자동차 사용 예시
let car = new Car();
car.startEngine();
car.accelerate();
car.brake();
car.stopEngine();
위의 코드에서 Car 클래스는 자동차를 추상화한 것이다. 자동차의 주행 기능인 엔진 가동, 정지, 가속, 브레이크를 메서드로 표현했다. 추상화를 통해 자동차 객체를 사용하는 사용자는 주행에 필요한 메서드만 호출하여 자동차를 조작할 수 있다.
객체 추상화를 사용하면 복잡한 시스템을 단순화하고, 필요한 기능에 집중할 수 있다. 이는 코드의 가독성과 유지 보수성을 향상시키며, 객체 간의 결합도를 낮추어 유연하고 확장 가능한 코드를 작성할 수 있도록 도와준다.
이러한 특징들을 결합하여 객체 지향 프로그래밍은 유연하고 모듈화된 코드를 작성할 수 있으며, 코드의 재사용성과 유지보수성을 향상 시킨다.
객체 지향 프로그램의 단점
- 복잡성: 객체 지향 프로그래밍은 객체 간의 상호작용과 상속 등의 개념을 포함하여 복잡성이 증가할 수 있다. 큰 규모의 프로젝트에서는 객체 간의 관계와 상호작용을 이해하고 유지하기 어려울 수 있다.
- 성능 저하: 객체 지향 프로그래밍은 일반적으로 함수 호출과 메모리 할당에 대한 오버헤드가 발생할 수 있다. 객체 간의 통신 및 메시지 전달은 일반적으로 프로그램의 실행 속도를 느리게 만들 수 있다.
- 학습 곡선: 객체 지향 프로그래밍은 기존의 절차적 프로그래밍과는 다른 개념과 구조를 가지고 있습니다. 이로 인해 초보자들이 OOP를 이해하고 습득하는 데 어려움을 겪을 수 있다.
- 남용의 위험: 객체 지향 프로그래밍에서는 객체의 재사용성과 모듈화를 강조한다. 하지만 이로 인해 상속 구조가 복잡해지고, 과도한 객체 간의 의존성이 발생하여 유지 보수가 어려워질 수 있다. 또한, 객체들이 상태와 행위를 함께 가지고 있기 때문에 상태 변경에 따른 부작용이 발생할 수 있다.
- 유연성 부족: 객체 지향 프로그래밍은 상속과 정적 타입을 이용하여 코드를 구조화하고 제약을 가할 수 있다. 이로 인해 유연성이 제한될 수 있으며, 코드 변경이 어려워질 수 있다. 객체 간의 강한 결합도로 인해 하나의 객체를 수정하면 그와 관련된 다른 객체들도 수정해야 할 수 있다.
'CS > 프로그래밍' 카테고리의 다른 글
await, async (0) | 2023.07.02 |
---|---|
forEach()와 map의 차이점 (0) | 2023.07.01 |
호이스팅_민희 (0) | 2023.06.19 |
호이스팅 /Edited by.혜경 (0) | 2023.06.19 |
호이스팅 - 이도영 (0) | 2023.06.18 |