[강좌 : 객체지향 - 6] 상속성
2009.10.01 12:31
김성용(topmentor)
http://cafe.naver.com/gisdev/611  
6. 상속성
 
 
오랜만에 다시 이어갑니다. 지금도 중요한 일을 하고 있어야 하는 데 귀차니즘 때문에 그것은 미루고 이것에 손을 대고 있네요. ^^<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><?xml:namespace prefix = o />
 
이번 시간은 상속입니다. 상속은 객체지향의 꽃이라고 할 수 있습니다. 상속이 없다면 기존의 절차지향과 다를 게 없습니다. 절차지향에도 기능이나 속성을 추상화할 방법은 존재했기 때문입니다. 기능은 함수를 통해 속성은 구조체와 같은 사용자 정의형을 통해 구현을 할 수 있었죠. 상속이 있기에 객체지향과 절차지향은 중대한 문법적 차별성을 갖게 된 겁니다. 따라서 객체지향에서는 이 상속을 이해하고 활용해야 객체지향의 묘미를 살리는 셈이 됩니다.
 
 
   가. 상속의 개념
     : 상속의 기본 개념은 상위개념의 특징을 하위개념이 물려 받는 것이라 했습니다. ‘남학생’이라는 개념은 ‘학생’이라는 상위개념의 속성을 물려 받고 있습니다. 이런 특징을 프로그래밍적으로 어떻게 지원하는 가 하면 하나의 클래스가 가지고 있는 특징(데이터와 함수)들을 그대로 다른 클래스가 물려 받도록 문법화 하였습니다. 즉, 상속이라는 관계표시만 해 두면 별다른 조치없이 클래스의 기능과 속성을 그대로 가져오게 된다는 것입니다. 이는 기존 클래스에서 새로운 기능이나 특성을 부가하는 것만으로도 새로운 클래스를 정의할 수 있게 하기 위해서 입니다.
 
좀 더 프로그래밍적 측면으로 접근해 보면 ‘상속한다’의 의미는 클래스의 멤버를 다시 정의하지 않더라도 다른 클래스의 멤버변수나 함수들을 자신의 것처럼 쓸 수 있는 것을 말하는 것입니다.
 
오호!! 오늘도 저쪽에서 질문을 날리는 군요.
“편리한 것 같기는 한데, 요즘 에디터는 Copy & Paste가 쉬워서 기존에 만들어둔 코드를 그대로 복사해서 붙이면 되는데 굳이 상속을 쓸 필요가 있나요?”
 
대단한 지적입니다. 맞습니다. 복사해서 붙이기 하면 간단히 해결될 수 있습니다. 그럼 이런 상황을 생각해 봅시다. 화면에 원을 출력하는 기능을 확장해서 동심원을 출력하는 모듈을 만든다고 생각해 봅시다. 만약 복사를 해서 원을 출력하는 로직을 가져다 동심원 출력 모듈을 완성했다면 원을 출력하는 기능을 만든 사람이 그것을 업데이트 했을 때 동심원에 적용한 원 출력 로직은 업데이트가 안 된 상태로 남아있게 됩니다. 기능을 상속받았다면 업데이트 된 로직이 그대로 적용되었을 것입니다. 유지보수의 측면에서 상속이 복사&붙이기 보다 훨씬 일관성이 있고 안전하다고 할 수 있습니다.
 
“그런 경우 복사해서 붙이지 않고 함수를 호출하는 식으로 되면 안 되나요?”
 
이런 경우 원래 모듈의 안정성을 기할 수 있을 겁니다. 그런데 자료구조나 속성은 어떻게 물려줄 까요? 상속은 데이터이든 로직이든 안전하게 하위 클래스로 물려주고 자신의 색깔도 잃지 않게 하는 장점이 있습니다.
 
이런 측면도 있습니다. A라는 사람이 Car라는 클래스를 구현하였습니다. B라는 사람이 SuperCar라는 클래스를 만들려고 합니다. 그런데 Car의 기능과 속성을 이용하면 쉽게 구현할 수 있을 것 같습니다. Car 클래스는 A의 통제하에 있는 것이라 섣불리 B가 Car를 직접 수정할 수는 없습니다. Car는 그대로 두고 자신은 SuperCar만 손댈 수 있도록 하되 Car의 속성과 기능을 가져와야 합니다. 상속은 이런 상황에서 쓸 수 있는 좋은 방법입니다. Car의 속성과 기능을 물려 받되 마음에 들지 않는 것은 오버로딩이나 오바라이딩을 통해서 재구현할 수 있기 때문입니다. 빌려쓰는 모듈을 건들지 않고 원하는 모듈의 기능을 완성한다. 좋지 않습니까?
 
 
 
   나. 상속시 객체 구조
     : 상속을 받은 하위 클래스로 만든 객체의 구조를 이해하는 것은 상속관련 문법을 이해하는 데 매우 중요한 의미를 갖습니다. 일단 하위 클래스 객체에 대한 대원칙을 말씀드리겠습니다.
 
 원칙적으로 상속을 하면 모든 멤버를 하위로 가져온다. 단, 사용할 수 있느냐 없느냐로 상속이 된다 안 된다를 판단한다.
 
이것을 그림으로 설명드리겠습니다.
 
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = v />
 
 
Car를 상속 받은 SuperCar 클래스를 가지고 인스턴스를 생성하면 위 그림과 같이 SuperCar 객체 내에 Car 객체를 포함하는 형태가 됩니다. 상속을 한다면 마치 기능과 속성단위로 하나씩 가져오는 것 같지만 실제로는 그렇지 않다는 것입니다. 상위객체를 통체로 안고 있는 것입니다. 이를 통해서 확인할 수 있는 사실 하나… 상속을 받을 때에는 필요한 멤버만 선택적으로 가져올 수는 없다는 것입니다. 도움이 되든 안 되든 모두 가져와야 하는 구조입니다.
 
이쯤에서 이런 질문을 하실 겁니다.
“접근지정자를 쓰면 필요한 것만 상속한다고 하던데요? 즉, private로 지정되는 것은 상속이 안 된다고 하던데…”
 
많은 객체지향 책에서 그렇게 설명하고 있습니다. 일부는 맞는 이야기입니다. 그런데 이 부분은 정확히 이해하셔야 합니다. 접근지정자는 접근을 제한하는 용도이지 상속을 제한하는 제한자가 아닙니다. 상속을 하면 모든 멤버를 가져오는 데 접근지정자에 의해 하위 클래스 쪽에서 접근하는 것을 차단하는 것입니다. 이런 식으로 해서 private멤버를 쓸 수 없게 되니 ‘상속이 안 된다’라고 표현을 합니다만 사실 정확한 표현은 아닙니다. 메모리상에서는 private 멤버도 엄연히 allocation되고 있습니다. 단지 쓰지 못할 뿐이죠.
 
부가적으로 설명하자면 private 멤버는 하위 클래스에서 접근이 차단됩니다. protected나 public으로 지정되어야 하위 클래스서 접근이 가능합니다.
 
그리고 C++에서는 private 상속, protected 상속, public 상속을 구분하도록 문법이 제공되지만 거의 99% public 상속을 하고 있기 때문에 거의 의미가 없다고 보시면 됩니다. 따라서 Java나 C# 같이 나중에 탄생한 객체지향 언어의 경우 상속방식을 접근제한자로 구분하는 문법이 없습니다.
 
자~ 정리해 보겠습니다.
상속의 목적은 새로운 클래스를 정의하는 데 기존의 클래스를 확장하여 정의하고 싶을 때 사용된다. 그리고 하위 클래스의 객체는 상위 클래스의 객체를 포함하는 형태를 취하며 접근지정자에 사용이 제한될 뿐이다.
 
다음 시간에는 다형성을 해야 되는 데 상속에 대해 한가지 더 이야기를 할 게 있어 그것을 다루려고합니다. 사실 객체지향이 제시하는 상속은 2가지가 있습니다. 오늘 알아본 것은 구현상속이라는 것입니다. 새로운 클래스 구현을 목적으로 하는 상속을 말합니다. 상속을 하면 상위 클래스의 기능과 속성을 물려받는다는 특징을 이용하는 것이죠.
 
그런데 한가지가 더 있습니다. Type 상속이라는 것이 있습니다. 이것은 클래스가 갖는 형태만 상속을 하는 것입니다. “‘형’만 상속을 한다.”는 것에 대해 감이 잘 안 오실 겁니다. 주는 것 없이 그저 유형만 가져온다는 게 어떤 의미를 지니고 왜 필요한지도 모르실 겁니다. 하지만 이것을 이해해야 다형성의 고비를 넘어가실 수 있습니다. 다음 시간에는 이 type 상속에 대해 알아 볼 겁니다.
 
C++에서는 엄밀히 구분하지 않지만 Java나 C#등에서는 이 두 가지 상속을 구분하는 문법을 제공하고 있습니다.
Posted by windship
[강좌 : 객체지향 - 5] 캡슐화
2009.09.04 14:30
김성용(topmentor)
http://cafe.naver.com/gisdev/543  
5. 캡슐화<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><?xml:namespace prefix = o />
 
   이번 시간은 캡슐화에 대해 알아보겠습니다. 개인적인 생각으로는 객체지향 4대 특징중에 어쩌면 가장 주목받지 못하는 특징이 아닌가 합니다. 그 이유는 캡슐화를 개념적인 측면으로만 접근하고 실제 코드로 별로 적용하지 않기 때문에 생기는 문제라고 봅니다. 캡슐화가 객체지향의 4대 특징으로 올라설 수 있었던 것은 그 만큼 개념적인 중요성이 크기 때문인데 많은 개발자들이 이것의 중요성에 대해 인식하지 못하고 있습니다. 그도 그럴 것이 많은 객체지향 프로그래밍 책에서 캡슐화를 자세히 다루지 않기 때문입니다. 그저 접근지정자 설명에 그치는 경우가 대부분이죠. 하지만 캡슐화의 특징은 접근지정자 이상의 의미를 가지고 있고 실제 코딩에서는 다양한 형태로 구현이 됩니다.
 
자! 그럼 캡슐화로 들어가 보겠습니다.
 
 
가. 캡슐화 개요
잠시 복습하는 차원에서… 객체지향 4대 특징의 개념 시간에 캡슐화를 어떻게 설명했었죠?
네~ 그렇습니다. '데이터 구조'와 '데이터를 다루는 방법'를 결합시켜 묶는 것을 말합니다. 질환을 치료하는 데 필요한 몇몇 약들이 적정한 비율로 섞여 하나의 캡슐에 들어있는 알약을 예로 들어 설명했습니다. 그러면서 특정 객체가 독립적으로 역할을 제대로 수행하기 위해 필요한 데이터와 기능을 하나로 묶어 관리하는 것을 캡슐화라고 한다고 정리했었습니다.
거기에 데이터는 은닉하고 그 데이터를 접근하는 기능(함수)를 밖으로 노출하는 것도 캡슐화라고 했습니다. 데이터를 기능으로 보호하여 데이터의 입출력이 기능을 통해 통제되도록 설계하는 것을 말하는 것이었죠.
 
지금까지의 내용을 정리해 보면 캡슐화는 두가지 측면이 있습니다.
  1) class안에 관련된 변수와 메소드를 묶어 넣는 것.
  2) 정보은닉
     : 객체는 자신이 수행하는 모든 행동의 과정이나 속성을 외부로 보이지 않게 합니다.
       즉, 외부에서는 사용하는 메소드의 로직이나 멤버변수들에 대해서는 알 필요가 없다
       는 것입니다.
 
 
