객체지향 패러다임 (Object-Oriented Paradigm) C/C++


소프트웨어의 역할을 한번 정의해 봅시다.
기본적으로 소프트웨어는 하드웨어와 대칭되는 개념으로써,
하드웨어(HardWare) 는 몸체인 반면 소프트웨어(SoftWare)
실제하는 몸체를 조정해 주는 것으로 많이 이야기됩니다.

생활 속에서 하드웨어를 찾아보도록 합시다. 우리가 사용하는 컴퓨터도
하드웨어인 것이고, TV 리모컨 등도 하드웨어의 범주에 포함될 것입니다.
여기서 우리는 각각 하드웨어의 입력 장치를 사용하여 이를 컨트롤 할 수
있습니다. 이때 입력 처리에 대응하여 하드웨어의 동작을 제어하는 것이
소프트웨어입니다. 둘의 관계는 그야말로 뗄래야 뗄 수 없는 관계인 것입니다.

그렇다면, 소프트웨어 개발이라는 것은 무엇을 의미하는 것일까요?

하드웨어의 기능을 제어하는 프로세스를 준비하여, 원하는 동작을
컨트롤 할 수 있도록 하는 것이라 할 수 있지 않겠습니까?

때문에 이런 식의 제어 프로세스를 구성하는 방식에 대한 고민 역시,
소프트웨어 공학의 발전과 함께였습니다. 최근의 추세는 하드웨어와의
직접적인 연계를 다루는 시스템 소프트웨어 (System SoftWare) 뿐만 아니라,
시스템 소프트웨어와 상호작용을 통해 추가적인 기능을 제공하기 위한
응용 소프트웨어 (Application SoftWare) 분야가 활발해지면서 이러한 제어
프로세스를 구성하는 방법론은 더욱 중요성이 커졌다고 얘기할 수 있습니다.

( 이들 관계를 쉽게 표현하자면, 시스템 소프트웨어는 운영체제(OS) 를 생각하시면
 되고, 응용 소프트웨어는 운영체제 위에 올리는 프로그램들을 생각하시면 됩니다^^
 윈도우 환경이라 생각하면, 인터넷 익스플로러, 워드, 엑셀 등과 같은 프로그램들이
 응용 소프트웨어에 포함되는 것입니다. 또한 스마트폰 프로그램을 일컫는 "앱" 이라는
 단어 역시 어플리케이션 소프트웨어의 앞 단어 App 을 지칭하는 것이지요)



  하드웨어 (HardWare)  : 실재하는 몸체, 기기를 일컫습니다.
  소프트웨어(SoftWare) : 하드웨어를 제어하는 프로세스를 일컫습니다.

  시스템 소프트웨어 (System SoftWare)
    - 하드웨어와의 직접적인 관계를 가지며, 하드웨어를 제어하는 기능을
      가지는 소프트웨어, 기존에는 이런 성향의 소프트웨어만 존재했었습니다.

  응용 소프트웨어 (Application SoftWare)
    - 하드웨어를 제어하는 시스템 소프트웨어가 존재하는 상태에서
      시스템 소프트웨어와의 상호작용을 통해 추가적인 기능을 제공하기 위한
      목적을 가진 소프트웨어입니다.



서론이 조금 길어진것 같습니다만, 여기서부터는 본론으로 들어가 보겠습니다.
이처럼 중요한 소프트웨어 개발의 방법론은 결국에는 요약하면 현대에는 크게 2가지
분류로 나눌 수 있습니다.

하나는 기능 위주의 관점으로 원하는 기능을 하향식으로 보다 세분화하고
구체화해 가면서 만들어가는 구조적 패러다임 (Structured Paradigm) 이며,
나머지 하나는 데이터 위주의 관점으로, 모든 내용을 객체 단위로 관리하고,
이들 사이의 상호작용을 정의하는 것으로 기능을 포괄시켜 나가는 방식인
객제지향 패러다임 (Object-Oriented Paradigm) 입니다. 
이외에 최근에는 관점지향 패러다임도 등장하여, 객체지향 패러다임의 단점을
극복하려는 움직임도 활발한 편입니다.

