본문 바로가기

객체지향

[POCU-OOP] 개체지향 프로그래밍의 필요성

 이 포스팅은 POCU 아카데미의 '개체지향 프로그래밍 및 설계(Java)' 동영상 강의를 학습하고 정리한 내용입니다.

제 의견이 추가되어 강의 내용과 포스팅 내용이 일치하지 않을 수 있다는 점 미리 말씀드립니다.

 

 


 

 

개체지향 프로그래밍의 필요성

 OOP가 어떻게 등장하였는지, OOP를 하는 이유는 무엇인지 알기 위해, 과거로 거슬러 설명한다.

절차적 언어(C언어)에서 데이터를 표현하려면 다음과 같이 나타낼 수 있다.

String[] : 배열 김땡땡 김밥
int[] : 배열 2019001 2019002
int[] : 배열 4.1 4.5

 

 위 데이터에서 나타내는 것은 {김땡땡,2019001,4.1} , {김밥,2019002,4.5} 이지만, 데이터의 컬럼(ex. 이름) 별로 배열을 생성하여, 병렬적으로 저장하고 있다. 이는 사람이 봤을 때 직관적인 형태가 아니며, 데이터가 많아질 경우 관리가 힘들다는 단점이 있다.

 

이러한 불편사항을 해결하기 위해 C언어에서는 구조체(struct)를 도입하였다.

  • 데이터를 그룹으로 묶어 새로운 데이터형을 만드는 방법
  • 이 그룹을 마치 하나의 ‘변수’처럼 사용
struct Hunam
{
	int age;
	float height;
}

 하지만, 데이터와 동작이 분리되어 있기 때문에, 함수 사용시 어떤 구조체가 어떤 함수와 연관되어 있는지 연결짓는 비용이 든다는 단점이 있다.

// 데이터
struct Hunan
{
	int age;
	float height;
}

struct Dog
{
	int age;
	string name;
}
void increasAge(Dog* dog, int age){}
void walk(Huanm* hunam){}

 

 

 

 위에서 단점을 언급할 때 ‘인간의 이해방식’ 과 관련하여 말하였다. 사람은 어떠한 방식으로 세상을 인지할까? 사람은 세상을 물체(object)의 집합으로 인지한다. OOP에서의 개체(object)는 상태를 가질 뿐만 아니라 동작도 할 수 있다.

 

 실생활에서 어떤 행위를 요청하려고 할 때, 행위(WHAT)를 수행하는 대상(WHO)에게 요청한다. 이때 대상에 대한 모든 정보를 알아야할 필요성은 없다. 행위를 요청하기 위한 정보만 알고 있으면 된다. 이러한 관점에서 ‘인간’ 이라는 개체를 가정한다면 다음과 같이 표현된다.

  • ‘인간’의 상태(변수, 데이터)
String name; 
int age; 
Sex sex; // enum
  • ‘인간’의 동작(함수)
void walk(); 
void eat(); 
void speak();

 

 

 

 그러나 세상의 모든 것이 상태와 동작을 갖는 개체인 것은 아니다. 예를 들어 단순한 상태를 갖고, 변경하는 대상이 되는 경우, 해당 대상은 동작 없이 상태만 갖을 수 있다.

  • EX) 엑셀 데이터
원금 이자
100 200

 

반대로 행위만 갖고 있을 수 있다.

  • EX) 인터페이스
public interface helloable{ void hello(); }

 

즉, 반드시 모든 대상이 개체 이여야 하는 것은 아니다.

 

 

 

 

돌아가서, OOP를 이해하기 위해, ‘개체지향 프로그래밍’과 ‘절차적 프로그래밍’을 비교하겠다.

절차적 프로그래밍

 절차적 프로그래밍은 OOP와 비교했을 때 매우 객관적이다. 절차적 프로그래밍 언어의 대표주자인 C언어는 다음의 특성을 갖는다.

  1. 기계어는 위에서 아래로 차례대로 실행
  2. 어셈블리 명령어는 거의 모든 경우 기계어로 1:1 치환 가능
  3. C 언어로 작성한 코드 한 줄은 보통 어셈블리 명령어 몇 개로 치환 가능
  4. 함수 호출은 특정 메모리 위치로 점프해서 순서대로 명령어를 실행
  5. 그 명령어 실행 결과에 따라 레지스터 or 메모리에 저장된 데이터가변경

(→ 물론 모든 프로그램은 ‘컴퓨터에서 실행되는 관점’으로 봤을 때 절차적으로 실행된다.)

위 특성과 같이 인간의 주관적인 사고가 개입될 여지가 매우 적으며, 객관적이라고 판단할 수 있다.

 