나. 캡슐화의 구현
캡슐화를 구현하기 위해 각 객체지향언어들은 접근지정자라는 것을 제공합니다. 클래스의 멤버에 접근할 수 있는 권한을 통제하여 적절히 보안정책을 취할 수 있게 하는 것입니다. 대표적인 접근지정자는 다음의 3가지 입니다.
 
   . private   : 클래스 내부 (멤버함수)에서만 접근가능
      . protected : 클래스 내부 + 하위 클래스의 멤버함수에서 접근 가능
      . public    : 클래스 내부 + 하위 클래스의 멤버함수 + 외부 함수에서 접근 가능
 
class 클래스 이름
{
public :
        데이터형 멤버변수1;
        데이터형 멤버변수2;
리턴형 함수1 ( 매개변수 );
private:
데이터형 멤버변수3;
        데이터형 멤버변수4;
리턴형 함수2 ( 매개변수 );
};
 
 
위 예에서 멤버변수1, 멤버변수2, 함수1은 pulic 접근지정이 됩니다. 그럼 대충 눈치로 보면 멤버변수3, 멤버변수4, 함수2는 private 지정이 되겠구나라는 짐작이 가시죠? 클래스 내부에 인스턴스가 관련 기능을 온전히 하기 위해 필요한 데이터와 함수를 한묶음으로 가지고 있다면 이것은 캡슐화가 잘 된 것입니다. 캡슐화가 잘 된 클래스는 외부에 의존하는 정도가 줄어들겠죠.
 
두번째 캡슐화 정의를 구현하는 방법은 다음과 같습니다. 모든 멤버변수는 private로 접근지정을 해서 외부의 직접접근을 문법적으로 차단 시키고 멤버 변수 데이터를 수정하거나 데이터 값을 알아내기 위한 별도의 멤버 함수를 제공하는 것입니다. 이렇게 멤버변수를 수정하거나 값을 열람하는 접근함수를 Getter(accessor)/Setter(mutator)라고 합니다.
 
아래 예를 잠깐 살펴 보겠습니다.
 
class Car
{
private :
        int speed;
 
public:
void setSpeed(int n) {  speed = n; }
int getSpeed() {  return speed; }
 
};
 
int main()
{
   Car mycar;
   mycar.setSpeed(100);
   cout << mycar.getSpeed() ;
}
 
 
예제를 보면 speed라는 멤버변수는 private로 묶어 두었기 때문에 main함수에서는 직접 접근할 수 없습니다. 대신 이 멤버에 접근하기 위한 메소드를 제공하고 있는 것을 알 수 있습니다. speed에 데이터를 입력하기 위해 setSpeed()를 제공하고 speed 값을 얻어내기 위해 getSpeed()를 제공하고 있습니다. 그래서 main함수에서도 이들 함수를 호출하여 간접적으로 speed 멤버를 쓰고 있습니다. 함수를 통한 데이터의 접근, 이것이 바로 캡슐화인 것입니다.
 
 
아! 저기서 누가 손들고 계시는군요.
‘speed를 public로 해 두면 굳이 메소드를 만들지 않고 편하게 접근해서 쓸 텐데 이런 번거로운 것을 해야 하나요?’
 
네~!! 맞습니다. 그렇게 쓰면 편하죠. 그런데 이런 측면을 생각해 볼까요? 멤버변수중에 외부에서 값은 열람은 하되 수정은 하지 못하게 하고 싶다면 어떻게 해야 할까요? 멤버변수를 public로 그냥 노출하면 외부에서 수정하는 것을 원천적으로 차단할 수 없겠죠? Getter와 Setter를 선택적으로 두면 그 멤버변수는 읽기전용 혹은 쓰기전용식으로 데이터에 대한 접근권한을 더 세분화 할 수 있습니다.
 
또한 위 예제의 로직을 잘 보세요? speed멤버변수는 음수값이 들어오면 안 됩니다. 마이너스 속도란게 있을 수 없잖습니까? 만약 speed가 노출되어 있다면
speed = -100;
식으로 음수가 입력되는 것을 막을 수 없습니다. 하지만 메소드를 통해 간접적으로 접근하게 하면 이런 입력값의 유효성을 체크할 장치를 둘 수 있습니다. setSpeed()에서 두면 되겠죠.
 
void setSpeed(int n) {
if(n>=0)
  speed = n;
else
  speed = 0;
}
 
위와 같이 해 두면 아무리 main함수에서 ‘mycar.setSpeed(-2000);’ 한다 한들 speed에는 음수값이 입력되지 않습니다. 자~ 그럼 정리해 봅시다. 멤버변수를 멤버함수로 캡슐화하는 이유는
 
     1) 데이터에 대한 읽기 쓰기 권한 구분
     2) 입력데이터의 유효성 검증 부분을 로직에 포함 시킬 수 있음.
 
입니다. 정리가 되셨죠?  실제 COM과 같은 컴포넌트 프로그래밍에서는 외부에서 접근할 필요가 있는 멤버변수에 대해 Getter와 Setter를 반드시 두도록 되어있습니다.
 
 
 
다. 클래스 설계상의 캡슐화
세번째 캡슐화에 대해 설명 드리겠습니다. 이것을 객체지향 프로그래밍 책에는 소개되어 있지 않지만 실제 프로그래밍에서는 많이 활용되고 있는 기법입니다. 이것은 설계적인 측면이 있어서 이해하는 데 좀 어려울 수도 있습니다. 따라서 지금 이해가 안 되더라도 양심의 가책(?) 느끼지 마시고 넘어가셔도 됩니다. 다형성을 이해한 다음에 보시면 됩니다.
 
세번째 캡슐화는 선언만 노출하고 구현은 숨기는 것입니다. 잘 이해가 안 되시죠? 이와 비슷한 기법을 쓴 것이 바로 라이브러리입니다. C나 C++라이브러리를 이용할 때 보면 코딩시에 추가(include)하는 것은 라이브러리의 헤더입니다. 헤더에 드러난 함수나 클래스 선언을 보고 자신이 작성한 코드에서 라이브러리 함수를 호출합니다. 마치 자신이 작성한 함수처럼 말이죠. 그럼 그 라이브러리 함수의 실제 구현부분은 어디에 있는 것일까요? Lib 파일에 네이티브 코드형태로 있다가 link시에 이들 코드가 삽입되는 것입니다. 이것도 캡슐화입니다. 세부적인 구현은 숨기고 외부에는 사용할 수 있는 최소의 정보만 노출하는 것이면 모두 캡슐화입니다.
 
객체지향 설계에 있어서 캡슐화는 클래스의 선언만 담는 순수추상클래스를 전면에 내세워 외부에서는 이것을 사용하게 하고 순수추상클래스를 상속받는 클래스를 만들어 여기에 실질적인 구현을 하는 것입니다. 구조로 보면 아래와 같습니다.
 
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = v />
 
 
 
위 그림에서 ImageSource라는 추상클래스는 구현부가 없습니다. 그냥 멤버함수의 선언만 들어있습니다. 이것이 인터페이스 역할을 하는 것입니다. 그 멤버함수의 구현은 하위 클래스인 LocalImageSource나 RemoteImageSource에 있습니다.따라서 외부에서는 ImageSource라는 추상클래스를 활용하고 실제 기능의 수행은 하위클래스인 LocalImageSource나 RemoteImageSource에서 이루어집니다. 이렇게 되면 클래스를 사용하는 측에서는 세부구현을 신경쓸 필요없이 ImageSource가 노출하는 인터페이스만 보면 되는 겁니다.
 
이렇게 함으로 해서 클래스 사용하는 쪽이 클래스의 실제 구현부를 건드려 클래스 개발에 대한 일관성을 잃게 되는 위험을 피할 수 있습니다. 클래스 구현의 버전관리에도 강점이 있죠. 아무튼 이 기법은 클래스 설계상 구현할 수 있는 캡슐화입니다. 자바를 좀 하신 분은 JDBC가 이런 구조를 가지고 있다는 것을 아실 겁니다. 세번째 기법은 나중에 다형성이 끝난 후 디자인 패턴을 이야기 할 때 자세한 코드를 예로 들어 설명하겠습니다.
 
정리하죠. 캡슐화는 실질적인 것은 숨기고 접근할 방법만 노출하는 것을 의미한다. 요즘에는 관련된 것을 묶는 다는 의미는 많이 퇴색되었습니다.
Posted by windship
[강좌 : 객체지향 - 4] 추상화
2009.08.10 17:00
김성용(topmentor)
http://cafe.naver.com/gisdev/475  
4. 추상화
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><?xml:namespace prefix = o /><?xml:namespace prefix = o /><?xml:namespace prefix = o /> 
   가. 개 요
지난 시간에 설명한 대로 추상화라고 하는 것은 객체들의 공통적인 특징(속성과 기능)을 뽑아내는 것입니다. 구현하는 객체들이 가진 공통적인 데이터와 기능을 도출해 내는 것을 의미한다고 강조했습니다.
 
그리고 데이터의 추상화와 기능의 추상화를 설명하면서 추상화라고 하는 것에는 항상 새로운 이름이 붙는다는 공통점이 있고 프로그래밍 입장에서 추상화라고 하는 것은 ‘공통의 속성이나 기능을 묶어 이름을 붙이는 것’으로 정리하였습니다. 기억이 나시나요?
 
이번 시간에는 객체지향 프로그래밍 입장에서 추상화를 다루어 보도록 하겠습니다. 간단합니다. 클래스를 정의하는 과정이 바로 추상화입니다.
 
여기서 잠깐 복습하나 해 보죠? 클래스가 왜 필요하죠? …
네. 우리가 프로그램 상에서 사용할 실체는 객체인데 이 객체를 만들기 위해서는 틀이 필요합니다. 좀 시스템 적으로 들어가면 객체를 활용하려면 메모리상의 자원으로 적재되어야 하는 데 언어가 기본적으로 제공하는 type이 아니면 메모리에 적재할 수 없습니다. 즉, 정의하지 않았거나 미리 약속되지 않은 것은 메모리에 적재할 수 없다는 것입니다. 따라서 이미 약속된 것이 아니라면 하나의 type으로 정의해야 한다는 것입니다. 예를 들어 언어가 기본적으로 제공하지 않는 기능은 함수라는 것을 만들어야 쓸 수 있습니다. (실행시에는 함수도 메모리에 적재됩니다.) 그리고 언어가 제공하지 않은 새로운 데이터형은 구조체나 typedef등의 방법으로 새로운 type을 만든 후 그 type에 대한 변수를 생성할 수 있습니다. (변수 생성은 메모리상에 변수 영역이 할당됨을 의미합니다.)
 
객체도 마찬가지 입니다. 객체가 가진 속성데이터와 기능을 정의하지 않고는 메모리에 올릴 수 없습니다. 그 객체 생성을 위한 type이 바로 클래스입니다. 그래서 객체가 중심이 되는 객체지향 프로그래밍에서는 클래스가 핵심이 될 수 밖에 없습니다.
 
 
 
   나. 추상화 하는 방법
     1) 클래스 정의
