티스토리 뷰

1. 개요


C#의 가장 중요한 요소는 완벽한 객체 지향 언어라는 점입니다. C#은 C++과 Java와 같이 객체지향 언어의 이점을 가지고 있으며, OOP 경험을 향상 시키는 몇가지 추가적인 요소가 있습니다. 객체지향 이외에도, C#은 소프트웨어 시스템 개발 시 쉽게 재사용할 수 있는 블랙 박스 엔티티의 개념을 가지고 있는 컴포넌트의 생성에 대한 기능이 디자인되었다는 점입니다. 


이 글에서는 객체지향 언어가 무엇인지에 대한 큰 그림을 그릴 것입니다. 또한 객체, 클래스, 추상화, 캡슐화, 상속 및 다형성에 대해서 논할 것입니다. 이 내용에 대한 C#에 부분을 살펴볼 것입니다. 소프트웨어 재사용을 용이하게 하는 방식으로 객체 지향 프로그래밍의 생각을 확장할 수 있는 컴포넌트에 대한 소개와 함께 결론을 지을 것입니다. 


2. 객체


객체는 실제와 소프트웨어의 의미를 모두 가지고 있습니다. 객체 모델은 이 둘 사이의 관계를 나타냅니다. 이 섹션에서는 객체에 대한 핵심 용어를 정리할 것입니다.


실 세계에서의 객체


객체는 실제 세계의 직관적 의미를 가지고 있습니다. 여기에는 공, 자동차, 비행기와 같은 구체적이고 명백한 오브젝트들이 있습니다. 또한 위원회, 특허, 보험 계약과 같은 추상적인 내용을 가진 객체도 있습니다. 객체들은 수행할 수 있는 속성과 행위를 가지고 있습니다. 공은 사이즈, 무게, 색등등이 있으며, 이에 대한 행위는 던지기, 받기, 떨어트리기 등이 있을 수 있습니다. 


객체의 클래스들 사이에는 다양한 관계가 있을 수 있습니다. 예를 들어 하나의 관계는 특별한 관계일 수 있습니다. 이는 자동차는 특별한 차량의 종류가 될 수 있습니다. 다른 관계는 전체/부분의 관계입니다. 자동차는 엔진, 샤시, 휠 그리고 다른 파트로 구성이 됩니다. 


객체 모델


객체는 또한 프로그램에서 사용할 수 있습니다. 객체는 실세계의 소프트웨어 모델을 설정할 수 있기 때문에 프로그래밍에서 유용합니다. 소프트웨어 객체는 실세계의 객체와 대응됩니다. 실세계를 객체 용어를 통해 명시적으로 묘사하면, 시스템을 더욱더 명시적이고 정밀하게 이해할 수 있습니다. 프로그래밍 언어를 이용하여 실제 소프트웨어로 모델을 구현할 수 있습니다. 이 방식으로 구현된 소프트웨어 시스템은 실제 시스템에 좀 더 충실한 경향이 있습니다. 그리고 실제 시스템이 변경되었을 때 좀더 빠르게 대응할 수 있습니다. 


객체 모델을 묘사하기 위한 형식 언어가 있습니다. 가장 유명한 언어는 UML입니다. UML은 다른 이전 모델링 언어를 합쳐놓은 것입니다. 형식 모델링 언어는 이 내용을 벗어납니다. 하지만 이 내용을 매우 유용하기 때문에 관련된 내용을 찾아 보는 것도 좋습니다. 


재사용 가능한 소프트웨어 컴포넌트


소프트웨어에서 객체의 다른 장점은 재사용 가능한 소프트웨어 컴포넌트로 구성할 수 있다는 점입니다. 하드웨어는 재사용 가능 하드웨어 컴포넌트를 통해서 오랜 기간동안 많은 이점을 누리고 있습니다. 예를 들어 컴퓨터는 전원 장치, 인쇄 회로 기판 및 다른 구성요로부터 만들어 질 수 있습니다. 인쇄 회로 기판은 칩을 통해서 만들어 질 수 있습니다. 같은 칩은 다른 컴퓨터에서 재사용될 수 있습니다. 그리고 새로운 하드웨어 디자인은 처음부터 수행될 필요가 없습니다. 적절한 소프트웨어 기술을 사용하여 소프트웨어 시스템에서도 재사용을 동일하게 사용할 수 있습니다. 객체는 소프트웨어 재사용의 기초가 됩니다. 


