우리가 C언어로 프로그래밍을 할 때와 Java나 JavaScript, Python 등의 언어로 프로그래밍을 할 때는 고민해야 하는 부분이 다릅니다.  여기서 생각해야 할 점은 무엇이 더 좋고, 무엇이 더 어렵다는 관점이 아니라, 각 언어를 가지고 프로그래밍을 구현 하는 방법이 다르다는 의미입니다. C 언어는 절차지향 언어라고 합니다. 그래서 시간의 흐름과 일의 절차에 따라 프로그래밍을 하는 것이 중요합니다. 프로그래밍 중에 반복적이고, 재활용 가능한 부분을 함수나  라이브러리로 만들어 추후 다른 프로그램에서도 사용할 수 있도록 효율성을 높입니다. 

Java와 같은 객체 지향 언어는 객체에 기반 하여 프로그래밍을 합니다. 여기서 객체라는 것은 프로그래밍의 대상이라고 할 수 있습니다. ‘프로그램에 무슨 대상이 있을까?’ 라는 생각이 들겠죠? 가령 다음과 같은 상황을 생각해보도록 하죠

42SEOUL 학생들의 일과에 대한 프로그램을 한다고 해보겠습니다. 절차지향 프로그래밍으로 구현을 한다면 시간의 순서에 따라 프로그램을 합니다. 학생들이 클러스터에 대중교통으로 오고, 과제나 공부를 하고, 중간에 식사를 하고 집으로 돌아갑니다. 이때 매일 반복적으로 일어나는 이들을 함수로 모듈화 한다면 호출해서 사용할 수 있겠죠. 식사를 점심이나 저녁을 식사 같은 경우는 식사 함수에 매개 변수로 시간대 넣어 처리할 수 있습니다. 

같은 내용을 객체 지향프로그래밍으로 구현을 한다면 일단 프로그래밍의 대상을 생각해볼 수 있습니다. 즉, 객체가 될 수 있는데요 여기서 객체는 카뎃, 클러스터, 과제, 대중교통, 식사 등등이 될수 있습니다. (명사를 주로 이야기 했지만, 동사형 명사도 많이 있습니다. 쇼핑몰에서 주문, 배송… 등이 그 예가 되죠) 그리고 각 객체는 프로그램에서 클래스로 구현합니다. 이번에는 각 객체가 해야 하는 일들을 생각해 봅니다. 객체가 하는 일은 객체의 기능이고, 곧 클래스 내의 메서드로 구현합니다. 카뎃의 경우에는 클러스터에 출입을 하고, 과제를 하고, 식사를 하겠죠. 그렇게 할때 다른 객체와의 협력(cooperation)이 발생하게 됩니다. 또한 각 객체는 그 속성을 가지게 되는데 카뎃의 경우는 카뎃아이디, 기수, 과제 레벨 등등이 그 속성이 될것이고, 이는 카뎃의 메서드를 구현할 때 사용됩니다.  이렇듯 객체 지향 프로그래밍은 객체를 정의 하고, 그 속성(멤버 변수)과 기능(메서드)를 구현합니다. 그리고 객체간의 협력을 통하여 구현합니다. 클래스가 다른 클래스를 포함할 수도 있고, 다른 클래스의 매개 변수로 넘길 수도 있고, 상속을 받을 수도 있습니다. 

각 다른 특성을 가지는 언어는 그 나름의 장점이 있습니다. 절차지향 언어로 C언어와 객체지향 언어로 JAVA 언어를 생각해보죠.