클래스를 정의하는 방법부터 살펴 볼까요? 객체지향 프로그래밍 개요에서 객체지향 프로그래밍은 프로그램을 위해 활동할 객체를 정의하고 이들간에 인터페이스를 정의한다고 했습니다. 그 기억을 떠올리면서 클래스를 정의하는 단계를 보시기 바랍니다. 아래와 같습니다.
 
    첫번째 단계, 해결하려는 구축하려는 시스템 혹은 문제에 대한 것을 자연어로 기술한다. (문제기술)
           가급적 자세히 기술하는 것이 좋다.
    두번째 단계, 문제 기술로 부터 명사들을 뽑아낸다.
    세번째 단계, 명사들중에서 객체가 될 수 있는 명사와 객체가 지니는 속성이 되는 명사를 구분해 낸다.  
           속성 데이터에 대한 추상화라고 할 수 있음.
    네번째 단계, 문제 기술에서 동사에 주목해서 객체의 기능이 될 수 있는 부분을 추출해 낸다.
        이 부분이 바로 객체의 기능을 추상화하는 것임. 만약 기능을 추가 과정에서 필요한 데이터가 있으면
        멤버 변수로 추가할 수 있다.
        (이것을 설계멤버라고 합니다. 추상화에 의해 얻어진 속성 데이터와 구분하기 위한 것입니다.)
    다섯째 단계, 추상화된 데이터(속성)과 기능을 하나의 형(Type)으로 정의한다. (클래스로 정의)
 

 
    <?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = v /><?xml:namespace prefix = v /><?xml:namespace prefix = v />
위 그림을 보면 문제기술로부터 객체 후보를 뽑아내고 이들의 공통적인 특징을 추상화하고 있습니다. 공통의 속성 (이름, 성별, 나이, 고향)과 공통의 기능(패를 낸다, 패를 뒤집는다, 광을 팔고 쉰다, 패를 계산한다)을 도출하여 ‘GIS과정학생’이라는 클래스를 정의하고 있습니다.
 
추상화를 통해 클래스를 정의할 때 몇가지 고려할 사항이 있습니다. 첫째, 도출한 객체 후보(명사들)들을 클래스로 만들 것인가? 아니면 속성데이터로 넣을 것인가?를 결정해야 합니다. 단순히 변수하나로 처리하면 될 것을 일부러 클래스로 만들어 복잡하게 처리할 필요가 없습니다.
 
둘째, 구현에 필요한 속성인가?를 결정해야 합니다. 구현에 필요하지도 않은 속성을 열심히 끌어 붙이는 것은 메모리 낭비일 뿐만 아니라 코드만 복잡해집니다. 위 그림의 예를 보면 ‘이름’이라는 공통의 속성이 있지만 이것이 프로그램 수행에 아무 역할도 못한다면 과감히 배제하는 것이 낫습니다. 여기에는 일정한 답이 존재하지 않습니다. 추가, 배제에 대한 판단은 구현하려는 시스템이나 서비스에 초점을 두어 판단하면 됩니다.
         
 

    2) 인스턴스화 : 정의된 클래스로 부터 객체를 생성해 내는 것.
인스턴스는 만들어진 클래스로부터 생성된 객체입니다. 인스턴스란 원래 어떤 틀로부터 찍어낸 메모리상의 실체를 통칭해서 말합니다. (윈도우 프로그래밍에서도 인스턴스란 용어가 나옵니다.) 좀 어렵나요? 
int a;
라는 코드에서 a는 int 타입의 인스턴스라고 볼 수 있습니다. 따라서 인스턴스는 클래스 타입의 변수로 생각하면 될 것 같습니다.
 
          
 
위 그림을 보면 ‘GIS과정학생’이라는 클래스로 이세돌, 한도리, 김만수라는 객체를 만들고 있습니다. 바로 이들이 인스턴스입니다.
 
  

다. 클래스의 정의
 이 부분은 간단한 문법만 살펴보고 넘어가겠습니다. 원래 C++강좌가 아니라 객체지향 강좌이기 때문에 여기서 길게 설명을 이어가는 것은 낭비라는 판단입니다.
 
     1) 클래스 선언 및 정의 문법 (C++기준)
        - 형태
        class 클래스이름 {
          (멤버접근지정) :
            멤버 변수 선언;
           멤버 함수 선언;
        }
        리턴형 클래스이름::멤버함수명(인자..)
        {
         // 구현 부분            
        }
 
         ex) class Point {
              private :
                  int xPosition;
                  int yPosition;
              public:
                  void move(int x, int y);
          }
 
          void Point::move(int x, int y)
          {
                xPosition += x;
                yPosition += y;
           }
 
         * 대개 클래스 정의 부분은 헤더 파일(.h) 에, 멤버함수에 대한 구현 부분은
         .cpp파일에  하는 것이 일반적이다
 
 
     2) 멤버변수와 멤버 함수 정의
         클래스 내부에 속해있는 데이터와 함수를 멤버라고 합니다. 이 멤버에는 2종류가 있습니다.
         첫째, 추상화 멤버 가 있는 데 이것은 추상화를 통해 얻어진 멤버를 일컫습니다.
         둘째, 설계 멤버 는 클래스와 의미상 관계는 없으나 프로그램 개발의 필요에 의해
            (특히 함수 구현에 있어 필요한 경우) 개발자가 임의로 만든 멤버를 말합니다.

         ‘멤버’를 지칭하는 용어가 여러가지 있는 데 언어에 따라 조금씩 다른 용어가 쓰이고 있으니 참조하기 바랍니다.
 
일반정의
Data(변수)
Procedure(함수)
학술적정의
State
Behavior
VB, Smalltalk,
Object Pascal
Attribute
Method
C++
Member 변수
Member 함수
Java
Field
Method
        
    
   3) 멤버들의 특징
      멤버들의 사용에 앞서 한 가지 정확하기 인지할 것이 있습니다. 객체의 사용대상은 객체 자체라기 보다는 객체가 가진 멤버라는 것입니다. 즉, 객체단위의 연산이나 조작은 별로 없습니다. 대부분 객체의 멤버를 대상으로 데이터를 입출력하고 함수를 호출합니다. 일반적으로 멤버에 대한 접근은 아래와 같은 문법을 따릅니다.
 
    객체이름.멤버
    ex) MyCar.speed = 1;
       MyCar.speedUp();
 
다음은 멤버함수와 멤버변수의 특징입니다.
 
      - 멤버 함수
         . 멤버변수는 모든 멤버함수를 통해 공유된다.
         . 멤버변수를 아무 제약없이 멤버 함수에서 사용할 수 있다.
 
      - 멤버변수
         . 객체를 생성해야 사용가능.
         cf. 멤버변수 선언과 동시에 초기화 하는 것은 C++에서는 문법적 오류로 본다.
          => 콜론 초기화를 이용하거나 생성자에서 초기화 한다.
          class MyClass
          {
              int a=10;               // 에러
          };
        
 
 
4) 인스턴스 생성
인스턴스를 생성하는 방법은 크게 2가지가 있습니다. 정적인 방법으로 생성하는 것과 동적인 방법을 생성하는 것이 있는 데 이것은 C++에서만 그렇고 요즘 대표적인 객체지향 언어인 자바나 C#의 경우는 동적인 방법으로만 객체를 생성할 수 있습니다.(이 방식이 더 객체지향적이라고 봅니다.) 일단 아래 설명은 C++을 기준으로 합니다.
 
         가) 정적할당 방법으로 객체 생성
          1- 클래스 객체 생성 (인스턴스)
              ex) Car myCar;
          2- 객체 사용
             : 구조체와 마찬가지로 멤버접근 지정자(.)를 사용한다.
              ex) myCar.velocity = 10;        // 멤버변수
                myCar.speedDown();    // 멤버함수
          - 정적 할당된 객체는 Stack에 저장영역이 만들어 집니다. 그런데 Stack에 만들어진 객체들의
           멤버 변수들을 자동 초기화 되지 않으므로 생성자에서 꼭 초기화 해 주어야 합니다.
 
         나) 동적할당 방법으로 객체 생성
           1- 클래스 객체에 대한 포인터 변수 정의 
              ex) Car *myCar;
           2- 클래스 객체 생성 (인스턴스)
              ex) myCar = new Car;
           3- 객체 사용
              : 포인터에 의한 멤버 접근 연산자(->) 사용
              ex) myCar->velocity = 10;       // 멤버 변수
                 myCar->speedDown(); // 멤버 함수
           4- 객체 사용이 끝나면 동적 할당한 객체를 해제 해야 한다.
              ex) delete myCar;
            - 동적 할당된 객체는 Heap에 만들어 지므로 프로그램이 끝날 때까지 메모리 영역이 남아있
             게 됩니다. 따라서 객체 사용이 끝나면 필히 delete 시켜 주어 메모리에서 해제를 해주어야
             합니다. 자바나 C#의 경우는 가비지 컬렉션을 통해 생성한 객체를 자동으로 해제 시켜 줍니
             다.
Posted by windship
[강좌 : 객체지향 - 3] 객체지향 프로그래밍의 4대 특징
2009.07.31 13:39
김성용(topmentor)
http://cafe.naver.com/gisdev/461  
3. 객체지향 프로그래밍의 4대 특징<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><?xml:namespace prefix = o />
 
내가 객체지향을 공부했어!
객체지향 프로그래밍엔 빠삭해!
XXX 객체지향 언어에 대해서는 모르는 게 없다!
 
이렇게 말할 수 있으려면 객체지향의 4대 특징을 이야기 할 수 있어야 하고 그 객체지향 언어가 어떤 문법을 통해 4대 특징을 지원하는 지 열거할 수 있어야 합니다. 그 만큼 객체지향 프로그래밍의 4대 특징은 객체지향의 핵심중의 핵심입니다.
 
객체지향 프로그래밍의 첫번째 특징은 추상화 (abstraction)입니다. 추상화라고 하는 것은 객체들의 공통적인 특징(속성과 기능)을 뽑아내는 것입니다. 즉, 우리가 구현하는 객체들이 가진 공통적인 데이터와 기능을 도출해 내는 것을 의미합니다.
 
그럼 추상화가 객체지향만의 특징이냐? 그렇지 않습니다. 추상화라고 하는 것은 절차지향 프로그래밍에서도 있어왔습니다. 대표적인 것이 구조체와 같은 사용자 데이터 형입니다. 이것은 데이터를 추상화해서 하나의 새로운 데이터 유형을 만드는 것입니다. 예를 들면 국어, 영어, 수학 점수를 모아 하나의 데이터 형으로 만든다면 아래와 같이 정의할 겁니다.
 
struct Sungjuk
{
  int kor_score;
  int eng_score;
  int math_score;
};
 
Sungjuk이라는 새로운 이름으로 데이터형을 정의하는 데 그 부속데이터로 kor_score, eng_score, math_score를 두고 있습니다. 성적이라는 데이터를 추상화를 통해 정의한 것입니다.
기능의 추상화도 있습니다. 함수가 바로 그것인데, 잘 쓰는 기능을 이름을 붙여 정의하였으니 기능을 추상화 한 것이죠. 여기서 데이터의 추상화와 기능의 추상화에서 알 수 있는 하나의 사실이 있습니다. 추상화라고 하는 것에는 항상 새로운 이름이 붙는다는 점입니다. 따라서 프로그래밍 입장에서 추상화라고 하는 것은 이렇게 정리해 볼 수 있습니다.
 
‘공통의 속성이나 기능을 묶어 이름을 붙이는 것’
 
객체지향 프로그래밍에서 추상화는 그럼 무엇일까요? …
네 생각하는 대로 입니다. 클래스를 정의하는 과정이 바로 추상화라고 할 수 있습니다. 추상화관련 문법은 다음 장에서 다루기로 하고 일단 여기서 추상화 설명을 마치겠습니다.
 
 
두번째 특징은 바로 캡슐화(encapsulation)입니다. 객체지향에서 캡슐화는 데이터 구조'와 `데이터를 다루는 방법'를 결합시켜 묶는 것을 말합니다. 캡슐형태로 된 알약을 떠 올리시면 됩니다. 캡슐형 알약에는 질환을 치료하는 데 필요한 다른 종류의 약이 적정한 비율로 섞여있는 것을 볼 수 있습니다. 해당 질환을 치료하기 위한 목적으로 하나가 아닌 몇 가지 기능의 약을 하나의 캡슐안에 담은 겁니다.
객체지향에서 캡슐화도 마찬가지 입니다. 특정 객체가 독립적으로 역할을 제대로 수행하기 위해 필요한 데이터와 기능을 하나로 묶어 관리합니다. 객체가 맡은 역할을 수행하기 위한 하나의 목적을 위해 데이터와 기능들을 묶는 것이죠.
 
