1. 객체 지향 프로그래밍 ( Object Oriented Programing )

1) 객체

객체란 말 그대로 대상을 나타내는 단어입니다.

예를 들어, 사람 개인 한 명 한 명을 모두 객체라 할 수 있고, 책 한 권 한 권을 객체라 할 수 있습니다.


사람은 생김새와 성격이 똑같을 수는 없기 때문에 개개인을 객체라 할 수 있으며,

책도 내용이 같을지라도 한 권의 책에 흠집을 낸다고 해서 모든 책들이 전부 흠집이 나는 것이 아니기 때문에 한 권 한 권을 객체라 할 수 있습니다.




2) 클래스

사람들은 일반적으로 같은 속성들을 갖고 있습니다.

여기서 속성이란 눈, 코, 입, 손, 발, 등의 신체들을 의미합니다.

책도 책 이름, 작가, 출판사, 출판일 등 같은 속성을 갖고 있다고 할 수 있습니다.


사람, 책 같은 객체들이 공통적으로 갖는 속성들을 모아서 정의내린 것을 클래스라고 합니다. ( 이를 추상화라고 하는데 뒤에서 살펴보겠습니다. )

즉 사람이라는 클래스는 눈, 코, 입 등의 속성이 존재하고 객체들은 눈, 코, 입의 생김새가 다르기 때문에 다른 객체로 분류됩니다.


객체와 클래스는 많은 책들에서 붕어빵과 붕어빵을 찍는 기계라고 표현합니다.

처음 들었을 때는 무슨 소리인지 몰랐는데, 지금 시점에서는 정말 좋은 표현인 것 같습니다.

붕어빵을 찍어내는 기계는 붕어빵이라는 객체들을 생성하기 위한 틀을 제공합니다.

그래서 붕어빵 찍는 기계는 클래스라 표현할 수 있고, 붕어빵 틀에서 만들어진 붕어빵들은 각각이 객체가 됩니다.




3) 객체 지향 프로그래밍 ( OOP )

OOP는 객체의 관점에서 프로그래밍 하는 것을 의미합니다.

C언어를 절차 지향 프로그래밍이라 하는데, 절차 지향 프로그래밍은 프로세스가 함수 단위로 순서대로 진행되는 것을 말합니다.


반면 OOP는 객체들의 유기적인 관계를 통해서 프로세스가 진행됩니다.

즉, 애플리케이션을 구성하는 요소들을 객체로 바라보고, 객체들을 유기적으로 연결하여 프로그래밍 하는 것을 말합니다.


요즘 대부분은 OOP로 개발하기 때문에 OOP가 "원래 당연한거 아니야?"라고 생각할 수 있습니다.

그런데 처음 OOP 개념이 나왔을 때 신세계였다고 하네요...ㅎㅎ





2. OOP의 특징

이제 OOP의 특징에 대해 알아보도록 하겠습니다.

코드를 살펴보는 것은 조금 무리가 있을 것 같고, 구구절절 말로 풀어써보도록 하겠습니다.


1) 추상화

추상화는 목적과 관련이 없는 부분을 제거하여 필요한 부분만을 표현하기 위한 개념입니다.


지도에는 위성지도와 등고선지도 등 여러가지가 있는데, 각 지도마다 목적이 다릅니다.

  • 위성지도
    • 그 지형의 정확한 실제 모습을 담기 위한 목적의 지도
  • 등고선 지도
    • 지형의 높낮이를 표현하기 위한 목적의 지도

등고선 지도를 그릴 때, 목적에 맞지 않는 부분을 제외하고 필요한 부분(지형의 높낮이)만 표현합니다.


이를 객체와 클래스의 관점에서 살펴보겠습니다.

객체들은 실제 그 모습이지만, 클래스는 객체들이 어떤 특징들이 있어야 한다고 정의하는 추상화된 개념입니다.

다시 말하면, 추상화는 객체들의 공통된 특징을 파악해 정의해 놓은 설계 기법이라 할 수 있습니다.




2) 캡슐화

캡슐화에서 캡슐은 알약이라고 생각하면 됩니다.

혹시 알약을 깨물어본 적이 있으신가요?

알약을 깨물어 보면 그 안에 내용물은 정말 씁니다. (고통스러웠어요...)

알약 안에 있는 내용물은 정말 쓴 맛이기 때문에 사람들이 약을 먹지 않으려고 합니다.

그래서 내용물을 아무 맛도 안느껴지게 알약에 포장시켜서 사람들이 약을 쉽게 먹을 수 있도록 도와줍니다.

이것이 캡슐화입니다.


클래스 입장에서 캡슐화를 살펴보겠습니다.

자바에서 접근 제어자( public, protected... )가 있다는 것을 알고 계실겁니다.

private으로 정의된 속성은 외부에 노출 시키지 않고 자신의 클래스에서만 사용하기 위해 정의합니다.

즉, private으로 정의된 속성은 알약의 실제 내용물이라고 생각하면 됩니다.

엄청 쓴 맛이 나는 내용물이죠.

이 속성은 외부에 알려줄 필요가 없습니다.

즉, 정보은닉을 할 수 있다는 장점이 있죠.


참고로 캡슐화와 정보은닉은 동일한 개념이 아닙니다.