개체지향 프로그래밍

 OOP는 “프로그램을 구성하는 기본 요소를 개체로 보려는 노력 or 패러다임”이다. OOP에서 프로그램은 상호작용하는 개체들의 집합으로 인식된다. (반면, 절차적 프로그래밍에서는 실행할 명령어의 목록으로 보았다.)

 

 그렇다면, 왜 OOP에서는 프로그램 요소를 개체로 보려고 하였을까? 프로그램을 인간의 사고방식으로 이해하기 위함이다. 사람은 세상을 볼 때 개체(object)의 집합으로 인식하기 때문에, 프로그래밍도 이러한 방식으로 접근하여, 더 쉽게 이해할 수 있도록 만들기 위함으로 유추된다. 하지만 ‘인간의 사고방식’이라는 말 자체가 매우 주관적이다. 개개인의 사고방식은 완벽히 동일할 수는 없으며, 대중(다수의 사람)이 옳다고 생각하는 방식이 곧 ‘인간의 사고방식’으로 정의할 수 있다.

 

 ‘인간의 사고방식’을 정의하는 필자의 의견도 물론 주관적이며, 사회와 기술이 발전하면서 사람들의 사고방식은 변화한다. OOP가 주관적이라는 근거이다. 다행히도 다수가 따르는 OOP 개념이 존재한다. Java, C#, C++ 등의 주류 OOP 언어들이 그러하다.

 

 

OOP에서 말하는 개체(object)는 아래 항목을 따른다.

  • 개체란 서로 연관있는 상태와 동작을 가지고 있다.
  • 사람들은 기본적으로 세상을 개체들의 모음으로 본다.

 

OOP에서의 재사용성

 OOP에서는 재사용성을 중요시한다. 어떠한 근거로 그러할까? "바퀴를 발명하지 마라"라는 문장을 통해 힌트를 얻을 수 있다. 바퀴는 설계, 구현, 테스팅까지 모두 마친 "동작과 상태"가 명확한 물체이다. 이걸 그대로 사용하여 유용한 물체를 만드는 것이 더 효율적인 방향이다. 이러한 이유로 재사용성을 중요시한다.

 이러한 특징은 OOP가 설계와 코딩에 드는 시간을 줄여준다는 장점을 제공한다. 하지만, 프로그램이 미래에 어떻게 변할지 완벽히 예측하는 것은 불가하기 때문에, 재사용성에 눈이 멀어 잘못될 바퀴를 장착해서는 안된다.

 추가적으로, 테스트에 걸리는 시간을 줄여주고(상속 or 컴포지션), 관리 비용을 절약해준다는(코드 중복X) 장점을 제공한다.

 

OO 모델링 실력을 키우는 방법

OOP는 주관성이 높은 영역이기 때문에 몇 가지 베스트 프랙티스를 학습하는 것으로는 간단히 정리가 불가능하다. 모델링을 직접 많이 해보면서, 실패하고 어떤 방식이 효과적인지 경험해야한다. 프로그래밍 언어를 배울 때처럼 쉽게 얻을 수는 없는 것이다. 지름길은 없지만 참고할 사항은 존재한다.

  • 기본 : 많은 코딩 경험만이 해답이다.
  • 부가적인 도움 : 잘 설계된 코드(ex. 유명한 오픈소스 , Java or C#의 자체 제공 라이브러리)를 많이 사용해 보기.

'기본'과 '부가적인 도움'을 둘 다 해야 한다. OO는 주관성이 크기 때문에, 경험이 쌓일 수록 능력이 올라가는 영역이다. 따라서 지름길을 찾으려는 욕구에 주의해야 한다.

 

 

TIP : OOP 토론 시 피해야 할 사람
- 처음 듣는 주장을 하며 ‘그건 올바른 OOP가 아니야!’라는 사람
- ‘이건 순수(pure) OOP 언어가 아니야’라는 사람
- ‘모든 프로그램은 OOP로 만들어야 해!’라는 사람
- ‘<어쩌고>한 <누구>가 이리 말했으니 너는 틀려!’라는 사람예시 : ‘~책에 따르면’
- ‘이 방법만 따르면 문제가 해결돼!’라는 사람

진실을 전파하는 유일한 방법은 장점을 최대한 객관적으로 보여주는 것이며, 제대로 된 실무자 또는 학자라면 ‘과학적 사고방식’을 따른다.

훌륭한 프로그래머는 해결하는 문제에 적절한 도구를 사용한다. 모든 문제를 해결할수 있는 절대반지는 존재하지 않으며, 모든 해결을 미리 배워 두는 것은 불가능하다. 따라서, 문제를 발견했을 때 새로운 해법을 빠르게 찾아 습득하는 능력이 더 중요