현실과 소프트웨어 세계에서의 객체

우리는 현실에서는 객체의 세계, 소프트웨어 세계에서는 객체지향의 세계에서 살고 있다고 해도 과언이 아니다.

현실에서의 객체란 독립적이면서 (분리되지 않고) 하나로 취급되는 인식의 단위를 말한다. 인간은 대상을 정확히 인식하기 위해서 목적한 대상과 다른 대상들과의 개념적인 차이들을 필요로 하고, 그 차이들이 명확해지고 나면 그 대상에 대해 명칭을 부여한다. 이 과정을 통해 불분명했던 대상은 정확한 명칭을 지닌 객체가 된다. 우리의 인식 속에서 일단 객체로 자리잡은 대상은 고유한 인식적 위치를 점유하게 되고 이는 다른 대상을 판별하는데 이용됨으로써 인식의 세계가 점점 더 넓어지는데 일조하게 된다. 대상을 다른 대상들과 분리하여 인식하는 이와 같은 방식은 현실에서의 인간이 살아가는데 큰 도움을 준다.

근본적으로 프로그래밍 언어로서의 객체지향 개념은 위에서 본 현실에서의 객체에 대한 인식과 크게 다르지 않다. 프로그래밍 언어의 세계는 관념적인 세계이다. 인간은 현실을 객체 단위로 이해하고 있지만 실제 세계는 객체적인 세계가 아니다. 개와 고양이는 (관념적으로는) 같은 동물이긴 하지만 개와 고양이는 같은 개념으로 묶을 수 있는 단위가 아니다. 하지만 우리의 두뇌는 현실을 관념적으로 파악하기 때문에 거리낌 없이 개와 고양이를 묶어 동물이라고 부른다. 그리고 아이러니하게도 이렇게 비현실적인 관념으로 세계를 파악하는 방식이 전체를 분리하지 않은 체 이해하는 방식보다 거의 언제나 더 유용하다. 유용하다는 말은 더 빠르고 정확하게 이해할 수 있다는 말이다. 따라서 프로그래밍 언어에 객체지향이라는 개념이 도입된 이유는 인간이 객체를 중심으로 프로그래밍을 하는 편이 더 빠르고 정확하게 이해하면서 구현하는 것이 가능하기 때문이다. 이 점은 매우 중요한데, 프로그래밍의 도구는 오직 두뇌 뿐이고, 두뇌가 더 빠르고 정확하게 문제를 이해하는 것은 프로그래밍에 그만큼 유리하게 작용하기 때문이다.

2016년 6월 기준으로 Java, C++, Python, C#, PHP, Javascript, Ruby, Objective-C 등과 같이 굵직한 언어들 중에서 객체지향을 온전히, 혹은 상당 부분 지원하는 언어의 비중을 따져보면 약 44.5%를 차지했다. 만약 하드웨어적인 제약 사항을 만족시키기 위한 언어(C, Assembly)나 제한된 목적을 위한 언어(Cobol, Matlab, Delphi, Visual Basic 등)를 제외한다면 범용적이고 일반적인 어플리케이션의 대부분은 객체지향 언어로 만들어진다고 볼 수 있을 것이다.


프로그래밍 언어의 역사와 객체지향

우리가 현실 세계를 객체로 이해하고 있다는 점을 이해한다면 객체지향 언어가 프로그래밍 언어 영역에 도입된 시기는 매우 빨랐을 것으로 추측할 수 있다. 실제로도 그렇다. 이반 서덜랜드(1938~)는 1963년도에 "스케치패드 : 사람과 기계와의 그래픽 대화 시스템"이라는 논문을 통해 객체지향 개념을 기반으로 구현한 그래픽 프로그램을 발표한다.("누가 소프트웨어의 심장을 만들었는가") 이후 시뮬라67 언어가 만들어지고(1967), 앨런 케이에 의해 스몰 토크라는 언어가 만들어짐으로써 온전한 객체지향 언어가 탄생하게 된다. 시기적으로 보면 현대에 가장 많이 사용되고 있는 비 객체지향 언어인 C 언어가 1972년에 만들어졌으니 객체지향 언어는 완성된 비 객체지향 언어보다도 개념적으로 더 오랜 역사를 가지고 있는 셈이다.