그런데 캡슐화라는 특징은 다른 의미로도 쓰입니다. 즉, 데이터는 은닉하고 그 데이터를 접근하는 기능(함수)를 밖으로 노출한다는 의미를 나타낼 때 캡슐화라는 용어를 씁니다. 데이터를 기능이라는 캡슐로 보호한다는 것이죠. 
 
 
 

위 그림처럼 데이터를 기능으로 보호하여 데이터의 입출력이 기능을 통해 통제되도록 설계하는 것을 말합니다. 역시 자세한 것은 뒤에 설명될 겁니다.
 
 
세번째 특징은 상속성(inheritance)입니다. 객체지향의 꽃입니다. 상속이 없으면 객체지향은 절차지향과 큰 차이가 나지 않습니다. 객체지향 문법이 어렵고 복잡해 질 이유도 없죠. 상속이란 특징을 가지면서 객체지향 언어가 절차지향 언어에 비해 문법의 규모가 2배이상 늘어났습니다.
 
상속이란 상위개념의 특징을 하위 개념이 물려받는 특징을 말합니다. 예를들어 ‘남학생’이라는 단어에는 ‘학생’이라는 단어의 특징을 물려받고 있습니다. 개념적 특징이 상속되는 것이죠. ‘학생’이 갖는 특징을 그대로 계승하면서 ‘남학생’만 갖는 특징을 부가하여 ‘남학생’의 전체 특징이 형성됩니다. 이 개념을 프로그래밍에 도입한 것인데 하나의 클래스가 가지고 있는 특징(데이터와 함수)들을 그대로 다른 클래스가 물려주고자 할 때 상속성의 특징을 사용합니다.
 
 
네번째 특징은 다형성(polymorphism)인데 객체지향 개념 중 가장 까다롭고 4대 특징중에 가장 이해하기 어려운 특징입니다. 알았다고 해도 코딩으로 잘 활용이 안 되는 특징이기도 하죠. 이것을 잘 이해하고 활용한다면 객체지향 언어를 제대로 쓰는 것으로 봐도 무방할 정도입니다.
 
다형성의 의미는 약간 다른 방법으로 일을 하는 함수를 동일한 이름으로 호출해 주는 것을 말합니다. 이해가 잘 안 되죠?  예를 들어 보겠습니다. 홍길동이란 이름의 학생과 김철수라는 학생이 있다고 가정해 봅시다. 그런데 선생님이 홍길동을 바라 보면서 ‘학생! 칠판 지워’라고 명령을 했다고 합시다. 홍길동은 나름의 방법으로 칠판을 지울 겁니다. 다시 선생님이 김철수를 바라보면서 ‘학생! 칠판 지워!’라고 명령했을 때 김철수도 자신만의 방법으로 칠판을 지울 겁니다. 그런데 홍길동이 지웠던 방식과는 다르겠죠? ‘학생! 칠판 지워.’라는 표현은 같지만 칠판을 지우는 행위는 다르게 나타나고 있습니다. 이것이 바로 다형성입니다. ‘학생! 칠판 지워.’라는 명령이 다양한 결과로 나타나기 때문에 이것을 다형성이라고 하는 것입니다.
 
프로그래밍 입장에서 다형성을 해석해 본다면 명령의 해석을 연결된 객체에 의존하는 것으로 정의할 수 있습니다. 이것도 나중에 자세히 코딩을 통해 설명할 것입니다.
 
 
이번 시간은 객체지향 프로그래밍 4대 특징의 정의 정도만 이해하시면 되겠습니다. 추상화를 이용한 프로그래밍 문법은 다음 시간에 하도록 하죠.
Posted by windship
[강좌 : 객체지향 - 2] 객체지향 프로그래밍이란?
2009.07.30 14:06
김성용(topmentor)
http://cafe.naver.com/gisdev/453  
2. 객체지향 프로그래밍 이란?
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><?xml:namespace prefix = o /><?xml:namespace prefix = o /> 
      객체지향 프로그래밍을 설명하기에 앞서 자주 사용되는 몇 가지 개념을 먼저 살펴보도록 하겠습니다. 객체지향에서 핵심은 객체입니다. 객체는 무엇일까요? 객체는 우리가 구현하려는 대상입니다. 현실세계를 객체지향으로 모델링 하면 고객의 문제를 해결하기 위해 특정한 역할을 수행할 객체들이 도출됩니다. (클래스를 만들어 낸다고도 하는 데 비슷한 것 같지만 미묘한 차이가 있습니다.) 비유하자면 은행의 입출금 서비스를 설계한다고 할 때 이 서비스에 어떤 역할이 필요한지 먼저 생각하게 될 것입니다. 고객을 맞이하여 입출금을 받는 출납계원, 금고를 관리하는 사람, 업무에 필요한 문서를 준비하고 출납계원에게 배부하는 사람, 고객에게 은행서비스를 안내해 줄 안내원, 은행이란 공간의 전체적으로 경비하는 경비원 등을 떠올리게 됩니다. 이들이 구현하려는 대상인 객체인 것입니다.
 
   그렇다면 클래스(Class)는 무엇일까요? 객체로 다시 돌아가서…  객체라는 것을 프로그램 코드로 구현하려면 어떻게 해야 할 까요? 객체가 가지고 있는 속성데이터를 관리해야 하고 그 객체가 갖는 고유의 기능을 구현해야 합니다. 속성데이터는 변수나 배열 같은 것으로 구현하면 될 테고, 기능은 함수로 구현하면 되겠죠. 그런데 객체가 가진 속성과 기능을 각 객체마다 관리하려면 복잡해 집니다. 물론 헝가리언 코드와 같은 네이밍 규칙을 주면 어느 정도 관리해 볼 수 있겠지만 동적할당과 같은 방식으로 객체를 만들면 네이밍 할 수도 없고 짜증납니다. 따라서 같은 목적의 속성데이터와 기능을 한 단위로 묶어주어야 편리하게 관리 할 수 있습니다. 그래서 객체지향 언어에서는 기능과 속성을 한 단위로 묶어 하나의 Type으로 정의할 수 있게 해 놓았습니다. 그것이 바로 클래스입니다. 한마디로 클래스는 객체를 만드는 틀이라고 보시면 됩니다.
 
   여기에서 한가지 질문을 날리 실 겁니다. 객체가 구현하려는 대상이라고 하는 데 클래스로 생성한 변수 (아래 코드 참조)
        Car mycar;
도 객체라고 하지 않나요? 맞습니다. 이것도 객체라고 부르고 있습니다. 그런데 이 객체는 앞서 설명한 구현 대상으로써의 객체와 구분하기 위해 ‘인스턴스(Instance)’라는 말로 부르기도 합니다. 인스턴스는 클래스가 만들어져 있어야 생성할 수 있는 객체인 셈입니다.
 
이제 프로그래밍 입장에서의 객체지향을 이야기 해 보도록 하죠. 앞 시간에 객체지향 프로그램은 객체와 객체의 연결이라고 말씀 드렸습니다. 그런데 객체의 생성을 위해서는 클래스를 정의해야 합니다. 따라서 객체지향 프로그램의 시작은 클래스 정의부터 이루어집니다. 즉, 객체의 틀(type)로써 클래스를 만드는 데 객체의 속성정보를 저장하기 위한 데이터들과 기능구현을 위한 함수들을 한 단위 묶어정의 하는 것입니다. 따라서 객체지향 프로그래밍 방법은 아래의 순서로 이루어 집니다.
 
      객체지향 프로그래밍 방법 (클래스정의 + 주로직 구성)
        가) 문제영역으로부터 객체들을 도출해 낸다.
        나) 도출 해 낸 각 객체들의 필요한 역할을 정의해 본다.
        다) 유사한 객체들을 모아 형(Type)을 정의한다. :  클래스 생성.
            - 속성정보는 변수나 배열로
            - 기능은 함수로 정의 된다.
        라) 클래스로부터 각 객체에 해당하는 인스턴스를 만들고 주요 흐름에 맞게 인스턴스들의
         기능을 수행시킨다.
        마) 각 객체간에도 호출이 필요하면 객체가 노출하는 인터페이스를 통해 서로 데이터를 주
         고 받으며 통신한다.
 
위에서 설명하지 않은 부분은 바로 ‘주로직(main logic)’입니다. 주로직은 프로그램의 실질적인 실행흐름이 있는 곳입니다. 일반적인 애플리케이션에서는 main()함수가 주로직입니다. GUI 프로그램의 경우는 이벤트 핸들러 함수에 주요로직을 둡니다. C++이 객체지향 언어이긴 하지만 주로직에 해당하는 부분은 특정 클래스의 어느 함수가 아닌 entry point function으로 약속된 main함수입니다.
 
(사실 C++은 완전한 객체지향 언어를 표방하지 않습니다. 비얀 스트러스트럽도 C++을 절차지향과 객체지향의 장점을 모두 포괄하는 유연한 언어로 이야기 하고 있습니다. 객체지향 언어에 머물러 있기를 바라지 않는 듯합니다. )
주로직에서는 주요 실행로직이 들어가는 데 여기에서 인스턴스들이 생성되고 각 인스턴스의 멤버들을 이용하여 전체실행 로직이 만들어 집니다.
 
그럼 간단한 프로그램 예제를 통해 절차지향 코드와 객체지향 코드를 비교해 보겠습니다.
// 절차지향 코드
 
#include <iostream.h>
 
void startup(int *sp)
{
    *sp = 0;
    cout << "차량 출발" << endl;
}
 
void speedup(int *sp)
{
    (*sp)++;
}
 
void stop(int *sp)
{
    *sp = 0;
    cout << "차량이 멈추었습니다" << endl;
}
 
int car2_speed ;
 
void startup2()
{
    car2_speed  = 0;
    cout << "차량 출발" << endl;
}
 
int main()
{
    int car1_speed ;
    startup(&car1_speed);
    speedup(&car1_speed);
    cout << "현재 속도는 " << car1_speed;
    stop(&car1_speed);
 
    startup2();
    speedup(&car2_speed);
    cout << "현재 속도는 " << car2_speed;
    stop(&car2_speed);
   
    return 0;
}
 
절차지향 코드는 함수중심입니다. 함수를 정의하고 각 함수를 호출관계로 엮어가는 방식입니다. 2개의 자동차를 모델링하고 있는 데 어떤 자동차 인스턴스에 명령을 내리는 지 꼼꼼히 해석해 보지 않으면 잘 알 수 없습니다.
 
이번에는 객체지향 코드를 볼까요?
// 객체지향 코드
 
#include <iostream.h>
 
class Car
{
public :
    int speed;
    void startup()
    {
      speed = 0;
      cout << "차량 출발" << endl;
    }
 
    void speedup()
    {
      speed++;   
    }
    void stop()
    {
      speed = 0;
      cout << "차량이 멈추었습니다" << endl;
    }
};
 
 
int main()
{
    Car car1;
   car1.startup();
   car1.speedup();
   cout << "현재 속도는 " << car1.speed << endl;;
   car1.stop();
 
   Car car2;
   car2.startup();
   car2.speedup();
   cout << "현재 속도는 " << car2.speed << endl;;
   car2.stop();
   
    return 0;
}
 
main함수를 보시면 car1, car2에 대한 인스턴스를 생성하고 각 인스턴스의 멤버를 접근하는 방식으로 코딩되어 있음을 확인할 수 있습니다. 마치 누구에게 명령을 내리는 것 같지 않습니까?
 
