객체지향 프로그래밍은 '사람이 세계를 보고 이해하는 방법을 흉내낸 방법론'이다.
사람들이 세계를 어떻게 보고, 어떻게 이해한다는 것일까? 간단히 우리가 출근하는 상황을 생각해보자. 일단 일어나서 씻고, 밥을 먹고, 지하철을 타고 회사에 도착한다. 별거 아닌 과정처럼 보이지만 하나하나 살펴보면 '샤워기'의 물을 트는 것, '숟가락'을 드는 것, '지하철'을 타는 것.. 모두 '어떤 대상'과 상호작용을 함으로써 한 행동들이다. 이렇게 사람이 세상을 살아가며 하는 행동들, 즉 '어떤 대상'(객체)들과 서로 영향을 주고 받는 행동을 흉내낸 것이 바로 객체지향 프로그래밍이다. 일단은 객체가 무엇인지부터 알아보며 객체지향 프로그래밍의 전반적인 그림을 완성해보도록 하자.
객체(Object)
객체는 말 그대로 어떤 대상을 말하는 단어이다. 현실에서는 바로 옆에 있는 컴퓨터, 핸드폰, 책, 옷부터 사람, 자동차...등 정말 눈에 보이는 무엇이든 객체가 될 수 있다. 게임으로 치면 캐릭터, 몬스터, 무기 등도 모두 객체에 해당된다.
객체 = 속성 + 행동 !
객체는 1) 속성 그리고 2) 행동으로 구성된다. 속성은 객체의 특징이나 상태를 말한다. 예를 들어 노트북이라는 객체가 있다고 하자. 색상, 무게, 해상도, 디스플레이 같은 특징들이 바로 노트북 객체의 '속성'이라고 할 수 있다.
행동은 객체의 동작, 기능, 행위 등을 말한다. 노트북의 화면이 켜지는 행동, 사용자로부터 키보드 입력을 받는 행동 모두 노트북 객체의 '행동'이라고 할 수 있다.
객체지향 프로그래밍(Object Oriented Programming)
객체지향 프로그래밍(OOP)은 앞서 설명한 '객체'들을 가지고 프로그래밍을 하는 것이다. 객체 지향 프로그래밍의 관점에서 프로그램이란 객체들을 모아둔 것이고, 그런 객체들이 서로 상호작용하는 과정을 프로그래밍 하는 것 이다.
사람이라는 객체를 하나 더 추가해 노트북에 글자를 입력하면 해당 글자를 출력하는 상황을 생각해보자. 이런 상황이 일어나려면 키보드를 누르는 행동, 글자를 보여주는 행동이 일어나야 한다. 그리고 이런 행동들은 '노트북' 객체와 '사람' 객체가 상호작용을 해야만 이루어질 수 있다.
객체지향 프로그래밍은 이처럼 객체(Object)들을 기준으로 하며, 객체들이 소통하는 과정을 코드로 작성하는 프로그래밍 방법이라고 할 수 있다.
위에서 객체 = 속성 + 행동 이라고 했던 것을 기억할 것이다. 프로그래밍에서는 '객체의 속성'은 보통 변수로, '객체의 행동'은 함수로 구현한다. 이렇게 보면 결국 프로그래밍에서의 객체는 변수와 함수의 묶음이라고 생각할 수 있지 않을까? 그리고 객체를 생성하고, 객체에 여러 속성과 기능을 부여할 수 있도록 하는 프로그래밍 방법을 '객체 지향 프로그래밍'이라고 볼 수 있을 것 같다.
객체 지향 프로그래밍 구현하기
좀 더 나아가 객체 지향 프로그래밍을 구현하는 과정도 생각해보자. 객체지향 프로그래밍은 결국 객체들이 협력하는 과정을 코드로 작성하는 방법이라고 했다. 그럼 우리가 이런 코드를 작성하기 위해 알아야 하는 건 어떤 것들이 있을까? 일단 어떤 객체들이 필요할 지부터 정해야 할 것이다. 그리고 그 객체들이 각각 어떤 속성, 행동을 포함하고 있는지도 알아야 한다. 그리고 마지막으로 각각 독립된 객체들이 서로 어떤 영향을 미치고 어떤 관계에 있는지 상호작용을 정의해야 할 것이다. 지금까지의 이야기를 정리해보면, 객체 지향 프로그래밍 과정은 아래처럼 세 단계로 이루어진다고 볼 수 있다.
1. 일단 어떤 객체들이 필요한 지 정의한다.
2. 각 객체들의 속성과 행동을 정의한다.
3. 객체들 간 상호작용을 정의한다.
클래스 (Class)
객체 지향 프로그래밍은 '클래스(Class)'라는 것을 기반으로 한다. 클래스는 쉽게 말하면 객체의 속성과 행동을 코드로 적어둔 것이다.
앞서 노트북의 속성으로 색상, 무게, 해상도, 디스플레이 같은 것들이 있다고 이야기했었다. 물론 노트북의 종류에 따라 색상이 빨간색일수도 검정색일수도 있고, 무게가 2kg일수도 3kg일 수도 있다. 이렇게 구체적인 값은 다를 수 있지만 모든 노트북이 색상, 무게, 해상도같은 속성(특징)을 갖는다는 사실은 공통적이다.
아직도 좀 추상적인 것 같으니 예시를 통해 이해해보자. 노트북이라는 객체들이 공통적으로 갖는 속성들(색상, 무게...)이 있다고 했는데, 이런 일반적인 속성들을 정의해둔 것이 클래스이다. 그리고 클래스의 속성들에 구체적인 값을 부여해주면 '객체'를 정의할 수 있게 된다. 아래처럼 노트북 클래스의 속성에 적절한 값을 부여하면 갤럭시북 객체를 만들수도, 맥북 객체를 만들 수도 있다.
좀 더 프로그래밍적으로 말을 정리해보면 클래스의 변수에 구체적인 값을 할당하면 객체를 정의할 수 있다는 것이다.
Javascript에서 객체를 생성하는 방법은 다음편에서 자세히 다루겠지만, 맛보기로 노트북의 경우를 코드를 작성해보면 대략 이런 형태가 된다.
class Notebook(색상, 해상도, 무게, 디스플레이) {
this.색상 = 색상;
this.해상도 = 해상도;
this.무게 = 무게;
this.디스플레이 = 디스플레이;
this.화면켜짐 = function() {화면 켜기};
this.키보드입력 = function() {키보드 입력받기};
}
var galaxyBook = new Notebook('네이비', '2560x1600', '1.2kg', '15인치');
var macBook = new Notebook('스페이스그레이', '2560x1600', '1.8kg', '16인치');
객체지향 프로그래밍의 특징 4가지
1. 캡슐화 (Encapsulation)
캡슐화는 한 객체에서 비슷한 역할을 하는 속성, 메서드를 캡슐처럼 한 곳(클래스)에 담는 것을 의미한다. 여기서 클래스 = 캡슐이라고 생각하면 된다. 이렇게 클래스가 미리 정의되어 있으면, 객체를 생성할 때는 클래스가 기본적으로 제공하는 속성(변수)이나 메서드들을 따로 정의하지 않고 편하게 사용할 수 있다. 캡슐화를 하게 되면 객체를 계속해서 생성하지 않아도 되기 때문에 재사용이 가능해진다는 장점이 있다.
캡슐화를 하는 또 다른 목적은 바로 정보은닉이다. 정보은닉은 말 그대로 정보를 숨기는 것인데, 객체의 구체적인 정보(변수, 메서드)를 외부에 노출시키지 않고 접근할 수도 없게 보호하는 방법이라고 할 수 있다. 캡슐화를 통해 정보를 은닉하면 그 정보는 오직 객체 내의 함수 내부에서만 접근이 가능해진다!
2. 추상화(Abstraction)
추상화는 복잡한 문제를 단순화시키는 작업을 말한다. '일반화'라고 이해하는 게 좀 더 쉽게 와닿을 것 같다. 단순화를 하기 위해선 우선은 관련 없는 부분은 제거하고, 딱 필요한 부분만 표현해야 한다. 프로그래밍에선 이런 추상화를 어떻게 구현할 수 있을까? 가장 필요하다고 생각하는 부분만 묶어두면 된다. 여기서 필요한 부분은 객체들이 공통적으로 갖고 있는 속성이나 메서드가 될 수 있다.
객체와 클래스의 관점에서 다시 한번 생각해보자. 각 객체들은 구체적인 값이 부여되어 실제하는 개념이지만, 클래스는 객체들이 가져야할 특성이나 기능들을 정의해둔 추상적인 개념이다. 정리하면, 추상화는 객체들의 공통된 특징들만 뽑아내는 기법이라고도 할 수 있다. 그리고 이 때 객체의 속성과 메서드의 이름만 선언만 할 뿐 구체적인 내용은 설계해두지 않는다.
3. 상속(Inheritance)
현실에서도 자식이 부모로부터 상속을 받는 것처럼, 객체 지향 프로그래밍에서도 자식 클래스는 부모 클래스로부터 상속을 받을 수 있다. 상속은 상위 클래스를 기반으로, 새로운 클래스와 행위를 정의할 수 있게 한다. 일반적인 노트북에 '제조사:애플'이라는 속성이 추가되면 맥북이 되는 것처럼 기존 클래스 속성을 유지하면서 + 동시에 새로운 속성 혹은 기능을 추가할 수도 있다.
상속 : '거의 같지만 예외가 있다'
정리하면 상속은 부모클래스의 속성과 기능을 그대로 이어받아 사용할 수 있게하고 기능의 일부분을 변경해야 할 경우 상속받은 자식클래스에서 해당 기능만 다시 수정(정의)하여 사용할 수 있게 하는 것이다. 상속 또한 코드를 재사용하기 때문에 중복을 제거할 수 있다는 장점이 있다.
4. 다형성(Polymorphism)
다형성도 말 그대로 '다양한 형태'를 가지는 특성을 말한다. 다형성은 상속과 관련되는 개념이며, 다형성을 구현하는 대표적인 방법 두 가지가있다.
Overriding(오버라이딩) : 부모클래스 메서드를 자식 클래스에서 재정의하는 것
Overloading(오버로딩) : 같은 이름으로 다양한 매개변수, 리턴타입의 메소드를 여러개 정의하는 것
상속을 받더라도 오버라이딩을 통해 자기 맘대로 다시 메서드를 재정의해 다양한 형태를 만들 수도 있고, 오버로딩을 통해 이름은 같지만 매개변수의 데이터 타입이 다른 메서드를 여러 개 정의할 수도 있어서 다형성을 구현할 수 있게 된다. 기본적으로 공통된 속성을 갖지만, 필요에 따라 다양한 기능을 추가하거나 덮어 씌워 응용을 할 수 있는 것이다.
요약
객체
✔️ 객체는 눈에 보이는 모든 대상
✔️ 객체 = 속성(특징, 상태) + 행동(동작, 기능)
✔️ 객체의 속성은 변수로, 객체의 행동은 함수로 구현한다.
객체 = (속성 + 행동) = (변수 + 함수)
객체 지향 프로그래밍
✔️ 객체 지향 프로그래밍 = 객체들이 상호작용하는 과정을 프로그래밍 하는 것
1. 일단 어떤 객체들이 필요한 지 정의한다.
2. 각 객체들의 속성과 행동을 정의한다.
3. 객체들 간 상호작용을 정의한다.
클래스
✔️ 클래스 = 객체의 속성과 행동을 코드로 적어둔 것
✔️ 클래스의 변수에 구체적인 값을 할당하면 객체를 정의할 수 있다!
객체지향 프로그래밍의 특징 4가지
1. 캡슐화 (Encapsulation) : 한 객체에서 비슷한 역할을 하는 속성, 메서드를 캡슐처럼 한 곳(클래스)에 담는 것
2. 추상화(Abstraction) : 복잡한 문제를 단순화
3. 상속(Inheritance) : 부모클래스의 속성과 기능을 그대로 이어받아 사용할 수 있게함 (일부 변경, 추가 가능)
4. 다형성(Polymorphism) : 다양한 형태를 가지는 특성 (by 오버라이딩, 오버로딩)
여기까지 객체지향 프로그래밍(OOP)가 무엇이고 어떤 특징이 있는지, 그리고 객체 지향의 핵심 개념인 '클래스'에 대해서도 알아보았다. 이어지는 글에서는 프로토타입기반 언어인 Javascript에서 Prototype을 통해 어떤 식으로 객체지향 프로그래밍을 구현하는 지 살펴보려고 한다.
'Language > Javascript' 카테고리의 다른 글
OOP (3) Javascript에서의 객체지향 프로그래밍 (ES6 이전의 Pseudoclassical한 방법) (0) | 2021.01.16 |
---|---|
OOP (2) Javascript의 Prototype 기반 객체지향 (0) | 2021.01.15 |
this(1) 상황따라 바뀌는 this (0) | 2021.01.14 |
실행 컨텍스트(Execution Context) (0) | 2021.01.13 |
undefined 제대로 알기 (2) null의 등장 (0) | 2021.01.10 |
댓글