하지만 이율배반적이게도 많은 사람들이 객체지향 언어를 접한 시기는 상대적으로 최근의 일이다. 여기에는 여러가지 이유가 있다. 첫째 객체지향 언어는 컴퓨팅 파워가 뒤쳐졌던 70년대에는 다른 언어들에 비해 상대적으로 비인기 언어였다. 낮은 하드웨어 성능을 최대한 끌어낼 수 있는 절차지향 언어가 먼저 인기를 끌었다. 둘째, 우리에게는 객체를 중심으로 현실을 이해하는 것 만큼 익숙한 이해의 방식이 하나 더 있기 때문이다. 이것은 어떤 문제(또는 일)를 시간과 인과 관계의 순서로 이해하는 방식이다. "처음엔 A였다가 B라는 이유로 C가 되었다가 결국엔 D로 끝났어"와 같은 서술 방식은 시간과 공간 속에서 살아가는 인간에게 매우 익숙한 상황 인식 및 설명의 방식이다. 이러한 방식을 프로그래밍 언어에 도입한 것이 절차지향 언어이다. 첫번째 이유로 인해 기피되던 객체지향 프로그래밍 방식이 초반부터 매우 강력한 경쟁자를 만난 셈이다.

세번째 이유는 객체지향 언어를 이해하는 것이 절차지향 언어에 비해 상대적으로 어렵다는 점이다. 객체를 중심으로 이해하는 것이 현실을 이해하는데 유용하다는 점에서 볼 때는 매우 아이러니한 일이 아닐 수 없다. 우리는 매우 자연스럽게 세계를 객체 중심으로 이해한다. 이 과정은 너무나도 자연스럽기 때문에 그 메커니즘에 대해서는 잘 인지하지 못한다. 우리는 개와 고양이를 개와 고양이라고 부르면서 구분하고 있고, 동시에 동물이라는 카테고리 안에 이 둘을 자연스럽게 포함시킨다. 또 동물과 식물을 구분하고 있으면서 동시에 생물이라는 카테고리 안에 이 둘을 포함시킨다. 이것을 그림으로 그리면 트리 구조가 될 것이다. 하지만 우리는 이러한 구분을 트리 구조를 통해서 이해하고 있지 않다. 그냥 자연스럽게 그 인식 과정을 받아들인다. 하지만 이러한 메커니즘을 모사하여 프로그래밍 언어에 도입하는 과정은 그다지 순탄하지 않다. 개와 고양이를 구분하려면 개를 개념적으로 명확하게 정의하고 고양이를 개념적으로 명확하게 정의할 수 있어야 한다. 그리고 이들 둘을 동물이라는 같은 개념으로 묶을 수 있으려면 두 동물이 가진 개념 중에서 공통점을 추출할 수 있어야 한다. 또한 동물의 특성을 개와 고양이가 가질 수 있게 하려면 상속이라는 개념을 도입해야 하고, 동물이라는 개념으로 개와 고양이를 다룰 수 있으려면 다형성이라는 개념을 도입해야 한다. 요컨데 인간의 두뇌가 현실을 이해하는데는 엄밀한 정의도 필요하지 않고, 전체적인 논리적 완결성을 추구할 필요가 없지만 이를 매우 논리적인 완결성을 요구하는 프로그래밍 언어에 도입하는 데에는 다양한 개념의 정립이 필요하다.


객체지향이 대두된 이유

그렇다면 절차지향 언어가 계속 우위에 설 수도 있었을텐데 객체지향 언어는 왜 다시 대두되었고, 현재와 같은 주류 언어가 될 수 있었을까?

