객체 지향 프로그래밍(OOP, Object-oriented programming)이란?
- 객체 지향 프로그래밍은 사람이 세계를 보고 이해하는 방법과 매우 흡사하다. 우리가 주변의 실세계에서 사물을 인지하는 방식을 프로그래밍에 접목하려는 사상을 의미하며 코드를 추상화하여 직관적으로 생각할 수 있기 때문에 이미 오래전부터 프로그래밍 방법론으로 빠르게 적용되었다.
- 많은 프로그래밍 언어(Java, C++, C#, Python, PHP, Ruby)는 객체지향 프로그래밍을 지원하는데 JavaScript는 Java의 Class와는 다르게 Prototype으로 객체 지향 언어를 구현한다.
- 객체 지향 프로그래밍은 절차 지향 프로그래밍과는 다르게 데이터와 기능을 한곳에 묶어서 처리한다. 속성과 메서드가 하나의 객체라는 개념에 포함되며 각 객체는 메시지를 받을 수도 있고, 데이터를 처리할 수도 있으며, 또다른 객체에게 메시지를 전달할 수도 있다. 각 객체는 별도의 역할이나 책임을 갖는 작은 독립적인 기계 또는 부품으로 볼 수 있다.
클래스와 인스턴스
객체 지향 프로그래밍은 하나의 모델이 되는 청사진(Blueprint)을 만들고 -> class
그 청사진을 바탕으로 한 객체(Object)를 만드는 -> instance
프로그래밍 패턴이다.
class
class Laptop {
constructor(brand, name, color) {
// 인스턴스가 만들어질 때 실행되는 코드
}
}
- 클래스는 class 키워드를 사용하며 대문자로 시작한다.
- 생성자 함수라 부르며 인스턴스가 만들어질 때 실행되는 코드이다.
instance
let galaxyBook = new Laptop('samsung', 'galxyBook', 'black');
let macBook = new Laptop('apple', 'macBook', 'spacegray');
let gram = new Laptop('LG', 'gram', 'white');
- 인스턴스는 new 키워드를 사용하여 만든다.
- 즉시 생성자 함수가 실행되며 변수에 인스턴스가 할당된다.
- 각각의 인스턴스는 클래스의 고유한 속성과 메서드를 갖는다.
속성과 메서드
- 객체 지향 프로그래밍에서 속성과 메서드는 현실 세계를 생각해보면 조금 더 쉽게 와닿는다. 예를들어 Laptop의 속성은 브랜드, 이름, 색상, 배터리 상태, 저장공간 등이 있을 수 있고 메서드(객체에 딸린 함수)는 전원on/off, 배터리 충전, 게임, 공부 등이 있을 수 있다.
- 이와 같이 객체지향 프로그래밍은 현실 세계를 기반으로 프로그래밍 모델을 만들 때 유용하다.
속성의 정의
class Laptop {
constructor(brand, name, color) {
this.brand = brand;
this.name = name;
this.color = color;
}
}
- this는 인스턴스 객체를 의미하며 매개변수로 넘어온 브랜드, 이름, 색상은 인스턴스 생성 시 지정하는 값이다
위와 같이 this에 할당한다는 것은 만들어진 인스턴스에 해당 브랜드, 이름, 색상을 부여하겠다는 의미이다.
메서드의 정의
class Laptop {
constructor(brand, name, color) {
this.brand = brand;
this.name = name;
this.color = color;
}
powerOn() {
}
batteryCharge() {
}
}
- 생성자 함수와 함께 class 키워드 안쪽에 묶어서 정의한다.
인스턴스에서의 사용
let galaxyBook = new Laptop('samsung', 'galxyBook', 'black');
galaxyBook.brand; // 'samsung'
galaxyBook.powerOn(); // 전원을 시작합니다
let macBook = new Laptop('apple', 'macBook', 'spacegray');
macBook.color; // 'spacegray'
batteryCharge(); // 배터리를 충전합니다
객체 지향 프로그래밍의 특징
1. Encapsulation (캡슐화)
- 데이터와 기능을 하나의 단위로 묶는 것
- 은닉(hiding): 내부 데이터나 구현은 숨기고 동작(메서드)은 노출시킨다.
- 느슨한 결합(Loose Coupling)에 유리, 코드 실행 순서에 따라 절차적으로 작성하는 것이 아닌 코드가 상징하는 실제 모습과 닮게 코드를 모아 결합한다.
- 코드의 복잡성을 줄이고 재사용성을 높인다.
2. Inheritance (상속)
- 부모 클래스의 특징을 자식 클래스가 물려받는 것
- 기본 클래스(base class)의 특징을 파생 클래스(derived class)가 상속받는 것
- 불필요한 코드를 줄여 재사용성을 높인다.
3. Abstraction (추상화)
- 내부 구현은 복잡하지만 실제로 노출되는 부분은 단순하게 만든다는 개념(인터페이스 단순화)
- 코드의 복잡성을 줄이고 단순화된 사용으로 변화에 대한 영향을 최소화
- 캡슐화가 은닉에 포커스가 맞춰져있다면 추상화는 클래스를 사용하는 사람이 필요하지 않은 메서드를 노출시키지 않고 단순한 이름으로 정의하는 것에 포커스가 맞춰져 있다.
4. Polymorphism (다형성)
- Polymorphism이라는 단어의 poly는 '많은', morph는 '형태'라는 뜻을 가지고 있으므로 '다양한 형태'를 가질 수 있다는 것을 의미한다.
- 같은 객체도 상황에 따라 다르게 동작 할 수 있다.
- 동일한 메서드에 대해 if/else if와 같은 조건문 대신 객체의 특성에 맞게 달리 작성하는 것이 가능해진다.
결론
사람이 세계를 보고 이해하는 방법을 흉내 낸 방법론
- 객체 지향 프로그래밍 패러다임을 따라가 보면 사람이 세계를 보고 이해하는 방법과 매우 흡사하다고 느끼게 될 것이다.
- 코드 상에서 혹은 화면에 보이는 하나의 요소를 객체 단위로 구분시켜서 생각하면 보다 이해하기 쉬운 코드를 작성할 수 있게 된다. OOP의 특성을 이해하고 잘 사용하면 좋은 설계를 할 수 있다.