car1.speedUp();
 
코드는 car1에게 speedup()을 하라는 명령을 내리는 것 같이 보입니다. 아주 직관적인 코딩이죠. 확실한 대상을 먼저 지정하고 그 대상이 가진 속성이나 기능을 쓰게 한다. 바로 이것이 객체지향 코딩의 특징입니다.
 
이제 객체지향 프로그램의 코딩스타일이 이해되시나요? 아직 잘 모르겠다면 앞으로 계속 경험해 보세요. 슬슬 익숙해 질 겁니다.
 
다음 강좌에서는 객체지향의 4대 특징인 추상화를 알아보겠습니다.
Posted by windship

[강좌 : 객체지향 - 1] 객체지향에 대해
2009.07.28 15:04
김성용(topmentor)

http://cafe.naver.com/gisdev/450  

I. 객체 지향의 개요

 1. 객체지향에 대해
   가) 모델링(Modeling)
    모델링이란 모델을 만드는 일입니다. 너무 뻔한 답인가요? 한마디로 모델링은 현실세계에 존재하는 문제나 현상을 특정한
  관점에서 해석하여 어떤 결과물을 설계하거나 구현 하는 것을 의미합니다. 객체지향을 두고 갑자기 왠 모델링이야기인가 
  싶겠지만 객체지향은 소프트웨어를 모델링하는 한 방법입니다. 
  따라서 모델링을 이해하는 것은 우리가 객체지향을 왜 선택하고 있는지에 대한 답을 알 수 있는 것입니다.
 
     모델링의 대상은 현실세계에서 우리가 느낄 수 있는 것이라면 무엇이든 해당합니다. 단, 구현하려는 대상이어야 겠지요.
   모델링은 접근관점과 목적에 따라 다른 결과를 보여 주는 데 예를 들면 시나리오 작가가 은행을 모델링한다면 어떻게
   접근할 까요? 아마 드라마의 배경이 되는 은행을 구상할 것입니다. 경비업체 입장에서는 은행을 어떻게 바라 볼 까요?
   그들에게 있어서 은행은 외부의 침입으로 부터 방어해야 할 하나의 대상이 될 것입니다. 구현하려는 대상은 같지만 바라보는
   시점과 목적에 따라 그 관심과 결과물이 달라지는 것입니다. 따라서 모델링의 산물인 모델도 다르겠죠.
 
    전산쟁이 관점에서 모델링은 무엇일까요? 소프트웨어나 시스템으로 구현하는 대상으로 현실을 바라보겠죠. 위의 은행의 예를
    전산쟁이에게 적용해 본다면 그가 DB 설계자라고 가정할 때 그 사람이 만들어내는 모델은 은행에서 일어나는 모든 데이터에
    대한 스키마일 것입니다. 네트워크 설계자는 은행에서 사용하는 모든 전산망에 대한 구성을 모델로 내놓을 것이고, 프로그래
    머는 은행 업무처리 프로그램을 결과물로 만들 것입니다.
 
     이제 다시 프로그래밍 입장으로 돌아와 보죠. 프로그래밍적인 관점에서 모델링은 현실세계의 요구를 충족할 프로그램을
     어떤 구조로 만들 것인지 결정하고 그것에 맞는 설계 방법론을 적용하는 것입니다. 
     소프트웨어 모델링에는 절차지향 방식과 객체지향 방식이 대표적입니다.  더 많은 패러다임들이 있지만 이 두 가지가 
     가장 많이 쓰여온 방식입니다.
 
 
   나) 절차지향과 객체 지향
   절차지향적 모델링과 객체지향적 모델링을 비교해 보도록 하겠습니다.
   우선 절차지향적 모델링은 프로그램을 기능중심으로 바라보는 방식입니다. 따라서 함수가 모듈의 단위가 됩니다.
   절차지향 모델링을 할 때에는 '무엇을 어떤 절차로 할 것인 가?'가 핵심 질문이 됩니다. 즉, 프로그램의 어떤 기능을 
   어떤 순서로 처리 하는 가에 초점을 두어 설계해 나갑니다. 따라서 이 관점에서 설계된 프로그램은 자료구조와 
   알고리즘으로 구분되는 특성을 갖습니다.

   . 절차지향 프로그램 = 자료구조 + 알고리즘
     
   반면 객체지향 모델링은 기능이 아닌 객체를 중심으로 설계를 합니다.  따라서 모듈의 단위는 클래스가 됩니다.
   (모듈의 단위가 객체가 아닙니다.... ^^ 왜 그럴까요?  객체의 type정의가 바로 클래스이기 때문입니다.)
   객체지향 모델링을 할 때에는 '누가 어떤 일을 할 것인 가?'가 핵심 질문이 됩니다. 프로그램 구현에 필요한
   객체를 파악하고 그 객체의 역할이 무엇인가 정의해 나가는 것이 객체지향이라고 보시면 됩니다.
   따라서 객체지향 관점에서 설계된 프로그램은 객체와 객체의 연결로 되어 있습니다. 그런데 그 객체 안에
   자료구조와 알고리즘이 들어있는 것이죠.

   . 객체지향 프로그램 = 객체 + 객체(자료구조+ 알고리즘) 

  절자지향과 객체 지향 두 방식을 비교하면 아래와 같습니다.
   1) 소프트웨어를 보는 관점
       . 절차지향 관점 : 자료구조 + 알고리즘 = 프로그램
    . 객체지향 관점 : 자료구조 + 알고리즘 = 객체, 객체+객체 = 프로그램

  2) 절차지향과 객체지향 설계방식
   - 절차지향 : 모델링할 대상의 기능을 추출하고 순서적으로 나열
   - 객체 지향 : 객체들을 도출하고 각 객체가 해야할 역할을 정의하고 객체간에 통신을 
     통해 수행을 전개해 나간다.
 
 
  다) 객체지향
   
   객체지향에 대해 좀 더 자세히 살펴보죠. 객체지향 모델링은 인간이 사고하는 방식과 비슷한 방식으로 
   모델링 한다고 하여 natural modeling이라고도 불립니다. 우리가 어떤 일을 수행할 때를 생각해보면
    필요한 사람들을 모으고 각 사람들에게 임무를 부여하는 방식을 취합니다. 객체지향 모델링도
   비슷합니다. 프로그램 수행에 필요한 객체들을 생성하고 이들간에 데이터를 주고 받으면서 프로그램이
    실행되도록 되어있습니다.
 
   여기에서 한가지 느껴지는 것이 있을 겁니다. 절차지향적인 방식은 컴퓨터 작동구조를 염두에 둔 설계이
   므로 기능중심으로 설계를 할 수 밖에 없었습니다. 그런데 인간이 사고하는 방식과 프로그램 설계방식이
   비슷하다면 어떻게 될 까요? 모델링을 쉽게 할 수 있다는 생각을 해 볼 수 있습니다.  이상적인 모델링인
   셈입니다.
 
   요즘처럼 고객의 편의를 제공하거나 문제를 해결하기 위한 프로그램을 만들 때에는 요구사항을 분석할 때
   객체지향 방식이 훨씬 유리할 것이란 결론을 얻을 수 있습니다.  
   객체지향이 처음 나올 당시 큰 기대를 걸었던 것은 바로 인간이 사고하는 방식으로 설계 함으로 해서 설계에
   들어가는 시간을 줄이고 더 탄탄한 구조설계를 할 수 있을 것으로 보았기 때문입니다. 이렇게 해서 소프트웨어의
   위기를 넘기려고 했던 것입니다.
 
 
   다음 강좌는 프로그래밍 입장에서의 객체지향을 살펴보겠습니다.
Posted by windship

4. 객체지향언어 C# - 4.1 맛보기 | 객체지향언어 - C#
전체공개 2009.11.07 17:18
 

4. 객체지향언어 - C#

 

4.1 맛보기


 Java, C++, C#등을 공부하고 있는 많은 학생들이 오해하고 있는 부분이 있다. 심지어 필자가 실무에서 학생들을 가르치면서 필자에게 닷넷을 배우러 오는 학생들 중에 1년 안팎의 실무 경력을 가진 학생들에게 다음과 같이 질문을 해보면 너무도 놀라운 대답을 한다.


필자 : 본인들이 하고 있는 C#의 "객체지향 언어"라는 것이 어떤 의미이지?

학생 1 : 글쎄요... 그거 class를 사용하여 프로그램 하는 것 아닌가요?

학생 2 : 음, 모든 프로그램의 중심이 객체라는 것 아닌가요?


필자 : 그렇다면 객체란 무엇이지?

학생 1 : 음 사물이요......

학생 2 : 프로그램에서 실 생활과 같이 객체를 class로 만들어 사용하는 것 아닌가요?


필자 : 그렇다면 객체지향 언어와 그렇지 않은 프로그램 언어는 뭐가 다른 거야?

학생 1 : 음...

학생 2 : 객체지향 언어는 모두 class로 코딩을 하지만 아닌 언어는 그렇지 않아요.


필자 : 그 차이 밖에는 없는 건가?

학생 2 : 아닌가?


 위의 대화 내용을 보면서 여러분들은 어떻게 생각하는가? 물론 초심자들은 위의 내용조차도 생소할지 모른다. 하지만 혹 대학에서 전산학을 전공하면서 약간의 프로그램적 경험이 있다면 생소하지는 않을 것이다.

 위의 대화 내용에서 필자의 질문에 여러분은 어떻게 대답할 것인가?

 위의 대화 내용에서 학생들이 대답한 것은 절대로 틀리지 않았다. 하지만 필자가 답답함을 느끼는 이유는 객체지향 언어 라는 단어중에 객체지향이라는 단어가 절대로 코딩을 하는 기법을 이야기 하는 것이 아니기 때문이다.

 그런데도 위 두 학생은 모두 마치 객체지향 이라는 의미가 프로그램 실제 코딩을 하는 하나의 기법으로 오해하고 있다는 것이다.