구조적 방법론은 기본적으로 소프트웨어를 생산할 때, 
기능 (Function) 과 프로세스 (Process) 에 집중하게 됩니다.
특정 상황에 대해서 필요한 기능을 정의하고, 이 기능을 완성하기 위한
파츠를 구성해 나가는 방식이 여기에 해당됩니다.

이 방식은 객체지향적 접근 방식보다 초기 접근 방식이 매우 쉽습니다.
사실 소프트웨어라는 것은, 특정 조건에 맞추어 (조건은 사용자의 입력처리도 포함하죠)
수행할 동작을 지정하고, 분기에 따라 처리를 분할할 수만 있으면 목적을
달성하는 것이라 할 수 있습니다.

때문에 상황을 파악하고, 여기에 대응되는 기능 (Funtion) 을 절차적으로
수행하는 것에 집중하는 구조적 방법론은, 오로지 해결방안을 찾으며 필요한
알고리즘에만 집중하여 높은 생산성을 가질 수 있습니다.

하지만 객체지향 방법론은 기능구현을 먼저 생각하는 것이 아니라,
먼저 제시된 상황 속에서 특정 대상을 객체(데이터) 로 정의하고, 이 데이터를
관리하고 다룰 수 있는 인터페이스를 먼저 마련하게 됩니다.
그리고 마련된 인터페이스 간의 상호작용을 통해 필요한 기능까지 할 수 있도록
소프트웨어를 생산하는 것으로,

기능 자체에 관점을 두는 구조적 방법론에 비해 복잡하며, 2단계를 거쳐
소프트웨어를 생산하게 됩니다. 때문에 객체지향 방법론이 이후에 등장한 패러다임
이라고 해서 우월하다고는 할 수 없는 것입니다.




한가지 예를 들어 볼까요? 상황에 맞추어 어항 속의 금붕어에게 먹이를 지급하는
기기에 필요한 소프트웨어를 만드는 상황을 가정해 봅시다.


여기서 구조적 방법론으로 접근한다면...




1. 먼저 이전에 먹이가 지급된 시간으로부터 얼마나 지났는가 체크해주는
    함수를 준비합시다...
2. 물의 온도에 따라서 지급 빈도를 조절해야 하니까 온도를 체크할 
    함수가 준비합시다...
3. 시간과 온도에 따라서 지급 유무를 결정하는 함수를 준비합시다...

 -> 여기까지 조건을 지정하는 함수입니다.

4. 시간이 되었고, 지급 유무의 결과가 참이라면 먹이통을 열어줘야 하므로,
   먹이통을 여는 함수를 준비합니다..
5. 지급 후 먹이통을 닫는 함수를 준비하자. 이때 마지막 지급 시간을
   갱신해 주도록 합시다...

-> 실제 먹이통을 열고 닫는 처리입니다. 먹이를 지급하는 행위는 어디까지나
    통의 문을 열어주는 기능을 만들면 되는 것이니까요.
    마지막으로, 지급 시간을 갱신하는 처리는, 알고리즘을 다시 최초로 돌려준다는
    의미가 있습니다.




이런 식으로, 어항의 상황을 조건으로, 하여 먹이통을 열고 닫는 기능을 생각해
나가면 됩니다. 모든 관심사는 먹이통을 어떤 빈도로 열고 닫는가에 집중되어 있습니다. 


이 상황에 대해서 객체지향적으로 접근한다면 

이런 식으로 사고해야 합니다...




1. 어항을 하나의 객체로 만듭니다.
 
   - 어항 객체는 내부적으로 온도값을 가지고 있으며,
     어항 내부의 온도를 측정하여 기록하는 기능을 가지고 있습니다.
   - 측정된 온도는 객체 내부의 멤버변수로 보관되었다가
     외부로 값을 전달할 수 있는 처리를 포함합니다.  

2. 기계를 하나의 객체로 만듭니다.

   - 기계 객체는 먹이통을 열고 닫는 제어기능을 가집니다.
   - 외부로부터 메세지를 받아 먹이통을 열고, 스스로 시간을 재고
     시간이 되면 먹이통을 닫게 됩니다.
   - 먹이를 지급했던 최종 시간을 보관하고 있으며 일정 수준의
     시간이 지났는가를 bool 형 변수로 보관하여, 참 거짓을
     반환할 수 있습니다.