소프트웨어에서의 객체


객체는 독립 적인 모듈로써, 데이터와 관련 함수를 포함한 소프트웨어 엔티티입니다. 객체는 상태와 특정 행위를 가지고 있습니다. 그림은 은행 계좌에 대한 객체를 나타내고 있습니다. 이 객체의 상태는 계좌 소유자, ID, 잔액으로 이루어져 있습니다. 이 계좌의 행위는 입금과 출금, 계좌 소유자 변경, 계좌 상태 획득으로 이루어져 있습니다. 객체는 추상화, 캡슐화, 인스턴스의 수단으로 제공됩니다. 




상태와 행위


객체는 프로퍼티나 속성의 집합으로 본질적인 특성을 가진 데이터를 가집니다. 객체의 상태는 특정 시점에서의 이 속성의 값입니다. 객체의 행위는 특정 작업에 대한 집합을 나타냅니다. 이는 자신 혹은 다른 객체를 처리해야 합니다. 아래 그림에서 보이는 것과 같이 데이터와 작업들은 하나의 객체에 합쳐져 있습니다. 소프트웨어 디자인의 한 파트로써, 이러한 패키징은 캡슐화와 추상화에 도움을 줍니다. 관련항목은 하나의 개념 단위로 설정이 됩니다. 

 




추상화


추상화는 상세한 내용을 포함하지 않고 필수의 기능을 가집니다. 추상화의 모든 인스턴스는 공통적인 요소를 공유합니다. 추상화는 복잡성 처리에 도움을 줍니다.


캡슐화


추상화의 구현은 반드시 시스템의 일부분으로부터 떨어져 숨겨져 있거나, 캡슐화 되어야 합니다. 객체는 아래 그림과 같이 공개할 데이터(public)와 공개하지 않는 부분(private)을 가지고 있습니다. 

 




private 부분은 public에 대한 부분을 구현하는 것인 반면에 public부분은 시스템에 공개하고자는 내용입니다. 데이터 들은 프로그램으로부터 떨어진 private 상태입니다. 데이터는 함수 혹은 메소드라 불리는 public 인터페이스를 통해서 접근할 수 있습니다.  이러한 보호 방안은 두 가지가 있습니다. 


내부 데이터는 충돌로부터 보호를 받습니다.

객체의 사용자는 인터페이스 변경으로부터 보호를 받습니다.


캡슐화의 예


계좌 객체의 목록을 가지고 있는 은행 객체를 생각해보도록 하겠습니다. 우리는 어떻게 이 리스트를 표현할 수 있을 까요? 배열이나 링크드리스트 혹은 다른 방식으로 사용할 수 있을 것입니다. 링크드리스트라 불리는 특정 방식을 선택했다고 하면, 이 방식에 대한 사용 방식을 시스템에 알려야 합니다. 이는 지나치게 복잡한 시스템을 가지게 되는 것과 같습니다. 게다가 링크드리스트에 접근하는 방식이 시스템에 여러 개가 존재하기 때문에 이 시스템은 매우 불안정할 것입니다. 이는 에러를 만들 수 있는 코드의 일 부분을 제공할 여지가 있습니다. 


더 좋은 방식으로는 은행 객체안에서 리스트를 캡슐화하고, AddAccount와 DeleteAccount와 같은 public 함수를 통해서 접근하는 방식입니다. 시스템의 나머지 부분은 리스트에 대한 다른 부분을 고려하지 않아도 되지만, public 함수를 통해서 제어가 가능합니다. 


3. 클래스


클래스는 공통적인 행위와 구조를 가진 모든 객체를 그룹화합니다. 클래스는 같은 타입의 새로운 객체의 생성을 허용합니다. 객체는 어떤 클래스의 인스턴스입니다. 인스턴스를 생성하기 위한 개별 객체를 생성하는 과정을 참조할 것입니다. 클래스는 상속과 포함과 같은 다양한 방법으로 연관을 지을 수 있습니다. 


상속