실제 컴퓨터 프로그램에서 객체지향 이라는 개념을 처음으로 도입한 회사는 바로 마이크로소프트 사이다.

 마이크로소프트 사는 하드웨어 통제를 하기 위해 1972년 만들어진 C 라는 언어를 조금더 효율적으로 사용할 목적으로 C++ 이라는 컴퓨터 프로그램 언어를 만들어 발표하였고 이 C++이라는 언어에 처음으로 객체지향 개념을 도입하였다.


 그렇다. 위의 내용을 다시 한번 잘 읽어 보라. 마이크로소프트사가 C++ 이라는 언어를 만들면서 객체지향 개념을 도입한 것이지 마이크로소프트사가 객체지향 개념을 만든 것은 아니다. 즉 원래 객체지향 개념은 컴퓨터 프로그램을 만드는 기법으로 만들어 진 개념이 아니라는 것. 이미 객체지향 이라는 개념은 지구상에 존재하고 있었던 개념이지 새롭게 만들어진 개념이 아니라는 것이다. 이 개념을 마이크로소프트사는 컴퓨터프로그램이라는 곳에 적용시킨 것이다. 그리고 선(SUN)사에서, 이런 C++ 이라는 언어가 가지고 있던 최대 단점인 “문법적으로 사용자가 접근하기가 쉽지 않다” 라는 점을 최대한 보완하여 만들어 낸 것이 바로 JAVA 이다.

 도대체 이 사람 무슨 말이 하고 싶은 거야? 라고 하는 사람도 있겠지만, 객체지향이라는 개념을 마이크로소프트사가 C++에 적용한 것은 바로 설계 기법이다. 프로그램을 만들때 프로그램적 설계 기법에 객체지향 이라는 개념을 도입한 것이다.

 그리고 우리가 배우고 있는 C#도 마찬가지이다.


 생각을 한번 해보자. 우리는 앞에서 닷넷 프레임워크를 배우면서 BCL 이라는 마이크로소프트사가 만들어 놓은 클래스 라이브러리를 MSDN을 통해서 잠깐 접해 보았다. 그리고 공부를 조금 진행해 보니까 우리가 그렇게 아무렇지도 않게 사용하던 데이터 타입 int 형 조차도 BCL 내부에 정의되어 있는 하나의 struct 타입 이라는 것도 알게 되었다.

 그렇다. 이미 마이크로소프트사도 BCL 을 객체지향 이라는 개념으로 아주 크게 라이브러리를 설계해 놓은 것이며, 그 덕분에 우리는 BCL 내부에 있는 class 등을 우리가 사용하고 싶을 때 마음 대로 사용하는 것이다.


 초심자들은 어렵게 생각할 것 없다.


 Console.WriteLine("안녕하세요");


 이제 위의 코딩을 모르는 사람은 없을 것이다. Console 이라는 명령어를 우리가 사용할 수 있는 이유는 바로 이 명령어가 BCL 내부에 정의 되어 있기 때문이다.

 이쯤 되면 아마도 이런 질문을 할 분이 있을지 모르겠다. 그렇다면 프로그래머는 마이크로소프트사가 정의해 놓은 객체지향 개념의 BCL내부의 내용을 그냥 가져다 사용하면 되는 것 아닌가요 라고 말이다.

 위의 질문은 맞는 말이면서 틀린 말이다. 이 궁금증을 풀어야 한다. 그리고 필자가 던진 “위의 질문은 맞는 말이면서도 틀린 말이다” 라고 하는 이 한 문장을 여러분들이 필자의 강좌를 보면서 이해한다면 정말 필자도 보람을 느낄 것 같다.


 자, 이 시점에서 필자는 차후 강좌 진행을 위해서 한 가지 예제를 진행해보고자 한다. 도대체 객체지향 이라는 개념이 C#이라는 프로그램에 어떤 모습인지 말이다. 그릐고 필자가 앞에서 이야기 하고 있는 부분들이 어떤 내용인지 말이다.

 지금 진행하려고 하는 예제는 초심자들에게는 좀 어려울 수도 있다. 하지만 혹 이해가 되지 않는다고 하더라도 그냥 좀 따라해 주기 바란다.


 예제 진행과 동시에 차후 확실한 개념 이해를 위해서 필자는 스토리를 만들었다.


 * 스토리 1


 - 4칙연산을 할 수 있는 계산기를 만들자.

 - 테스트를 위하여 콘솔에서 일단 만든다.

 - 이 계산기는 2개의 숫자를 입력받아 +,-,*,/ 라는 4칙연산중에 하나를 선택하면 그 결과를 보여준다.(단 나눗셈은 소수점 계산은 하지 않고 몫과 나머지를 보여준다.)


 자, 위의 내용을 보면 바로 비쥬얼스튜디오를 열고 콘솔 응용프로그램을 선택하는 분들이 있다. 절대로 그렇게 해서는 안된다. 앞에서 필자가 이야기 했듯이 객체지향이라는 개념은 설계적 개념이다. 즉 프로그램에 앞서 어떤 특정 프로그램을 작성하려면 우선 객체지향 개념으로 설계부터 해야 한다는 것이다.

 차후 다음 강좌에서 조금 더 자세하게 진행 하겠지만 일단 필자를 믿고 따라와 주길 바란다.


 위의 프로그램을 작성하려 할 때 객체지향 개념으로 프로그램을 작성하려면 프로그래머는 선택부터 해야 한다.

 우리는 C# 이라는 언어를 배우고 있지만, 앞에서 계속 언급했듯 "객체지향"이라는 개념을 도입한 언어라면 상관없다. 자바든 C++ 이든 즉 우선 어떤 프로그램으로 위의 프로젝트를 진행할지 결정한다. 우리는 객체지향 개념이 도입되어 있는 언어 중에서 특히 C# 을 선택한 것이다.


 C#을 선택했다면 비쥬얼 스튜디오를 열면 되는가? 


 아니다. 오히려 이 시점에서 우리에게 필요한 것은 아주 깨끗한 A4지 한 장과 볼펜이다.


 다시 한번 강조하지만 객체지향은 하나의 설계기법이라고 보는 관점이 맞다. 즉 객체지향언어인 C#으로 어떤 프로그램을 만든다고 한다면 당연히 설계를 먼저 해야 한다는 의미와 일맥상통한다.

 자, 여러분은 지금 A4지와 볼펜을 준비하자. 그리고 필자가 시키는 대로 따라 해보자.

 위의 스토리를 보면서, 저 계산기를 만들때 필요한 객체를 모두 적어보자.

 이렇게 하면 모두들 혼란스러워 한다. 심지어 조금 프로그램 경력이 있는 사람들은 필자의 의도와는 완전히 다른 쪽으로 생각을 접근한다.

 초심자는 무슨 말인지 이해하지 못하고 좀 아는 분들은 이미 머릿속에 본인들이 사용할 BCL 내부에 있는 명령어들부터 떠 올린다.

윈폼을 주로 한 사람들은 윈폼에서 버튼을 몇 개 만들 것이며, 디자인은 위해서 GDI+를 사용하면 좀 더 예쁜 계산기를 만들 수 있겠구나 머 이런 고민을 하고, 웹폼을 주로 한 프로그래머는 Html은 어떻게 구성하고 차후 렌더링 되면 어떻게 되나 머 이런 것들을 고민할 지 모르겠다.

 그러나 이것은 필자가 요구한 것이 아니다. 이런 내용들은 이미 설계의 단계를 지나쳐 버렸다. 벌써 어떻게 구현할 건지를 고민한 것이다.

 필자가 요구한 것은 오히려 "실생활에서 본인이 계산기를 만든다면 필요한 것이 무엇이냐"라는 개념에 대한 질문을 한 것이다.

 실제 필자가 실무에서 학생들을 가르치면서 특히 데이터베이스 수업을 진행해 보면 오히려 처음으로 배우는 초심자들이 오히려 데이터베이스 설계 수업은 이해가 빠르고 차후 문법적용으로 들어가면 경력자들이 우세하다는 사실을 알게 되었다. 경력자들은 오히려 설계를 하라고 하면 먼저 구현부터 생각한다. 그래서는 안된다. 오히려 설계는 순수하게 접근하는 것이 맞다.

 그리고 필자가 앞에서 언급했듯이 객체지향 이라는 기법은 원래부터 컴퓨터 프로그램을 위하여 도출되어진 이론이 아니다. 이미 실생활에서 여러 분야에서 사용되던 하나의 이론이다. 그것을 마이크로소프트 사가 컴퓨터 프로그램 분야에 적용시킨 것이다.

이 계산기 예제에서 객체를 골라 보라고 한다면 설계 단계에서는 오히려 순수하게 실생활에 근접하게 객체 즉 사물을 떠올리는 것이 타당하다고 하겠다.


 자, 이제 다시 생각해 보라. 어떤가?

 공대를 다니는 공학생이라면 공학용 계산기를 떠올릴지도 모르지만 우리는 4칙 연산만을 제공하는 계산기를 만들자고 한정하였고 그렇다면 차라리 우리 어머니들이 주로 집에서 가계부를 작성하실 때 사용하는 계산기를 떠올려 보자. 그렇다면 이렇게 정리해 볼 수 있지 않을까?


* 어머니가 사용하시는 계산기를 보면서 떠 올린 객체(사물)


 1. 계산기 몸체

 2. 계산기 버튼들

   - 1 ~ 9 까지의 숫자 버튼

   - +, -, *, / 4칙연산 버튼

   - = 버튼

   - CLEAR를 위한 C 버튼


 3. 선택된 버튼의 값이 표시된 LED 계기판


 어떤가? 일단 이 정도만 있으면 계산기 몸체는 만들 수 있을 것 같다.


 아직 필자가 객체지향에 대한 자세한 설명을 하지 않았기 때문에 초심자들은 이해가 좀 어렵겠지만 따라해 주길 바란다. 여기서 우리가 계산기를 완성하려면 다음과 같은 과정을 이해해야 한다.


 1. 계산기 사용자가 본인이 필요한 버튼을 누르면 LED 에 그 값이 표현된다. (사용자의 행위)

 2. LED에 표시된 값은 계산기의 메모리에 저장되어야 한다. (계산기가 스스로 할 행위)

 3. 그렇게 2개의 값과 하나의 연산(+,-,*,/)의 값이 기억되고 드디어 = 버튼을 사용자가 누른다. (사용자의 행위)

 4. 2개의 값과 연산을 기억한 계산기 4개의 연산중에 적당한 연산을 찾아 두 개의 값을 연산한다 (계산기가 스스로 할 행위)

 5. 결과값이 LED에 명시된다. (계산기가 처리해야 할 행위)


 이렇게 지구상의 모든 것을 사물(객체) 중심으로 받아들이는 것이다. 그리고 각각의 객체의 특성과 행위를 찾아서 그 객체를 설명하는 것이다.


 현재 위의 프로젝트에는 실제 아주 크게 보면 2개의 객체가 존재한다.


 1. 계산기

 2. 사용자


 위의 두 개의 객체 중에 계산기를 만드는 것이 우리의 목적이다.


 하지만 우리가 만든 계산기는 어쩔 수 없이 사용자(사람)와 서로의 상호 작용을 일으킨다. 그것을 무시할 수 없다. 그러나 강좌의 진행을 위해 우선 사용자는 무시하고 순수하게 계산기 쪽으로만 객체를 바라보자.


 그렇다면 앞에서도 언급한 것처럼 계산기라는 객체는 다시 여러개의 객체로 이루어 져 있슴을 알 수 있다.


 1. 계산기 몸체

 2. 버튼들

 3. LED 계기판


 그리고 객체는 각각 속성과 행위로 나누어 표현되어 진다고 했다. 계산기 몸체부터 한번 살펴보자.


 계산기 몸체는 특별하게 위의 설명에서 보듯이 특별하게 자기가 하는 행위는 없다. 다만 특성은 있다. 예를 들면 계산기 몸체 크기 정도가 되지 않을까? 즉 다음과 같다.


계산기 몸체

특성

행위

가로길이

없음

세로길이

표 1


 그리고 이제 버튼을 표현해 보자.

 버튼도 앞에서 언급했던 것처럼 숫자버튼, 4칙연산버튼, =버튼, C버튼 으로 나뉘어진다. 각각의 특성과 행위를 살펴보자.


숫자 버튼

특성

행위

가로길이

사용자가 누르면 눌려진다.

세로길이

버튼에 명시될 값

표 2


4칙 연산 버튼

특성

행위

가로길이

사용자가 누르면 눌려진다.

세로길이

버튼에 명시될 값

표 3


= 버튼

특성

행위

가로길이

사용자가 누르면 눌려진다.

세로길이

버튼에 명시될 값

표 4


C 버튼

특성

행위

가로길이

사용자가 누르면 눌려진다..

세로길이

버튼에 명시될 값

