제공 : 한빛 네트워크
저자 : 문우식
출처 : Blog2Book, 패턴 그리고 객체지향적 코딩의 법칙
개발팀에 새로 합류한 신입사원 나초보씨는 어느 날 팀장으로부터 간단한 계산 모듈을 만들라는 지시를 받았다. 팀장은 객체지향으로 개발하라는 당부의 말도 잊지 않았는데, C밖에 모르는 나초보씨는 고민에 빠졌다. 간단한 모듈이라서 익숙한 C로 만들면 3일이면 될 것 같았기 때문이다. 하지만 팀장의 말도 있고 해서 일단 객체지향을 공부해 보기로 했다. 하지만 클래스를 비롯해서 C++만의 문법을 익히는 도중에도, 근본적으로 도대체 왜 C가 아닌 꼭 C++로 만들어야 하는지 나초보씨는 납득할 수가 없었다.
나초보 : C로 개발하면 안되나요?
팀장 : 객체지향으로 개발하는 것이 좋으니 C++로 만드세요.
나초보 : 아니 아무리 생각해도 함수가 동작하는 것은 똑같은데 왜 굳이 제가 익숙치
도 않은 C++을 사용해야 하는지 모르겠습니다. 또 제가 왜 객체지향을 공부
해야 하는지도 모르겠습니다.
팀장 : 나초보씨 뿐만 아니라 다른 팀원들도 C++로 개발하니 그냥 C++을 사용하는
것 입니다.
나초보 : 회사의 방침이기 때문에 C++을 사용해야 된다는 건가요?
팀장 : ......
나초보 : 회사의 방침이 아니라면 왜 굳이 제가 익숙치도 않은 C++로 개발해야 되는
건가요? C로 개발하면 안되나요?
나초보씨처럼 객체지향 때문에 한번쯤은 왜 구조적 프로그래밍 언어인 C가 아닌 객체지향 언어인 C++로 개발해야 하는가에 대해 근본적인 의문을 가져본 적이 있는가? 아무 생각 없이 많은 사람들이“객체지향이 대세다!”라고 외치기 때문에 막연히 좋은가보다 하며 유행을 따르다 보니 객체지향을 공부하는 것인가? C++이 C의 모든 기능을 포함한 언어의 확장이기 때문에 더 능숙하게 사용하면 폼나 보이기 때문일까? 왜 객체지향 개발 방법이 권장되고 있는지에 대해 현실적인 관점에서 알아보도록 하자.
의문점
모든 프로젝트를 한가지 언어만으로 개발할 수는 없다. 개발을 시작할 때 가장 먼저 결정해야 하는 일은 프로젝트 성격에 맞는 가장 적합한 언어를 선정하는 것이다. C/C++이 최고의 언어라며 Web Application을 개발하는데 ASP, PHP, JSP 등을 무시한 채 오로지 C-CGI(Common Gateway Interface)로 개발하는 것도 정답이 아니고 UI 중심이나 데이터베이스 관련 프로그램을 개발하면서 Visual Basic이나 Delphi, Power Builder등을 무시하는 행동도 또한 정답이 아니다.
언어를 선택하는 것이 우선이고 선택된 언어가 C/C++이라고 한다면 개발 방법을 C 중심으로 할 것인지 객체지향을 활용하기 위해 C++을 사용할 것인지 결정해야 한다. 이 대목에서 많은 개발자들은 자신에게 익숙한 언어를 먼저 염두에 두기 마련이다. C/C++을 모든 개발자가 능수능란하게 사용할 수 있다면 별 문제 아니겠지만 개발자마다 실력의 차이나 개발했었던 환경의 차이로 인해 C나 C++중 더 익숙한 환경이 있을 것이다(물론 가장 좋은 경우는 이 두 가지 모두 익숙한 경우이겠지만 말이다).
단순히 팀이나 회사의 방침이 객체지향 개발이기 때문에 익숙하지도 않은 객체지향 언어를 공부하면서까지 개발해야 하는 것일까? 더 심각한 문제는 닥쳐서 공부를 한다고 해서 하루 아침에 객체지향에 능숙해지지 않는다는 점이다. 적지 않은 시간 동안 시행착오를 겪고 관련 공부를 많이 하고 나서야 객체지향에 능숙해 질 것이다. 이런 노력이 없다면 C++로 개발해도 C로 개발하는 것과는 별반 다를 바가 없을 것이다. 당장 내가 C로 잘 만들 수 있는데 왜 굳이 객체지향 언어인 C++, Java를 배워야 하는 걸까?
Why not?
정말 당신이 C에 능숙하다면 C로 개발하라. 안될 이유가 없지 않은가? 모든 팀원들이 C에 능숙하고 코드의 확장이나 유지 보수 그리고 배포에 문제가 없다면 C로 개발하는 것이 정답이다. 실제로 퍼포먼스(Performance) 면에서는 C가 더 빠르다.
많은 개발자들이 왜 C++로 개발하는 것이 C보다 좋은지 명확한 답을 내주지 못한다. 단순히“C++은 상속, 캡슐화, 다형성 그리고 그밖에 디자인 패턴으로 대변되는 여러 가지 유용한 테크닉이 존재하기 때문에 C++로 개발해야 한다”라고 이야기하는 것은 C++에 익숙해 지고 나서 활용에 관한 부분이고 우리는 보다 근본적인 대답이 필요하다. 테크닉은 테크닉일 뿐 결국 기본이 중요하다. 개발 방법의 기본은 아래와 같다.
- 개발을 체계적으로 진행할 수 있는가?
- 개발하기 쉬운가?
- 관리하기 쉬운가?
- 확장하기 쉬운가?
- 안정적인가?
하지만 C++이 등장하기 이전이나 지금이나 많은 프로젝트들이 C로 진행되고 있는 것이 사실이다. 또 대부분의 오픈 소스들이 대부분 C로 개발되는 것도 간과할 수 없는 사실이다.
이해를 돕기 위해 오픈 소스의 구체적인 예를 들어보자. 오픈 소스로 유명한 프로그램 중에 리눅스의 포토샵이라고 불리는 GIMP(GNU Image Manipulation Program의 약어)라는 프로그램이 있다. GIMP의 코드 중 일부를 잠깐 살펴보자.
gdouble gimp_brushes_get_opacity (void);
gboolean gimp_brushes_set_opacity (gdouble opacity);
gboolean gimp_brushes_set_paint_mode
(GimpLayerModeEffects paint_mode);
gboolean gimp_brushes_set_brush (const gchar *name);
GimpLayerModeEffects gimp_brushes_get_paint_mode (void);
위의 코드는 GIMP 2.2.14의 gimpbrushes.h파일의 함수 선언 내용 전부이다. 함수 선언 형태만 봐도 해당 함수가 어떤 기능을 수행하는지 또 어떤 범주에 속해 있는지 쉽게 감이 온다(GimpLayerModeEffects라는 구조체가 사용된다는 것도 알 수 있다. gdouble이나 gboolean과 같은 기본 타입들은 double이나 bool과 같은 의미로 이해하자). 아마 파일 이름을 몰라도 헤더 선언만 보고도 brush에 관한 함수라는 것을 알 수 있을 것이다. 당연히 gimpbrushes.h에 선언된 함수들은 gimpbrushes.c에 구현되어 있다.
누구나 GIMP소스를 본다면 언어를 떠나서 높은 가독성과 확장성에 놀랄 것이다(GIMP를 깊게 다루려고 하는 것은 아니다. 하지만 GIMP소스에 관심 있는 독자들은 GIMP홈페이지(http://www.gimp.org/에서 소스를 다운받아 볼 수 있다). 우리가 GIMP
의 예를 통해 이해해야 하는 점은 전 세계의 여러 개발자가 공동으로 작업하는 오픈소스가 마치 한 사람이 만든 것처럼 코드의 표기법을 비롯해 확장성 있는 소스의 구조와 높은 가독성을 가지고 있다는 점이다. 현실적으로 갓 개발에 입문한 새내기 개발자가 오픈 소스에 참여해서 세계적인 개발자들과 어깨를 나란히 하고 개발을 할 수 있을리 없다. 즉 이 정도 소스는 현실적으로 개발에 정통한 개발자들이 규칙을 정하고 그 규칙을 정확히 잘 지킬 수 있을 때 얻을 수 있다.
개발 현실은?
위에서 좋은 예로 GIMP를 언급했다. 하지만 실제로 C로 만들었어도 알아보기 힘든 소스가 많이 있다. 구조적 프로그래밍은 결국 데이터와 데이터 조작 이 두 단어로 표현할 수 있고 이는 C의 구조체와 함수로 표현할 수 있다. 구조체를 통해 메모리를 할당하고 함수를 통해 이 구조체 값을 변경하고 구조체 값에 기반해 원하는 기능을 수행한다. 하지만 익숙하지 않은 라이브러리나 생소한 코드를 접할 때 처음 부딪히는 문제는‘어떤 구조체를 사용해야 하는가’이다. 오픈 소스(Open Source)를 다운로드 받아 헤더를 열어 보니 너무나 많은 구조체가 존재한다. 이 중 과연 어떤 구조체를 사용해야 하는가는 알 수 없다. 다행히 샘플 코드를 참조해서 어떤 구조체를 중심으로 사용해야 하는지 알았다고 해도 아래와 같은 문제점이 있다.
- 수를 호출해야 되는가?
- 어떤 함수를 호출하면 안되는가?
- 구조체의 변수들은 어떻게 변경해야 하는가? 직접 혹은 함수를 통해서?
- 구조체 변수들이 의도되지 않게 변경됐을 때 프로그램은 어떻게 동작하는가?
Win32로 윈도우즈 프로그래밍을 해본 경험이 있는 독자라면 처음 윈도우를 띄우기 위해서 어떤 구조체를 선언하고 어떤 함수를 호출해야 되는지 막막했던 경험이 있을 것이다. 이 때 친절한 책들과 인터넷상에 있는 많은 자료들이 우리를 도와줬겠지만 실제로 프로젝트를 수행할 때는 이런 책들과 자료들이 언제나 존재한다고 볼 수 없다. 오히려 존재하지 않는 경우가 더욱 많다.
특정 구조체와 관련된 함수를 언어적으로 묶어 주는 개념이 있으면 좋을 것 같다. 그런 방법이 존재한다면 사용하고자 하는 구조체를 어떤 함수를 통해서 다루어야 하는지 헷갈릴 필요가 없을 테니 말이다. 위에 GIMP의 예를 보면 gimp_brushes_get_opacity 함수는 이름만으로‘GIMP의 Brushes에서 Opacity를 Get하는 함수’라는 것을 알 수 있다. 또 다른 gimp_brushes_set_paint_mode 함수는‘GIMP의 Brushes에서 Paint Mode를 Set하는 함수’임을 알 수 있다. 그리고 이 함수들이 하나의 헤더에 같이 있으므로 비슷한 부류의 함수라는 것을 쉽게 알 수 있다. 프로그램이 여러 사람에 의해 동시 다발적으로 수정되고 추가되고 삭제되면서 이런 통일성을 지속적으로 지킬 수 있는 것은 정말 높은 수준을 의미한다고 할 수 있다.
개발하기에 가장 좋은 방법은 수준 높은 개발자들 여럿이서 서로 원하는 수준에서 활발히 커뮤니케이션을 하면서 일하는 것이다. 하지만 우리가 일하는 현실을 돌아보자. 회사 내에서 모든 개발자가 같은 수준에서 개발할 수는 없다. 중급 개발자와 초급 개발자가 똑같은 수준에서 개발을 할 수는 없을 것이다. 중급 개발자가 별도의 코멘트(Comment)없이 마우스 제어 관련 기능 함수 선언을 mouse.h라는 파일에 모아 놨는데 초급 개발자가 아무 생각 없이 keyboard_input( ) 함수를 mouse.h에 넣을 수도 있다. 그렇다고 초급 개발자가 만든 코드를 매번 중급 개발자가 검토하고 잘못된 사항을 고쳐 주고 관리하는 것도 정답이 아니다. 또 모든 개발자들의 스타일이 제각각인데 이런 부분을 규칙으로 정해 놓고 지키도록 자율성에 맡길 수도 없는 노릇이다.
위에서 다소 생소할 수 있는 GIMP의 예를 굳이 꺼낸 이유는 소스가 몇 백줄 또는 몇 천줄까지는 어떤 방법으로 개발한다 해도 코드의 양이 적기 때문에 쉽게 수정할 수 있다. 하지만 사용자들에게 릴리즈되는 제품은 코드가 최소 몇 만줄 이상이므로 이런 큰 코드를 여러 개발자가 동시 작업하면서도 일관성 있는 코드를 만드는 것은 절대 쉬운 일이 아니다. 현실은 우리의 생각만큼 아름답지 못하다.