상속은 객체 지향 프로그래밍 패러다임의 핵심 기능입니다. 클래스의 공통된 요소를 추상화할 수 있습니다. 그리고 상위 레벨의 클래스에 이를 넣을 수 있습니다. 자식 클래스에서 공통되는 행위를 상속하여 기능을 추가하거나 변경할 수 있습니다. 상속은 코드 재사용과 확장성을 용이하게 합니다. 


부모 클래스로써 Account를 상속하는 CheckingAccount와 SavingsAccout 클래스를 고려할 수 있습니다. 모든 계좌는 잔액과 같은 공통 특성을 공유할 수 있습니다. 또한 다른 종류의 차이도 있을 수 있습니다. 예를 들어, 계좌 확인은 한달 마다 비용이 들고, 저축액에는 특정 이자율을 지급해야 하는 부분을 들 수 있습니다. 아래 그림은 계좌의 다른 속성 사이의 관계를 나타냅니다. 




 

클래스의 관계


클래스는 여러 방법으로 관계를 표현할 수 있습니다. 


  1. 상속 관계 (IS-A)는 특별한 다른 클래스의 기능을 가지는 클래스입니다. CheckingAccount은 Account 클래스의 자식 클래스입니다. 
  2. 구성 관계 (HAS-A)는 하나의 클래스가 다른 클래스와 부분이 되는 관계입니다. Bank는 Account 객체의 리스트를 보유하고 있습니다. 
  3. 사용 관계 (USES-A)는 하나의 클래스가 다른 클래스의 기능을 사용하는 관계입니다. 


4. 다형성


매달마다 계좌의 다른 부분에 대한 상태를 생성하는 문제를 고려해봅시다. 계좌를 확인하고, 저장하는 것은 다릅니다. 하나는 비용이 들고, 다른 하나는 이자를 받습니다. 


전통적인 방식은 계좌의 구조체의 타입에 대한 필드를 유지하고 수행하기 위해서 각 타입에 따른 Case를 처리할 수 있는 Switch 구문을 사용합니다. Switch 구문을 사용하는 것은 에러 발생 가능성을 높이며 새로운 타입이 추가될 때 많은 유지보수성을 요구합니다. 이에 대한 대안은 각 Account 클래스에서 GetStatement 함수를 통해서 명세서를 처리하는 부분은 처리하는 것입니다. 


일반적으로 월 명세서 코드는 계좌의 다른 타입을 처리할 수 있어야 합니다. 그리고 추가적인 타입을 지원하기 위해서 수정되어서는 안됩니다. GetStatement 함수를 제공하고, 상속받는 자식 클래스에서는 이 함수를 재정의합니다. 실제 Account 클래스에 따라서 적절한 GetStatement 함수가 호출이 됩니다. 


같은 함수에 대한 기능은 다형성에 따라 객체를 기반으로 다른 결과를 처리합니다. 비록 어떠한 부분이 변경되었지만, 다형성은 복잡한 시스템을 단순화 시킵니다. 이는 객체 지향 언어의 가장 중요한 부분 중 하나입니다.


5. 객체 지향 언어


객체를 사용하기 위해서 프로그램을 어떻게 개발을 해야 합니까? 캡슐화는 많은 프로그래밍 언어에서 쉽게 구현됩니다.


Simula와 C++


1967년 노르웨이에서 클래스 구조를 처음으로 사용하는 Simula 언어가 개발되었습니다. 이 언어는 Algol로부터 확장되어 개발되었습니다.  C++ 창시자인 Bjarne Stroustrup은 Simula를 모델 컴퓨터 시스템을 모델링 하기 위해서 시뮬레이션 프로그램 개발에 대한 그의 박사 연구에 사용을 하였습니다. 그는 Simula 언어가 상위 레벨의 추상화를 위해 매우 표현적인 것을 발견하였습니다. 그러나 논문에 필요한 수치 결과를 얻기 위해 프로그램을 실행하는 시점이 왔을 대, 성능이 너무 느린 것을 발견하였습니다. 


그래서 그는 그의 번역 프로그램을 C로 개발하였습니다. 그러나 그는 이를 매우 지능적으로 개발을 하였습니다. 손으로 모든 것을 코딩하는 대신 그는 클래스에 대한 확장성을 가지게 하였고, 이를 C언어로 전환하였습니다. 이는 이후 C++로 변경된 C with Classes라고 불리는 언어의 시초가 되었습니다. 이 번역 프로그램은 C++언어를 C로 전환할 수 있는AT&T의 ctfont 컴파일러가 되었습니다.