표 5


 객체지향적 개념으로 접근할 때, 설계에서 프로그램적 사고는 배제되어야 하는 것이 당연히 옳다. 즉 계산기를 만든다고 했으면 우선 우리가 해야 할 일은 순수하게 계산기의 속성과 행위를 생각하는 것이다. 사실 실제 우리가 실생활에서 위와 같은 재료들을 구입하여 조립한다면 실제 버튼이 하는 일은 한 가지밖에 없다. 바로 사용자가 누르면 눌려지는 것, 그 한가지 뿐이다. 이렇게 바라보는이 바로 객체지향적 관점에서 계산기를 바라보는 것이다.

 물론 이렇게만 한다면 우리는 계산기의 가장 중요한 기능을 빼먹게 된다. 즉 "계산을 한다" 라는 행위 말이다. 위의 경우 4칙 연산 이라는 행위를 빼 먹고 단순히 겉으로만 계산기를 완성시켰다. 즉 기능은 없고 모양만 있는 계산기의 모형이 되는 셈이다.

 실제 계산기를 만들기 위해서는 필자가 닷넷을 설명하면서 언급한 바와 같이 비록 성능이 떨어지는 CPU라고 할지라도 CPU도 있어야 하며, 당연히 메모리도 있어야 하고, 프로그래머가 실제 짠 프로그램을 저장할 저장장치도 필요하게 된다.


 여기서 우리는 컴퓨터 프로그램이라는 것에 대한 관점을 이해해야 한다. 컴퓨터 프로그램이 전지전능한 것은 아니다. 즉 프로그래머는 이미 컴퓨터라고 하는 하드웨어가 존재함을 인정하고 프로그램을 작성하는 것이다. 우리가 계산기를 실제 현실세계에서 만든다고 한다면 이미 여러분은 계산기 틀부터 버튼, 회로 등은 이미 만들어진 것들을 사서 조립하게 되지 않겠는가? 아무리 성능이 떨어지는 것이라고 해도 CPU 및 메모리를 우리가 직접 만들 수는 없지 않겠는가? 당연히 사야 한다.

 프로그래머 역시 이미 틀이 완성된 상태에서 4칙 연산을 하는 프로그램만 만들어, 그 틀에 맞추어 넣게 되는 것이다.


 다시 위의 계산기 프로그램을 생각해 보자.


 위의 표로 명시된 5개의 객체를, 이미 만들어진 부품을 샀다고 한다면 여러분은 산 것들을 조립만 하면 된다.

 그리고 CPU도 사고 메모리도 사고 보조기억장치도 샀다고 하고, 그것들을 모두 조립했다고 가정해 보자. 그러면 여러분은 이제 회로, 즉 4칙연산을 하는 프로그램만 작성하면 되는 것이다.

 “아 도대체 이 사람이 무슨 말을 하는 거야” 라고 생각할지도 모르겠다. 그러나 굉장히 중요한 관점의 차이이다. 사실 우리가 만들어 내는 모든 프로그램은 일단 기본적으로 CPU, 메모리 등과 같은 컴퓨터 하드웨어는 존재한다고 인정하고 개발에 임하는 것이기 때문이다.

 즉 프로그램에서 객체지향 언어라고 하는 것은 이미 기본적인 객체는 존재한다 라고 가정하고 시작한다는 것이다.


 그렇다면 위에서 우리가 설계한 계산기의 몸체와 버튼은 어떻게 구한단 말인가? 라고 반문하겠지만, 닷넷이라는 플랫폼 자체에 계산기를 만들기 위하여 사용하게 될 물건들은 이미 마이크로소프트사가 제공하고 있다는 뜻이다.

 즉 위에서 계산기의 틀이니, 버튼이니 하는 것은 이미 마이크로소프트사가 제공하는 것들을 가져다가 사용하면 된다는 것이다. 그리고 우리는 다만 그 제공하는 틀을 잘 활용하여 4칙연산 프로그램만을 작성하면 되는 것이다.


 자, 정리해 보자.


1. 컴퓨터 프로그램이라는 것으로 계산기를 만들려고 한다.

2. 우리가 만든 계산기는 실제 생활에서 사용하는 것이 아니라 이미 컴퓨터 라는 공간에서 운영체제가 설치되어 있는 컴퓨터에서 사용자가 이미 컴퓨터를 시작한 상황에서 사용할 계산기이다.

3. 컴퓨터 프로그램 중에 어떤 언어를 사용할까?

 - 우리는 마이크로소프트사가 제공하는 C# 이라는 언어를 사용할 것이다.

4. C#은 객체지향 언어이다.

 - 그래서 우리는 앞에서 계산기에 필요한 객체들과 그 객체들의 속성 및 행위를 정리해 보았다.

5. 그렇다면 계산기 몸체와 버튼을 우리가 만들어야 하나?

 - 아니다. 이미 마이크로소프트사가 닷넷 내부에 정의해 놓은 객체들을 가져다 조립만 하면 된다.

6. 어떻게 가져다 쓰지?

 - 여기서 우리는 다시 한 가지를 결정해야 한다. 이 계산기를 사용하는 사용자가 인터넷을 통해 웹에서 사용할 것인지 아니면 일반 응용 프로그램으로 사용할 것인지 말이다.

7. 만약 웹에서 사용하려면?

 - 그렇다면 닷넷 내부에서 제공되는 객체들 중에 계산기 틀과 버튼들을 모두 웹폼으로 사용해야 한다.

8. 만약 일반 응용 프로그램으로 사용하려면?

 - 당연히 이 경우는 윈폼으로 작성되어야 한다.

9. 그런데 그것이 객체지향과는 무슨 연관인가?

 - C#은 이미 마이크로소프트사가 BCL 내부에 클래스 등을 활용하여 객체지향 기법으로 설계된 내용을 이미 완성시켜 놓았다. 그래서 프로그래머는 현실 세계에서 계산기 틀을 구매하는 것처럼, BCL에 정의되어 있는 객체들을 가져다 사용하기만 하면 되는 것이다.

10. 그렇다면 프로그래머는 할 일이 없는 것 아닌가?

 아니다. 현실 세계에서 계산기 조립을 마치고, 컴퓨터처럼 CPU 등을 설치했다고 해도 사용자는 아직 계산기를 사용할 수 없다.

여러분이 아무리 좋은 컴퓨터를 사도 윈도우와 같은 운영체제를 설치하지 않으면 컴퓨터를 사용할 수 없는 것과 같다.


 필자는 위의 10가지로 정리해 보았다.

 즉 마이크로소프트사는 이미 닷넷 프레임워크 내부의 BCL 에 많은 것들을 만들어 놓았다. 그 BCL 내부에 정리 되어 있는 프로그램 방식, 즉 설계 기법이 객체지향 방식이다.

 그래서 우리가 그 내부에 있는 객체들을 가져다 사용함에 있어 효과적으로 운영하고 사용하려면 그 객체지향 기법에 대하여 이해력을 가지고 있어야 한다.

 생각해 보라. 실생활에서 식당이라는 것을 운영하고 김치찌개를 만들어 판다고 해도 좀 더 맛있는 김치를 담기 위해서는 여러분은 좋은 배추를 고르는 방법에서부터 많은 지식들을 가지고 있어야 한다.

 마찬가지이다. 단순히 그냥 아무 것이나 막 가져다 쓸 수는 없지 않은가. 이것이 바로 프로그래머가 객체지향 개념을 이해해야 하는 첫 번째 이유이다.


 아마 초심자들은 도대체 무슨 말인지 이해가 잘 되지 않을 것이다.

 이 강좌에서 초심자들까지 이해시킬 수 있도록 계산기 폼을 만든다는 것은 정말이지 실현 불가능이다. 왜냐하면 그래도 윈폼에 대한 기본적 지식은 있어야 하기 때문이다.

 그래서 일단 객체지향 개념의 이해 차원에서 설명하기 위해서라도 그냥 간단하게 흉내만 내 보려 한다.


 * 비쥬얼 스튜디오를 열자.

 * 파일 -> 새로만들기 -> 프로젝트 를 차례대로 선택하자.

 * 그리고 그림 1에서 처럼 윈도우 응용 프로그램을 선택하자.


 그럼 그림 2처럼 나온다.

그림 1

 

그림 2


윈폼을 한번쯤 다루어 본 분들은 이해가 쉽겠지만 처음이라면 그냥 일단 필자를 믿고 따라해 보자. 


그림 2의 왼쪽에 상단에 보이는 도구상자라는 탭을 선택해 보자.

 

그림 3


위의 그림 3처럼 나올 것이다. 필자가 빨간색 사각형을 칠한 Button 이라는 글자를 더블 클릭해 보라.

 

그림 4

그림 4처럼 오른쪽 디자인 페이지에 Form1 위에 하나의 버튼이 생성될 것이다.

그렇다면 저 버튼을 클릭해서 크기를 조절해 보자. 크기를 조절하는 것은 어렵지 않을 것이다.

 

그림 5


그림 5처럼 만들어 지는가?

 

그림 6

 

버튼을 클릭한 상태에서 왼쪽에 있는 속성 탭을 선택해 보자. 그러면 그림 6처럼 나올 것이다.

거기서 스크롤을 활용하여 아래로 내려보자. 그러면 그림 7처럼 text 라는 속성이 보일 것이다. 그 값을 숫자 1로 변경해 보자 (지금은 button1 이라고 되어 있다)

 

 

그림 7

 

그럼 아마도 다음 그림 8처럼 바뀌어 있을 것이다.

 

그림 8


 어떤가? 초심자들은 신기할 지도 모르겠다. 그렇다. 필자가 앞에서 계속해서 이야기했듯이 우리가 현실 세계에서 계산기를 만든다고 했을 때, 가게에서 계산기 모양의 틀과 버튼을 구매하는 것처럼 마이크로소프트 사는 이미 이런 툴을 여러분에게 제공하고 있는 것이다.

 자, 좀 더 확실히 이해하기 위해서 Ctrl + F5 를 눌러보자.

 그러면 여러분이 만든 프로그램이 실행되면서 결과물이 나올 것이다. 그러면 그 결과물의 1 이라는 버튼도 한번 클릭해 보자. 어떤가? 잘 클릭되는가? 클릭은 잘 될 것이다. 그렇다면 여러분은 왼쪽 도구상자를 이용하여 잘 하면 계산기의 모양은 만들 수 있지 않겠는가?

 이쯤 되면 혹 일부 초심자들은 아 별거 아니구나 하는 생각을 할 것이다. 그러나 그렇지 않다는 것을 미리 이야기 하고 싶다.

하여튼 우리는 이렇게 마이크로소프트사가 제공하는 툴을 활용하여 디자인을 할 수 있는 것이다.


 그러나 이러한 디자인 역시, 이미 BCL 내부에 정의되어 있는 객체지향적 개념으로 설계된 클래스 등을 우리가 가져다 사용하고 있다는 사실을 알아야 한다. 또한 왼쪽 도구 상자에서 Button 이라는 객체를 더블 클릭하면 Form1 이라는 객체 내에 자동으로 생성되어지지만 사실 내부적으로 이미 프로그램이 코딩되고 있다는 사실도 알아야 한다. 이 부분에 대해서는 차후에 이야기 하겠다.


 방금 우리가 만든 Button은 이미 프로그래머가 사용하기 편하게 하기 위해서 닷넷 프레임워크 내부의 BCL 에 정의 되어 있다는 것이다. 실제로 그런 것인지 확인해 보자.


 우선 MSDN 사이트를 방문하자.

http://msdn.microsoft.com/ko-kr/default.aspx


 그리고 검색란에 그림 9 와 같이 Button이라고 치고 검색해 보자. 그림 10과 같이 나올 것이다.

 

그림 9


 