캡슐화를 하면 불필요한 정보를 감출 수 있기 때문에, 정보은닉을 할 수 있다는 특징이 있다는 것입니다.

예를 들어, TV의 리모콘을 사용하는데 리모콘의 내부 회로(private으로 정의된 속성)를 알 필요가 있느냐 하는 것이죠.

사용자 입장에서는 리모콘의 조작 기능, 즉 public으로 정의된 속성만 알면 됩니다.

제가 처음 객체지향을 접했을 때, 오해했던 부분이라 말씀드리게 되었네요.





3) 상속

실제 세계에서 부모로부터 여러 가지를 상속을 받는데, OOP에서도 가능합니다.

OOP에서 이를 부모 클래스, 자식 클래스라고 표현합니다.


예를 들어, 고양이 클래스, 강아지 클래스가 있다고 하겠습니다.

그런데 고양이와 강아지는 생물학적 관점에서 포유류에 해당합니다.

포유류는 여러 속성들이 정의되어 있는데 고양이와 강아지는 포유류의 이런 속성들을 갖고 있습니다.

하지만 아주 많은 속성이 다르기 때문에 좀 더 디테일하게 고양이, 강아지로 종을 나뉘게 된 것이죠.


즉, 포유류라는 클래스는 고양이와 강아지 클래스에 속성들을 물려줍니다.

이것을 상속이라고 하고, 포유류와 고양이, 포유류와 강아지 클래스는 상속관계에 있다고 합니다.


상속이 필요한 이유는 코드의 중복을 없애기 위함입니다.

코드의 중복이 많아지면 개발 단계에서도 피곤하지만, 유지 보수에서도 많은 비용이 들게 됩니다. ( => 코드의 이원화 문제 )

그래서 개발을 할 때 코드의 중복은 반드시 피해야 합니다.


OOP에서는 상속을 통해 코드의 중복 문제를 일부 해결할 수 있습니다.

포유류 클래스에 여러 속성들을 정의해 놓고 포유류에 해당하는 종, 예를 들면 강아지 클래스가 필요할 경우 포유류 클래스와 상속 관계를 맺습니다.

상속관계를 맺으면 자식 객체를 생성할 때 부모 클래스의 속성들을 자동으로 물려받기 때문에 자식 클래스에서 또 정의할 필요가 없습니다.

이것이 상속이 필요한 이유입니다.




4) 다형성

다형성은 형태가 같은데 다른 기능을 하는 것을 의미합니다.


예를 들면, 고양이 클래스에는 "울음"이라는 속성이 정의되어 있다고 하겠습니다.

사자는 고양이 과이기 때문에 사자 클래스는 고양이 클래스를 상속 받는다고 하면, 사자 클래스에도 "울음"이라는 속성이 자동으로 추가됩니다.

앞에서 이것을 상속이라 했습니다.


그런데 고양이와 사자의 울음소리는 다르다는 것을 알고 있습니다.

고양이는 "야옹", 사자는 "크허헝" 인가요...? 어쨋든 사자는 무섭게 울어댑니다.

같은 "울음" 속성임에도 실제 울음소리는 다르죠.

이것이 다형성입니다.


부모 클래스로부터 상속을 받은 속성에 대해, 자식 클래스에서 물려받은 속성을 재정의 할 수 있습니다.

이것을 오버라이딩이라고 합니다.

즉, 사자 클래스는 부모클래스인 고양이 클래스의 "울음" 속성을 상속 받았지만, 사자는 고양이와 울음소리가 다르므로 "울음" 속성을 오버라이딩 해서 사자 울음소리에 맞게 재정의 할 수 있습니다.

OOP에서는 이러한 다형성을 허용하는 것이죠.


그럼 다형성을 사용하면 좋은 점은 무엇일까요?

같은 이름의 속성을 유지함으로서, 속성을 사용하기 위한 인터페이스를 유지하고, 메서드 이름을 낭비하지 않는다는 것입니다.

예를 들어, 고양이와 사자의 울음소리를 호출하기 위해서 각 개체에서 roar() 메서드를 호출하면 됩니다.

roarCat() , roarLion() 으로 각각을 정의할 필요가 없다는 것이죠.

API가 많아질수록 복잡성은 증가하기 때문에 다형성은 유용합니다.





3. 정리

  • OOP
    • 객체들이 서로 유기적으로 동작하는 프로그래밍 이론
    • 코드의 재사용성과 중복제거가 가장 큰 목적
  • 추상화
    • 목적과 관련이 없는 부분을 제외해서 필요한 부분을 포착하는 기법
    • 객체의 공통된 속성들 중 필요한 부분을 포착해서 클래스로 정의하는 설계 기법
  • 캡슐화
    • 외부에 노출할 필요가 없는 정보들은 은닉 (정보은닉)
  • 상속
    • 상속 관계에 있는 두 클래스에 대해, 부모 클래스가 자손 클래스에게 속성을 물려주는 것
    • 코드의 재사용이 목적
  • 다형성
    • 같은 형태이지만 다른 기능을 하는 것
    • 오버라이딩은 이와 관련된 기능임


이상으로 OOP에 대한 개념과 주요 특징에 대해 알아보았습니다.

결국에 OOP를 한다는 것은 어떻게 하면 유지보수를 잘 할 수 있을까의 관점인 것 같습니다.