이는 더많은 C++ 컴파일러를 만들게 하는 촉진제 역할을 하였습니다. 이후의 C++ 컴파일러는 특정 장비를 위해 머신 언어로 바로 번역을 할 수 있게 되었습니다. Cfornt를 이용하여 C로 번역이 되든, 바로 머신언어로 번역이 되든 마지막 결과는 타겟 플랫폼을 머신 언어 코드로 컴파일이 되었습니다. 코드를 컴파일하는 것 외에, 여러가지 방안으로 C++의 디자인의 효율성이 조정될 수 있습니다. 


스몰토크


또 다른 주요 객체 언어는 스몰토크입니다. C로부터 개발된 C++과는 달리 스몰토크는 순수 객체 지향 언어로 만들어 졌습니다. 스몰토크에서 모든 것을 심지어 숫자를 객체로 구현할 수 있습니다. 스몰토크에는 언어의 일부분을 차지하는 광범위한 표준 클래스가 있습니다. 또한 스몰토크를 위한 클래스 브라우저와 디버거와 같은 프로그램 개발 툴도 있습니다. 이에 대한 결과로 스몰토크는 매우 유능한 프로그램 개발환경을 보유하였습니다. 하지만 스몰토크는 C++의 효율성을 가지지 못했고, 기존의 개발자들이 사용하는 방식을 따르지 않았습니다. 스몰토크는 여전히 특정한 계층에 인기를 끌고 있는 언어로 남아있습니다. 현재는 Objective C와 Eiffel과 같이 특성이 있는 언어가 몇 개 남아있습니다.


자바


현재 가장 인기 있는 언어는 자바입니다. 자바는 객체 지향 언어로 개발되었지만 스몰토크와는 다른점을 가지고 있습니다. 자바는 기본 데이터 유형에 대해 좀 더 실용적인 접근방법을 취하고 있습니다. 자바는 어떤 플랫폼에서든 실행이 가능하고 자바 가상 머신에서 실행이 되는 바이트코드라 불리는 중간 언어로 컴파일 합니다. 이는 컴파일된 결과를 이용하여 서로 다른 컴퓨터에서도 실행이 가능함을 나타냅니다. 자바는 급속으로 확장되는 대규모 표준 클래스 라이브러리와 함께 제공됩니다. 하지만 자바의 단점은 성능이 느리다는 점입니다. 


Visual Basic


Visual Basic은 일반적으로 객체지향 언어로 구분되지 않습니다. 그러나 사실 최신 버전에서는 객체 지향 언어의 일부분을 가지고 있습니다. Visual Basic 객체 모델은 마이크로소프트 컴포넌트 오브젝트 모델과 깊게 연관되어 있고, COM 환경에서 COM 객체를 쓰거나 생성에 아주 잘 동작을 합니다. Visual Basic은 기본적으로 인터프리터 기반의 언어지만 이후 버전은 컴파일 코드를 생성할 수 있습니다. 이 언어는 프로그래밍 하기 매우 쉽습니다. Visual Basic의 새로운 버전인 Visual Basic.NET은 완벽한 객체지향 언어이고 C#과 같은 객체 모델을 준수합니다. 


C#


C++, 스몰토크, 자바, Visual Basic의 장점을 결합한 C#은 완벽한 객체지향 언어이며 Java에 가까운 언어입니다. .NET 환경의 기본적인 구조는 CLR이라 불리는 가상 머신에서 중간언어를 통해 실행하는 것은 바이트코드를 실행하는 자바 환경과 동일합니다. 그러나 C#은 몇 개의 주요 개선사항이 포함되어 있습니다. 가장 중요한 것은 스몰토크로부터 가져온 모든 것은 객체이다 라는 개념입니다. 이는 언어의 사용을 단순히 하여 숫자를 객체와 같이 처리하게 하고, Collection에 저장할 수도 있게끔 만들어 줍니다. 그러나 스몰토크가 가진 성능에 대한 문제점을 보완을 하였습니다. 