그림 10


 그림 10에서 보면 알수 있듯이 버튼(Button)도 여러 종류가 있다. 우선 여기서는 네임스페이스가 System.Windows.Forms 라고 되어 있는 (필자 검색 결과에서는 맨 위의 것)을 클릭하고 페이지를 이동해 보자. 그리고 오른쪽 설명 부분에서 C# 부분을 필자는 캡쳐했다.

 그림 11에서 보면 알겠지만, 우리가 만든 그것도 아주 쉽게 툴에서 만들었던 그 버튼도 결국 class 라는 데이터 타입으로 이미 BCL 내부에 정의되어 있다. 그리고 우리가 툴을 이용하여 디자인을 만들었지만 실제 내부에는 이미 Button 이라는 클래스가 사용되어 지고 있는 것이다.

 뭐 그 내부까지 우리가 알 필요가 있습니까? 라고 되묻고 싶은 사람도 있겠지만 물론이다. 지금 필자는 객체지향 개념과 필요성에 관한 강좌를 하고 있고 초심자들을 위하여 계산기를 만들 때 객체지향의 개념 접근 방식에 관하여 설명하다 보니 이렇게 예를 들고 있을 뿐 차후 객체지향 개념의 강좌가 끝날 무렵에는 분명히 다를 것이기 때문이다.


 

그림 11


 우리는 계산기를 만들기 위해서 이미 앞에서 필요한 객체를 찾아 보았고 그 객체의 속성과 행위를 찾아 보았다.

 그런데 앞에서 우리가 정리했던 표 다섯 개의 객체는, 결국 우리가 현실세계에서 계산기 틀과 버튼을 구입하듯이 이미 마이크로소프트사가 제공하는 윈도우 응용프로그램으로 해결할 수 있다는 것을 알았다.

 그렇다. 결국 우리가 앞에서 종이와 볼펜을 활용하여 설계해 보았던 객체들은 결국 마이크로소프트사가 제공하고 있다는 것을 알았다. 그리고 이 객체들은 결국 BCL 내부에 객체지향적 개념으로 설계되어 이미 만들어져 있다는 사실도 알게 되었다.


 그렇다면 프로그래머는 무엇을 한단 말인가?


 아직 초심자들에게 정확히 이 개념을 전달하기란 어렵다. 하지만 일단 다시 한번 필자를 믿고 우리가 찾아 놓은 MSDN 을 조금 더 살펴보자.


 그림 11의 내용중 Button 이 선언되어 있는 코딩 부분을 좀 살펴보자.


[ComVisibleAttribute(true)]

[ClassInterfaceAttribute(ClassInterfaceType.AutoDispatch)]

public class Button : ButtonBase, IButtonControl

표 6


 위의 코드가 잘 이해 되는가? 도대체 저게 무슨 소리인지 말이다.

 정답부터 이야기 하면 저 코딩 모두가 바로 객체지향 개념에서 시작되는 코딩 기법이다. 즉 객체지향의 개념이 이해되어야 이해할 수 있는 부분이라는 것이다.

 저 내용을 이해해야 하다 못해 앞에서 우리가 했던 계산기 틀을 만드는 과정에서 좀 더 멋지고 이쁘고 기능이 다양한 계산기틀을 만들 수 있는 것이다.

 좀 이해가 되는가? 아직 어려울 것이다.


 정리해 보자.


 * 우리는 계산기를 만들려 했다.

 * 그리고 C#으로 만들기로 했다. 그래서 계산기에 필요한 객체들과 속성들, 행위들을 정의하고 정리했다. 그리고 그 정리된 내용대로 마이크로소프트사가 제공하는 윈도우 응용 프로그램을 활용하여 만들 수 있다는 것을 알았다.

 * 그런데 우리가 막연하게 사용하는 툴도 결국 닷넷 프레임 워크 내부의 BCL에 이미 정의 되어 있는 클래스들을 활용하고 있는 것이라는 것도 알았다.

 * 그런데 그 클래스들도 결국 객체지향적 설계로 이루어져 있다.

 * 그래서 비록 우리가 MSDN을 찾았음에도 아직 그 내용을 이해하기가 쉽지 않다.


 여기까지 이해가 되는가? 자, 원점으로 돌아오자. 어째든 우리는 계산기 모양을 완성했다고 치자. 그러나 아직 계산기는 동작하지 않는다.


 우리는 이제 겨우 마이크로소프트사가 제공하는 툴을 활용(엄밀히 말하면 BCL에 정의 되어 있는 내용을 활용)하여 계산기 외부만을 만든 것이다. 즉 프로그램 관점에서 보면 이미 우리는 클라이언트에게 보여줄 부분(VIEW)을 완성한 것이다.

 이제 이렇게 만들어진 계산기의 계산을 하는 것은 우리가 직접 만들어야 한다. 즉 로직부분, 계산기의 가장 핵심인 회로 부분이이 필요하게 된 것이다.


 그래서 또다시 설계가 필요하게 된다.

 다만 이 시점에서는 앞에서 생각했던 여러 개의 객체를 하나로 줄일 수가 있다. 왜냐하면 우리는 여러 개의 객체를 모아서 "계산기"라는 하나의 모양으로 완성시켰기 때문이다.

 그래서 이제 우리의 눈앞에는 단 하나의 객체만이 있다. 그것이 바로 계산기이다.


 그러면 이제 그 계산기가 가지는 속성과 행위를 찾아보자. 다음과 같다.


계산기

특성(속성)

행위

계산기 크기

크기는 이미 정해졌다.

계산기 틀이 완성되었기 때문에.

덧셈을 한다.

버튼의 크기

이것도 완성되었다.

뺄셈을 한다.

LED판 

여기서는 신경 끄자.

나눗셈을 한다.

위에서 보았듯, 계산기의 기본 특성은 이미 틀이 만들어질 때 완료되어 버렸다.

곱셈을 한다.

표 7


 앞에서 표 5개로 설계해 본 것과 같이, 다시금 위 표 7 처럼 설계하는 과정을 객체지향적 설계라고 하는 것이다.


 그리고 이렇게 설계된 내용을 프로그램으로 표현해야 한다. 객체지향 언어에서 위와 같이 설계된 내용을 표현하기에 가장 적절한 데이터 타입이 바로 class와 앞에서 배웠던 struct 라고 하는 것인데, 물론 아직 class에 관해서는 언급하지 않았다. 계속 설명해 나갈 것이다.


 프로그램은 이미 앞에서 언급했듯이 필요한 값을 메모리에 저장했다가 적절한 시기에 CPU에게 연산을 시키는 과정이라고 했다.

 다음의 코드를 잠시 보자.


using System;

 

namespace Plus_Ex01

{

class Program

    {

      static void Main(string[] args)

      {

        int i = 16;

        int j = 8;

        int plus = i + j;

        int minus = i - j;

        int cross = i * j;

        int devide = i / j;

        Console.WriteLine("덧셈결과 : {0} - 뺄셈결과 : {1} - 곱셈결과 : {2} - 나눗셈결과 : {3}",plus,minus,cross,devide);    

      }

    }

}

예제 1


 위의 코딩은 결국 4칙연산을 모두 하고 있다. 그러나 단점이 있다. 결국 16과 8의 4칙연산만을 할 수 있을 뿐 우리가 원하는 결과는 아니다. 즉 위의 코딩은 객체지향적 코딩이 아니다.

 우리는 이미 계산기라는 객체를 설계하였다. 그리고 우리가 말하는 계산기라는 객체는 어떤 상황 속에서도 두 개의 변화되는 값을 주면 계산을 해내야 한다.

 그래서 객체지향적 프로그램에서는 그 객체를 표현하는 수단으로 두 가지를 제공하고 있다. 그것이 바로 위에서 이야기한 class 와 struct 이다.


 좀 더 자세한 것은 앞으로 강좌에서 하나씩 언급하겠다. 우선 다음 예제를 보도록 하자.


using System;

 

namespace Chapter04_Ex02

{

    class Cal

    {

        public void Plus(int a, int b)

        {

           int p = a + b;

           Console.WriteLine("덧셈 결과 : {0}",p);

        }

        public void Minus(int a, int b)

        {

           int m = a - b;

           Console.WriteLine("뺄셈 결과 : {0}", m);

        }

        public void Cross(int a, int b)

        {

           int c = a * b;

           Console.WriteLine("곱셈 결과 : {0}", c);

        }

        public void Devide(int a, int b)

        {

           int d = a / b;

           Console.WriteLine("나눗셈 결과 : {0}", d);

        }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

           Cal MyCal = new Cal();

           MyCal.Plus(16, 8);

           MyCal.Minus(16, 8);

           MyCal.Cross(16, 8);

           MyCal.Devide(16, 8);

        }

    }

}

 

예제 2


 물론 아직 위의 코드가 낯설 것이다. 우리는 정확히 class 가 무엇인지에 대해서도 배우지 않았으니까.


 필자는 표 7에서 설계한 계산기를 class 라는 데이터 타입을 사용하여 정의하였다. 그리고 그 계산기가 행하는 행위를 4개의 메써드(METHOD) Plus(덧셈), Minus(뺄셈), Cross(곱셈), Devide(나눗셈)으로 표현했고, Main()함수에서 다음과 같이 코딩하였다.


Cal MyCal = new Cal();


 위 코딩은 차후에 다시 자세히 설명하겠지만 메모리에 위의 class 내용을 모두 Heap공간에 할당하고 그 주소값을 stack영역의 MyCal 이라는 곳에 저장하라는 의미이다. 이해가 되지 않는다면 그냥 쉽게 위의 Cal 이라는 계산기의 코드 모두를 메모리에 저장한다고 이해해 주기 바란다.


           MyCal.Plus(16, 8);

           MyCal.Minus(16, 8);

           MyCal.Cross(16, 8);

           MyCal.Devide(16, 8);


 차례대로 4개의 메소드를 호출하여 그 결과값을 화면에 출력하였다.


 앞에서 이미 우리는 계산기 모양은 만들어 두었다. 그리고 이번에는 실제 계산기 로직이 포함된 코딩을 해 보았다. 즉 모양과 내부 회로(실제의 프로그램)를 따로 설계한 것이다. 그리고 class 라는 새로운 데이터 타입을 활용하여 설계되어진 객체를 프로그램으로 표현하였다.

 그렇다면 이제 우리가 할 일은, 미리 만들어 놓은 계산기 모형에다가 나중에 만든 프로그램을 연결하는 것이다.


 몇번이나 말했듯 객체지향이란 개념은 설계적 개념이다. 즉 모형과 로직을 따로 설계하는 것이다. 그리고 지금은 이 두 개를 합치는 일만 남았다.

 아직 어려울 것이다. 도대체 무슨 말을 하는 거야 라고 말이다. 그래서 앞으로 하나씩 배워야 한다. 이번 강좌는 차근 차근 읽고 따라 할 것들은 반드시 따라해 보길 권한다.


 정리해 보면 우리는 계산기 프로그램을 짜려고 했다. 그래서 객체지향 개념으로 설계도 했다. 그런데 그 설계가 두 가지로 나뉘었다. 하나는 계산기 모형이었고 하나는 실제 계산을 하는 로직이었다.

 그리고 그러한 객체를 표현하는 수단은 이미 앞에서 찾아본 것처럼 마이크로소프트사가 제공하는 것도 class 라는 데이터 타입이었고, 우리가 사용한 것도 class 이었다.

 

즉 객체지향 프로그램은 결국 객체를 중심으로 설계를 하고, 그 설계를 기반으로 프로그램을 작성하는 것이다.

 

 

다음 강좌부터는 본격적으로 객체지향 개념과 객체지향 개념을 프로그램에서 어떻게 표현하며 객체지향 프로그램의 장점은 무엇인지에 대하여 하나씩 알아보겠습니다.

 

 

 

 

이 강좌의 예제 파일은 업로드 되어 있는 파일을 받으셔서 압축을 푸시면 들어 있습니다.

 

 

--------------------------------------------------------------------------------

혹 퍼가시거나 배포하실분은 출처를 반드시 표시해 주세요   

부산직업전문학교 닷넷 전임강사 이지완 카페 - cafe.naver.com/busanitnet

--------------------------------------------------------------------------------



Posted by windship