기초적이고 단편적인 이유들을 먼저 설명해 보자. 첫째로 컴퓨터의 연산 능력이 좋아졌다는 점이다. 객체지향 언어가 생겨난 70년대 이후 수십년에 걸쳐 하드웨어는 비약적인 발전을 거듭해 왔다. 그리고 하드웨어적/소프트웨어적 발전으로 인하여 하드웨어는 단일한 플랫폼을 넘어서 병렬화되면서 성능은 더더욱 좋아지게 되었다. 이것은 상대적으로 연산량을 많이 필요로 하는 객체지향 언어가 활동할 수 있게 된 배경이 된다. 둘째로 절차지향 언어의 한계점이 대두되었기 때문이다. 앞서 말했듯이 절차지향 언어는 시간과 공간 상에서의 인과 관계를 중심으로 현실을 이해하는 인간의 인식 방식을 모방한 것이기 때문에 이해하기 쉽고 다루기 쉬운 프로그래밍 언어이다. 하지만 절차지향 언어로 개발된 소프트웨어는 어느 일부분을 떼어 내어 다른 소프트웨어를 만드는 것이 어렵다. 절차지향 언어가 함수라는 독립된 단위로 소프트웨어를 분할하고 있지만 각 함수는 연쇄적으로 호출되면서 동작하기 때문에 어떤 부분만을 별도로 나누어 다른 시스템에 적용시키기가 어렵다. 또한 절차 전체에서 메모리를 공유하거나, 특정 절차가 어떤 데이터와 연관되는지를 쉽게 알 수 없기 때문에 전체 동작을 이해하기 위해서는 각 절차들의 내부를 자주 들여다 봐야 되고, 이런 방식으로는 큰 소프트웨어를 작성하기가 어려워진다.

하지만 보다 근본적인 이유는 따로 있다. 1930년대 후반에 소위 "컴퓨터"라는 것이 발명된 직후, 컴퓨터의 용도는 주로 암호 해독이었다. 일련의 덧셈, 뺄셈, 곱셈, 나눗셈 등을 이용하여 인코딩된 정보를 디코딩하는 용도라고 할 수 있다. 1940년대에는 군사 분야쪽으로 용도가 넓어진다. 포탄 궤적용 표, 폭발 계산(원자폭탄 개발), 탄도 미사일 계산과 같이 군사 물리적인 용도가 주를 이루었다. 1950년대에는 FORTRAN 언어가 개발되면서 과학 연구 분야에 컴퓨터가 활용되기 시작한다. 초신성 폭발, 수치해석, 일기예보 등이 그 예이다. 1960년대에는 운영체제와 COBOL 언어가 등장함으로써 고등 제조 기술 분야와 비즈니스 분야에 소프트웨어가 활용된다. 항공기 설계(특히 엔진 설계), 우주선의 제작 및 우주선 궤도 계산 분야, 비즈니스 소프트웨어 분야에 활용되었다. 1970년대에 이르러서는 PC가 출현하고 유저 인터페이스 및 인터넷이 탄생한다. 이와 함께 PC용 소프트웨어가 개발되면서 소프트웨어는 산업 전반에 걸쳐 사용된다. 애플I이 개발된 것이 1976년의 일이다. 1980년대는 PC 시대가 활짝 열리게 된다. MS-DOS가 발명되고(1981), PC의 대중화를 주도한 맥킨토시(1984)가 발명된 것도 이 시기이다. 특히 맥킨토시는 최초의 GUI와 마우스를 채용함으로써 그래픽 기반의 소프트웨어 시대를 열었다. 1990년대는 뭐니뭐니해도 WWW, 즉 월드 와이드 웹의 시대이다. HTML과 웹 브라우저로 인하여 전 세계의 컴퓨터가 서로 정보를 주고 받을 수 있는 세상이 되었다. 이로 인하여 소프트웨어는 닫힌 공간을 위한 용도에서 연결된 공간을 위한 용도로 활용되게 된다. 2000년대는 소셜 네트워크 및 집단 지성의 시대이다. 이 시기에 구글이 기존과는 완전히 다른 개념의 검색 기술을 개발(2003)하였고, Wikipidia(2001)와 같이 집단 지성을 활용하는 시대가 되었다. Facebook(2004)은 SNS의 시대를 열었고, 아이폰(2007)은 이 연결을 통한 가치 창출을 모바일의 영역으로 확대하였다. 2010년대는 빅데이터와 인공지능의 시대이다. IBM은 왓슨(2011)을 통해 빅데이터 기반으로 훈련된 인공지능을 선보였고, 2016년에는 이세돌과 알파고의 대결을 통해 인간의 능력을 넘보는 인공지능의 시대가 시작되었다.