이번에는 현재 상황에서 "어항" "기계" 라는 대상에 집중하고,
이들을 객체(데이터) 로 먼저 만들게 됩니다.

어항 객체는 스스로 온도를 측정하고, 이 온도를 외부로 전달할 수 있습니다.
기계 객체는 먹이통을 열고 닫는 기능을 가지고 있습니다.
이렇게 대상을 객체화하는 것이 첫번째 단계입니다.

이후 객체가 준비되었다면, 서로 상호작용하는 작업을 외부에 마련합니다.
외부의 작업 처리는 이런 식이 되겠지요.

1. 기계 객체로부터 마지막 지급 시간으로부터 일정시간이 지났는가에
    대한 유무를 결과로 받는다.
2. 어항 객체로부터 온도에 따른 지급 유무를 결과로 받는다.
3. 이 두 조건이 모두 참이라면, 기계 객체에 먹이통을 열어라는
   메세지를 전달한다.

여기까지의 단계를 거치게 되면 비로소, 원하는 기능을 처리할 수 있는 구조적
기반을 마련한 것이 됩니다.




객체지향 방법론은 이런 식으로, 먼저 상황에 대해서 객체의 인터페이스를
정의하고 이들 간의 상호 작용을 통해 실제 처리를 구성하는 2중 과정을 거쳐야 합니다.
뿐만 아니라, 객체를 정의하는 것은 기능을 만드는 것에 비해 매우 추상적인 개념이며
정답이 없으므로, 기준이 모호합니다.

또한 특정 상황에 대해서 접근할때에, 구조적 방법론에 비해서 복잡하며,
아무리 간단히 구성한다고 하더라도 최소한의 구조를 강요합니다.

때문에 객체지향적 방법론은 트리 구조로 만들어지는 구조적 방법론에 비해서
그래프나 네트워크적 구조를 띄게 됩니다. 객체 간의 통신이 기능을 수행하는데
있어 핵심이 되는 방식이기 때문이지요.

이런 단점을 가지고 있음에도, 객체지향 방법론은 현재, 구조적 방법론에 비해서
많이 각광받고 있으며, 대부분의 개발 프로젝트에서 사용되고 있습니다.
(아직 관점지향적 패러다임은 정립되기엔 시간이 더 필요하다고 생각합니다.)

그렇다면 객체 지향 패러다임의 장점은 무엇일까요?
아래에 몇가지 장점을 나열해 보겠습니다. 이 장점은 객체지향 방법론이
사용되는 이유이기도 합니다.



* 설계 단계가 필수적입니다.
  (주먹구구식 개발을 원천적으로 피하게 됩니다.)

  객체지향적 방법론은 설계 단계를 어느정도 강요합니다.
  객체를 구성하고 (1단계) 상호 연동을 통해 기능을 수행하는 (2단계)
  2중 처리가 필요하므로, 클래스의 설계 없이는 소프트웨어를 작성하는것이
  매우 힘듭니다. 때문에 설계 단계는 반드시 거쳐야 하는 단계인 것이지요.
  하지만 명확한 설계 단계를 거치고 나면, 개발 도중 치명적인 문제가 생길
  확률이 현저히 저하되므로, 설계 단계가 있어야만 개발을 할 수 있다는 
  것은 오히려 장점이 될 수 있습니다.

* 유지, 보수가 쉽습니다.

  객체지향적 방법론은 구조적 방법론에 의거하여 개발을 하는 것에 비해
  유지 보수가 쉽습니다. 왜냐하면 처음부터 객체(데이터) 를 중심으로
  일부 범위를 묶어서 소프트웨어를 개발하고 있었으므로, 수정해야 할
  범위가 명백하게 정의될 수 있습니다.
  구조적 방법론으로 개발하는 환경이었다면, 전체 기능이 절차적으로 
  차례로 구성되어 있게 되므로, 일부를 수정하는 일이 전체를 수정하는 것으로
  번질 위험이 있습니다. 때문에 유지 보수 측면에서 객체지향적 방법론이
  보다 쉽다고 할 수 있는 것입니다.