C#은 박싱과 언박싱에 대한 개념을 가지고 있어 박싱을 통해 숫자를 객체로 변경하고, 언박싱을 통해 객체를 다시 숫자로 변경할 수 있습니다. 그러나 객체로 사용할 필요가 없는 숫자는 단순 값으로 처리되게 효율적으로 사용이 가능합니다. C#의 다른 혁신적인 점은 이를 컴포넌트 기반으로 처리하게끔 지원한다는 점입니다. 


6. 컴포넌트


몇 년 전 BYTE라는 잡지에서 객체 지향 프로그래밍은 죽었는가에 대한 내용을 커버 스토리로 다룬 적이 있습니다. 다양한 방식으로 그들은 객체에 대한 과대광고의 부응하지 않는 점을 나타냈습니다. 사람들은 객체의 코드 재사용을 어떻게 촉진하는지에 대해서 이야기를 하였습니다. 사실 객체는 하드웨어의 칩과 비교가 되어왔습니다. 소프트웨어 객체로 인해 하드웨어와 비슷하게 재사용을 하게끔 원하였지만, 재사용은 일어나지 않았습니다. 


한편 마이크로소프트는 윈도우 어플리케이션을 쉽게 만들 수 있는 Visual Basic이라 불리는 언어를 개발하였습니다. 이 언어의 접근 방식의 핵심은 다양한 그래픽 사용자 인터페이스 요소나 TextBox와 같은 컨트롤을 폼에 그리는 것입니다. 이러한 다양한 컨트롤들은 이벤트와 관련된 Handle을 처리하기 위해서 약간의 코드만 추가를 하면 됩니다. 처음부터 마이크로소프트는 내장된 컨트롤이 Visual Basic 개발자의 요구를 충분히 만족시키기는 어렵다고 인식하고 있었습니다. 그래서 마이크로소프트는 VBX(Visual Basic Extension) 사용자 컨트롤이라는 내용을 정의하였습니다. VBX는 VB 개발 환경에 포함될 수 있고, 기존에 있던 내장 컨트롤처럼 사용할 수 있지만 특수 기능을 수행할 수 있습니다. 기존의 컨트롤처럼 VBX는 VB 코드로 인해 처리되는 이벤트를 설정할 수 있는 프로퍼티를 가지고 있습니다. 

VBX가 발표되자, 소프트웨어 벤더들은 수천개의 VBX를 개발하고 판매하였습니다. VBX는 간단한 위젯을 제공하거나, 윈도우 소켓과 같은 복잡한 기능을 수행할 수도 있습니다. 어떠한 VBX는 Visual Basic 프로그램에 쉽게 적용할 수도 있습니다. 


BYTE의 글에서 재사용을 위해 구현된 어떤 객체들보다 VBX가 성공적이라고 평가하였습니다. 이 기사는 많은 객체 지향 커뮤니티에 영향을 미쳤습니다. VBX는 함수의 개념 및 상속과 다형성 등을 제공하지 않아 진정한 객체지향은 아니지만, 재사용성이 뛰어났습니다. 이로인해 상업적으로도 성공할 수 있었습니다. 


VBX는 소프트웨어 컴포넌트의 하나의 예로 생각할 수 있습니다. 소프트웨어 컴포넌트는 다른 어플리케이션에 쉽게 적용할 수 있는 바이너리 코드의 하나로 생각할 수 있습니다. .


C# 과 컴포넌트


클래스 기반의 객체지향을 지원하기에 앞서, C#은 컴포넌트 기반 언어로 디자인되었습니다. C#의 프로퍼티, 메소드, 이벤트들은 언어에서 바로 지원이 됩니다. 이는 Visual Basic 환경에서 가지는 특성을 바로 적용할 수 있는 쉬운 컴포넌트 생성을 가능하게 해줍니다. Visual Studio. NET의 RAD 특성과 결합을 하게 되면 C# 개발은 Visual Baisc의 개발 속도와 편이성보다 더 높은 이점을 가질 수 있습니다. C#은 완벽히 객체지향 언어입이기 때문에 C#은 매우 강력한 언어입니다. 


* 객체지향 언어와 컴포넌트에 대한 내용은 저자의 책에서부터 가져온 것입니다. 이 책은 Prentice Hall에서 2000년에 출판한 Understanding and Programming COM+입니다. 


이 글이 도움이 되셨나요? 그렇다면 아래의 그림을 클릭해주세요.



댓글