소프트웨어의 역사에서 가장 주목할만한 것은 소프트웨어 활용 영역이 지속적으로 확대 되었다는 점이다. 소프트웨어는 컴퓨터의 초기부터 지금까지 그 적용 분야가 계속 확대되어 왔다. 그러면 이제부터는 그 적용 분야가 점차 축소될 것인가? 인공지능 분야는 현재 제한적인 부분에서만 인간의 능력을 뛰어 넘는 수준에 머물러 있지만 앞으로 적어도 모든 분야에서 인간의 능력을 뛰어넘기 전까지는 계속 발전하게 될 것이다. 이를 위해서는 더 많은 정보가 수집되어 분석되어야 한다. 당연히 데이터는 계속 수집될 것이고, 인간의 능력을 뛰어넘는 분야는 점점 넓어질 것이다. 사람들이 가지고 있는 모든 지식과 컴퓨터 뿐만 아니라 모든 센서가 연결되고 그 데이터가 수집될 때까지 이 과정은 지속될지 모른다. 즉, 소프트웨어는 적용 분야, 크기, 연산량이 확대되는 방향으로 발전해 갈 수 밖에 없다.

이 과정에서 소프트웨어가 갖추어야 할 기능의 필요성, 즉 요구사항의 증가는 필연적이다. 요구사항은 계속 증가한다. 단순히 양만 증가하는게 아니고 적용 분야가 증가하면서 종류도 다양해진다. 또한 소프트웨어와 인간이 만나는 횟수가 증가하면서 요구사항은 점점 더 다양해지고 또 자주 바뀌게 된다. 개별적인 인간의 개성이나 변덕의 수준을 맞추기 위해서는 소프트웨어가 더 많이 바뀌고 더 자주 바뀌고 더 빨리 바뀔 수 있어야 한다. 이렇게 잘 바뀌는 특성, 즉 유연성(flexibility)이 소프트웨어의 최고 덕목이 된다. 그래서 프로그래밍 언어 중에서도 가장 유연성이 뛰어난 객체지향 언어가 새로운 강자로 떠오르게 된 것이다.


소프트웨어가 가져야 할 가치

TDD, xUnit 테스트, 애자일의 창시자로 유명한 소프트웨어 프로그래머 켄트 벡은 "켄트 벡의 구현 패턴"에서 소프트웨어가 가져야 할 가치를 유연성, 단순성, 커뮤니케이션으로 정의하였다. 커뮤니케이션은 갈수록 커져가는 소프트웨어의 규모를 맞추기 위해서는 여러 사람들의 협력이 필요하고, 이를 위해서는 소프트웨어가 자기 스스로를 설명할 수 있는 능력, 즉 커뮤니케이션 도구로서의 기능을 가져야 한다. 또한 사용자의 요구사항은 예측이 불가능하게 변화하거나 추가되기 때문에 소프트웨어는 유연성을 꼭 가져야만 한다. 이들 덕목을 갖추면서도 기능을 구현하는 가장 단순한 방법을 추구하는 단순성을 가지고 있어야 한다.

이들 중에서 소프트웨어의 유연성은 소프트웨어의 존재 이유에 해당하는 가치라고 볼 수 있다. 소프트웨어는 하드웨어와 같은 다른 요소가 감당하지 못하는 기능 변경 요구사항을 수용하기 위해서 만들어진 요소이다. 이로 인하여 소프트웨어의 생애 주기 중 대부분은 수정과 개선 기간이 된다. 로버트 L. 글래스는 (우리가 미처 알지 못한) 소프트웨어 공학의 사실과 오해라는 책을 통해서 소프트웨어의 유지보수가 보통 소프트웨어 비용의 40~80%를 차지한다고 말한다. 이와 함께 60/60 법칙을 제시하는데 소프트웨어 비용의 60%는 유지보수에 사용되고, 유지보수 비용의 60%는 소프트웨어 기능의 개선을 위해 사용된다고 한다. 이는 소프트웨어가 얼마나 자주 변경되는지, 요구사항이 얼마나 자주 바뀌는지를 말해준다. 더불어 유연성이 소프트웨어의 가치 중에서 얼마나 큰 비중을 차지하는지를 알 수 있게 해준다.

객체지향은 소프트웨어의 유연성이라는 측면에서 가장 뛰어난 접근 방식이다. 객체지향 언어는 소프트웨어에 새로운 기능을 추가하거나 기존의 기능을 변경하는 것, 또는 더 이상 필요 없는 기능을 제거하는 유지 보수 작업에 가장 유리한 언어이다. 다음 글에서는 객체지향 언어가 이 유연성을 어떻게 확보하는지를 알아보겠다.

Posted by 이세영2
,