* 재사용에 강합니다.

  객체(데이터)를 구분짓는다는 것의 의미를 생각해 봅시다.
  특정 개념을 일단 단위별로 묶은 것이고, 이러한 객체는, 로직이 변경
  된다고 해서 크게 변경되는 성질의 것이 아닙니다. 
  때문에 비슷한 성질을 가진 객체가 여럿 필요한 경우 재사용하기
  좋습니다. 
  또한 클래스 간의 상속 기능을 통해 기존 클래스를 재사용하여
  확장된 객체 모델을 구성할 수도 있습니다. 상속성은 객체지향 방법론에서
  매우 중요한 개념 중 하나이며, 재사용의 측면에서 큰 이점을 가집니다.



  
전체적으로 봐서 객체지향적 방법론은, 설계를 거치며, 유지보수가 쉬운 등,
구조론적 방법론에 비해서 보다 체계적이고, 불필요한 낭비를 막는 등의
성질이 있습니다. 때문에 객체지향적 방법론이 더 좋은것 같은 인식이
퍼질 수 있었던 것이죠. (물론 우월성은 절대로 따질 수 없습니다.)

이는 구조론적 방법론이 문제가 있어서가 아니라,
구조론적 방법론은 오로지 주어진 문제를 해결하는데 촛점을 맞춘 것이고,
객체지향적 방법론은, 상황에서 성질이 크게 달라지지 않을 객체를 구상하는
것에 더 촛점을 맞추었기 때문에 생기는 차이점입니다.
변화에 좀 더 강하다는 성질을 가지는 것이죠. 대신에 처음에 구조를
잡는 어려움이 있는 것이구요.

오히려 많은 기능을 가지지 않으며, 개발 기간이 짧은 경우에는 
구조론적 방법론이 훨씬 더 좋을 것입니다. 
다만 요즘의 소프트웨어는 예전에 비해서 대형화되고, 많은 기능을 가질
뿐만 아니라, 클라이언트의 요구에 따라서 자주 변화하기 때문에
객체지향적 방법론이 이러한 시대의 흐름에 더 맞았던 것일 뿐입니다.

물론 객체지향적 방법론의 단점은 있습니다. 단순히 복잡하다와 같은
식의 단점이 아니라, 근본적인 문제점 말이죠.
객체지향적 방법론은 객체화를 설계하는데, 주안점을 맞추고 있습니다.
그 덕택에 상황에서 객체의 범위를 정하고, 쪼개는 작업에 적합합니다.

일부 속성만 포함화여 묶인 객체는 독립적으로 구성되므로,
추상성 및 은닉성까지 가질 수 있는 것이지요.

하지만 완전한 독립을 이루기는 어렵습니다.
최근의 소프트웨어 프로젝트는 너무 거대화 되었고,
매우 다양한 기능을 요구하고 있습니다. 
때문에 특정 객체 단위로 명확한 설계를 하기가 점차 
어려워지고 있습니다. 

여기서 발생하는 문제는 모듈의 분할입니다. 특정 기능이 여러 객체에
분할되는 것을 이야기하는데요, 이 경우 객체 간의 의존성이 심각해지고,
설계 구조가 엉키게 됩니다. 그리고 객체지향 특유의 은닉성 탓에
유지보수를 더욱 어렵게 만들 수 있습니다.

이런 단점을 극복하기 위해서 최근에는 
관점지향적 패러다임 (Aspect-Oriented Paradigm) 이 논의되고 있습니다.
AOP는 객체 지향 패러다임을 대체하는 기술이 아니라,  위의 단점을
극복하기 위한 방법론입니다. 설계상 예외 영역을 하나로 모으는 식으로
처리하거나 여러 곳에서 참조되는 특정 함수에 대한 통제 등을 
중앙집중화하여, 위의 객체지향의 단점을 극복하는데 촛점을 맞춥니다.

향후에는 객체지향 패러다임에 이러한 내용을 추가하는 식으로
발전되어 갈 것으로 생각됩니다. 객체지향 패러다임은 아직 발전과정에 있다고
여겨지며, 향후에는 보다 나은 방법론이 되지 않을까 조심스레 생각해 봅니다.




덧글

댓글 입력 영역


라운드 시계