개인마다 조금씩 다를 수 있지만, 제가 생각하는 C 언어를 공부하는데 있어서의 핵심은 함수와 포인터라 봅니다. 함수와 포인터만 잘 활용할 줄 알면 능숙한 C프로그래머가 될 수 있습니다. C언어는 특히 함수가 중요합니다. 함수를 잘 분리하고 라이브러리로 잘 구현해놓으면 여러 곳에서 잘 활용할 수 있습니다. 통신프로그램 같은 경우 통신에 쓰는 라이브러리를 잘 구현해 놓으면 추후 채팅 프로그래밍이나 스트리밍 프로그래밍 등에서 잘 활용할 수 있습니다. 또한 포인터에 대한 이해가 아주 중요합니다. 포인터란 메모리의 주소를 가지는 변수입니다.  따라서 포인터를 가진다는건 직접 그 메모리에 접근하여 처리한다는 의미입니다. C 언어에서 포인터는 변수, 배열, 구조체, 또다른 포인터, 함수도 접근할 수 있습니다. 따라서 포인터만 잘 활용하면 굉장히 빠르고 효율적인 구현을 할 수 있습니다. (C++ 에서도 마찬가지입니다) 다만, 메모리를 직접 접근하다 보면 예기치 않은 오류(error, exception)와 중단(abort) 종종 만나긴 합니다(ㅎㅎㅎ)

자바 언어는 이러한 C, C++ 언어의 효율성보다는 안전성을 추구한 언어입니다. 단순히 문법적으로만 보면 C와 가장 큰 차이는 포인터를 사용하지 않는다는 점일 수 있습니다. 즉 메모리를 직접 접근하여 프로그래밍 할 수 없습니다. 이 외에서 예외 처리라던가 다중상속등 C, C++ 언어에서 발생할 수 있는 모호함과 불안정성을 많이 제거했습니다.  그리고 객체지향 프로그래밍 언어죠. 앞에서 예처럼 클래스를 정의하고 클래스의 속성을 정의하고 기능을 구현합니다. 

최근에 많은 개발 언어들이 Object Oriented Programming Language 이거나 Object Oriented Programming Influenced Language 인 이유는 무엇일까요? 

우리가 개발하는 서비스나 프로그램은 한 번 개발했다고 계속 사용되는 것이 아닙니다. 버그 수정은 물론이고, 추가적인 요구사항의 변화 기능추가등이 발생하게 됩니다. 그럼 프로그램은 수정해야 하는데 수정에는 비용이 들어가게 되는것이죠 되도록이면 기능 추가나 수정에 드는 비용이 적게 개발하는 것이 확장성(extensible)이 좋고 유지보수(maintenance)가 편하며 유연한(flexible) 프로그램이 되는 것입니다.  객체지향 프로그래밍 이 추구하는 부분은 이러한 부분입니다. 추가적인 요구사항과 기능 수정에 대해 유연하게 변화 할 수 있는 프로그램을 설계하고 개발하는 것이지요

제가 자주 드는 예 중 DataBase 관련하여 생각해 보겠습니다. 만약 어느 회사에서 ORACLE DB 기반으로 솔루션을 개발하였습니다. 추후 고객사가 새로 생겨서 솔루션을 설치하러 갔더니 DB를 MS SQL로 바꿔 달라고 할 수 있습니다. 만약 DB transaction 처리 하는 부분을 구체적인 클래스가 아닌 인터페이스를 활용하여 개발하였다면 같은 인터페이스에 선언된 기능들을 MS SQL 클래스로 개발하고 교체하여 수정 할 수 있습니다. 물론 많은 쿼리문을 새로 만들어야 하는 수고로움은 있지만, 모든 소스를 다 고칠 필요는 없습니다.  소스 관리도 두 개의 버젼을 용이하게 할 수 있습니다.

잘 설계된 객체지향 프로그램은 프로그램을 수정하고 확장하는데 필요한 시간관 노력(비용이라고 하죠)을 많이 줄일 수 있는 장점이 있기때문에 지금도 현업에서 많이 사용되고 있습니다. 그렇지만 객체지향 설계를 잘 한다는 것은 많은 경험과 노력과 시행착오가 필요한 부분입니다.  

그럼 다음에는 어떤 설계와 어떤 구조가 객체지향 프로그래밍 다운 방향인지 알아보도록 하겠습니다.