객체지향에서 Class 의 존재는 매우 중요하다. inheritance(상속성), encapsulate(캡슐화), polymorphism(다형성) 의 세가지로 대표되는 객체지향의 특성은 대부분의 객체지향 언어에서 제공하는 Class 에 포함되어 있다. 사실 살펴보고 싶은것은 너무나 잘 알려진 앞의 3가지 특성이 아니라 Class 와 instance 의 관계에 대한 것이다.
당신은 Class 를 무엇이라고 생각하는가? 우리는 Class 를 무엇이라고 정의할 수 있을까? Prototype?(물론 패턴이름을 말하는것은 아니다). 또는 어떠한것의 원형(Orign) 이라고 생각할 수도 있을지 모른다. 또는 과자등을 찍어내기 위한 형틀에 가까운 무언가일지도 모른다.
약간 다른 얘기가 되겠지만 조금 옆길로 새보도록 하자. 컵을 공산품으로 만들기 위한 과정을 고민해보자. 일단 컵의 원형부터 먼저 만들어야 할 것이다. 그리고 시행착오를 거쳐 대량생산이 가능한 형태로 다듬어야 공산품으로서는 쓸만할 것이다. 이렇게 하나의 컵이 만들어지게 되면 생산을 위한 준비과정으로 들어가야 한다. 만들어진 시험작을 이용해서 형틀을 만들것이다. 그리고 만들어진 형틀을 이용해서 생산설비를 만들것이다. 만들어진 설비를 이용해서 생산을 시작하면 된다. 물론 필요한 수량만큼 생산을 해야 낭비가 없을것이다.
다시 본론으로 돌아와서 Computer Software 의 범용적 특징을 되새겨보도록 하자(물론 특별한 조건등은 그다지 고민하지 않기로 한다). File(또는 software)는 일반적인 경우 원래의 위치에서 다른위치(같은 물리적 disk내의 다른위치일수도 있다)로 복사(copy) 작업을 진행하는 경우 원본의 내부 또는 외부가 전혀 손상되지 않는다. 원본과 그대로 같은 내용의(inode 또는 생성일등은 틀려질 수 있겠지만) 복제품이 만들어 지는 것이다. 이렇게 만들어진 복제품은 완전히 원본과 동일한 동작을 하게된다. 이런 복사작업은 저장 미디어 뿐만이 아니라 로딩된 물리메모리에서도 동일한 개념으로 동작하게 된다.
Class 는 어떠한 객체를 생성하는 형틀의 역할을 한다. 그 자체로도 필요한 기능을 가지고 사용될 수도 있지만 Class 와 꼭 닮은 객체를 만드는데로 사용될 수 있다. 자루까지 쇠로 만들어진 튼튼한 망치정도면 적당한 비유가 될까? 망치로서의 용도도 충분히 가지고 있지만 그 자체로 다른 망치를 만들어내는 원형(prototype)의 역할도 할 수 있다. 물론 Computer 의 세계는 실제 세계보다는 좀 더 논리적인 개념하에서 동작하지만…
이렇게 원형이 되는 경우를 Class 라고 하며 이를 이용해서 생성된 결과물의 존재를 객체(Obejct) 또는 인스턴스(instance) 라고 한다. 이렇게 instance 를 찍어내는 Class 는 그 스스로 무언가를 생성하는것과 비슷한 동작을 하게 된다. 이런 일련의 과정을 짚어보면 Class 를 공장(Factory)라고 볼 수도 있을 것이다. 그럼 이런 과정들을 위해 만들어진 Class 들을 뜯어서 다시 손보고 개량하는 작업은 어떻게 불러야 할까? 그렇다. 답은 명료하다. 바로 “refactoring” 이다. 필자는 이러한 내용들이 refactoring 을 설명하는 대에 대한 가장 정확한 답이라고 확신한다.
instance 를 취급하는 방법은 각 환경에 따라 다르다. compiler 는 class 를 통해서 instance 를 생성할때 real memory(protected) 에 생성되는 포인터(pointer) 로서 이것을 취급한다. 물론 compiler 는 interperter 가 아니기 때문에, 이러한 동작들은 binary 가 실행되는 시점(runtime) 에 진행되게 된다.
Virtual Machine 의 대표격인 smalltalk 에서는 instance 의 생성작업은 좀 더 복잡한 동작을 가지게 된다. 근래에 가장 유명한 Smalltalk 구현체인 Pharo(CogVM) 을 예로 들어보자. CogVM 을 실행하면 주어진 인자(argument)에 따라 Smalltalk image 를 로딩한다. 이때 Smalltalk image 안의 모든 class 를 로딩해서 unique instance 로 메모리에 생성한다(물론 image 의 동작에는 이런 부분이 snapshot 형태로 포함되어 있기도 하지만.. 이런 부분은 논외로 한다). smalltalk 의 Class Browser(nautilus)에서 보이는 모든 class 는 사실 unique instance 를 이미 가지고 있다고 보는것이 맞다. class side 의 메서드(Method)를 사용하는 경우라면, 내부에서는 Class 에 대응되는 unique instance 를 통해서 해당 메서드를 실행하게 된다. 물론 Class 를 이용해서 instance 를 생성하게 되면 unique instance 와는 전혀다른 새로운 instance 를 생성하게 되는데, 이때 바탕이 되는 class 의 생성자(creator)를 이용하기 위해서는 Class 에 대응되는 unique instance 의 생성자 메서드를 이용하게 된다. 대부분의 Smalltalk Systam 은 재념적으로 비슷한 동작을 하도록 구성되어 있다.
이번 내용은 조금 긴 내용이 되었지만, 요점은 다음과 같다.
* Class == Factory
* sintance == Class 의 전사체
* class 로 만들어진 library 를 정리하는 작업 == refactoring
* Virtual Machine 환경과 Compiler 언어의 instance 취급방법에는 차이가 있다.
이렇듯 class 와 instance 의 개념을 좀 더 숙지하고 나면 이후 객체지향을 이해하는데 좀 더 도움이 될 것이다.