객체지향 프로그래밍에 대한 오해와 진실

Posted by 大山 Wed, 16 Aug 2006 08:14:00 GMT

많은 개발자들이 OOP(객체지향 프로그래밍, Object Oriented Programming)를 처음 접하는 것은 아마도 C++나 자바를 통해서일 것이다. 보통 C++/자바 입문서는 OOP란 무엇인가를 설명하는 챕터로 시작되기 마련인데, 하나같이 객체지향 프로그래밍의 핵심을 상속(Inheritance), 캡슐화(Encapsulation), 다형성(Polymorphism)이라고 설명하고 있다.

나중에 Objective-C, Smalltalk, 자바스크립트 등을 접하면서 이같은 설명이 얼마나 엉터리인지 깨닫게 되었다. 이 글에서는 내가 지난 수년간 객체지향 프로그래밍에 관해서 이해하게 된 것을 한 번 정리해 보려고 한다.

조금 규모가 있는 프로그램을 작성하다 보면, 가장 골치아픈 이슈 중의 하나가 소스코드의 복잡성을 관리하는 문제이다. 변수와 함수의 이름을 일관적으로 정리하고 전체 소스코드에 체계적인 구조를 잡아두지 않으면, 자신이 직접 작성한 코드를 들여다 보는 것 조차 막막해지기 십상이다.

프로그래밍 언어는 이러한 소스코드의 복잡성을 보다 체계적으로 관리할 수 있는 방향으로 발전해 왔다. 초기의 프로그래밍 언어에는 함수 개념 조차도 빠져 있었다. 함수는 프로그램을 유닛 단위로 나누어서 관리하기 위해 만들어진 가장 기초적인 개념이다. 루프, 조건문, 케이스문 등 역시 프로그램을 보다 체계적으로 작성하기 위해 생겨났는데 과거에는 이들 대신에 GoTo문이 사용되곤 했었다.

그런데 점차 프로그램에서 사용되는 함수의 수가 늘어나자, 함수의 이름과 그 소스코드를 관리하는 일이 커다란 문제가 되어버렸다. C나 PHP로 개발을 해 본 사람은 잘 알겠지만, mysql_field_name(), mssql_field_name() 식으로 함수 이름 마다 접두사(Prefix)가 필요한 데다가, mb_strlen(), ob_get_length(), mysql_fetch_lengths() 처럼 함수 이름을 명명하는 방식은 개발자마다 제각각이게 마련이다. mailparse_determine_best_xfer_encoding() 처럼 함수 이름이 한도없이 길어지는 문제는 두말할 필요도 없겠다.

객체지향 프로그래밍은 바로 이러한 문제에 대한 해결책을 제시했다. 함수를 아예 데이타에 묶어서 관리하면 그 이름이 짧아지게 될 뿐더러, 함수의 소스코드 또한 데이타 구조의 정리체계에 따라 관리가 가능하다는 것이 바로 객체지향 프로그래밍의 핵심이다. 객체지향 프로그래밍에서는 이렇게 데이타에 묶여진 함수를 메소드(method)라고 부른다.

물론 데이타에 묶어서 관리하는 것이 자연스럽지 못한 함수도 적지 않은게 사실이다. OOP 언어에서는 데이타(객체)에 묶어두기에 적합하지 않은 함수를 클래스나 모듈에 묶어 관리하는 방식으로 이 문제를 비켜가고 있다. 클래스는 함수 이름 관리를 위한 적절한 네임스페이스를 제공해 주기도 하기 때문에, 객체에 묶이지 않은 함수의 경우에도 함수 이름과 그 코드의 관리가 한결 수월하게 되었다.

이 글의 시작에서 언급했던 내용을 다시 한 번 살펴보도록 하자. OOP를 설명하는 일반적인 방법은 상속, 캡슐화, 다형성 등의 개념을 통해서이다. 그런데 캡슐화란 프로그래밍에서는 너무도 보편적인 개념인 추상화(Abstraction)의 또다른 표현일 뿐이고, 다형성은 함수 이름에서 접두사(Prefix)가 빠진다는 것을 어려운 용어로 표현한 것에 불과하다. 상속 조차도 객체지향 시스템을 설계하는 하나의 방식에 불과해서, 자바스크립트 같은 언어에서는 상속 대신 프로토타입(Prototype)이라는 전혀 다른 개념을 사용하고 있다.

객체지향이란 함수를 관리하는 하나의 프로그래밍 기법에 불과할 뿐이다. 매우 효과적이고 편리한 방법임에는 틀림이 없지만, 그렇게 거창하지도 또 이해하기에 복잡한 개념도 아니다.

관련글: 객체지향 프로그래밍에 대한 오해와 진실 2

Posted in  | Tags ,  | 9 comments | 1 trackback

Comments

  1. 1.
    nohmad said about 1 hour later:

    전적으로 동의합니다. 저도 예전에 비슷한 내용의 글을 끄적이다 만 적이 있었습니다. 이 포스트의 후속편을 기대합니다. :)


  2. 2.
    홍민희 said about 3 hours later:

    안녕하세요. 저도 글의 전체적인 이야기에는 동의합니다만, 다형성의 부분에 있어서는 다른 생각입니다(제가 현재 블로그가 없어서 다소 긴 글을 코멘트로 올리겠습니다). 단순히 접두어를 생략한 것이 다형성을 제거했다고 볼 수는 없습니다. 위에서 말씀하신 것처럼, OOP 이전의 언어에서 데이터베이스에 쿼리하는 방식은 대체로 다음과 같습니다.

    mysql_query(query_string, db_connection)

    말씀하신 것처럼, 접두사를 통해 별도의 네임스페이스를 지닌 효과를 냅니다. 만약 저것을 여러 DBMS에 옮겨다닐 수 있도록 한다면, 가장 간단한 방식은 조건을 분기해서 처리하도록 설계하는 것입니다(지저분하죠).

    switch(dbms_type)
      case MYSQL
        mysql_query(query_string, db_connection)
        break
    
      case SQLITE:
        sqlite_query(query_string, db_connection)
        break
    
      case MSSQL:
        mssql_query(query_string, db_connection)
        break
    

    그리고 OO를 지원하는 언어에서는 대체로 그 인터페이스가 다음과 같이 변합니다.

    db_connection.query(query_string)

    OOP에서 말하는 다형성은 여기서 적용됩니다. 연산(evaluation)이 자료(data)에 묶여있으므로, 다른 객체의 같은 메서드를 호출하는 것만으로 여러 DBMS를 지원하게 되는 것입니다. 위 코드는 객체가 어떤 데이터베이스의 핸들이던 간에 제대로 작동할 것입니다(데이터베이스 라이브러리 사이의 프로토콜이 매치된다면).

    이러한 효과라면 단순히 접두어의 제거라고 보기에는 너무 좋은 효과입니다. 그렇지 않은가요?

    C++의 경우에는 다른 종류의 다형성을 맛볼 수 있습니다. 표준 라이브러리의 정렬(std::sort) 함수는 그 대상이 배열이든 벡터(std::vector)든 리스트(std::list)든, 혹은 자신이 직접 만든 컨테이너 타입이든 간에 다형성이 일어납니다. 이러한 것은 일반화 프로그래밍(generic programming)이라고 합니다.


  3. 3.
    大山 said about 5 hours later:

    @nomad: 후속편 아이디어 좀 주세요~ ^^;;

    @홍민희: 민희님께서는 주로 스태틱 타이핑(Static Typing) 언어를 통해서 객체지향 프로그래밍을 접해오신 듯 합니다. C++나 자바에서는 객체에 메세지를 보내는 것을 메소드 호출과 동일시하는 경향이 있습니다만 엄밀히 말하면 이 두가지는 별개의 프로세스입니다.

    코드에서 db_connection.query(query_string)라고 작성하는 것은 db_connection 객체에 'query'라는 메세지를 query_string과 같이 보내라는 것이고, 실제로는 런타임에서 db_connection 객체의 query 메소드를 호출하게 됩니다. 이 때문에 다형성이나 Generic Programming도 가능한 것으로 알고 있습니다. (컴파일타임에는 실제로 어떤 메소드를 호출해야 하는지를 알 수 있는 방법이 없지요)

    반면에 Smalltalk, Objective-C, 루비와 같은 다이내믹 타이핑(Dynamic Typing) 언어에서는 모든 객체에 어떤 메세지라도 보낼 수 있기 때문에(단지 메세지를 보내는 것이기 때문에 정의되어 있지 않은 메소드에 해당되는 메세지를 보내는 것도 가능합니다), 다형성이나 Generic Programming 같은 개념이 존재하지 않습니다. (두가지 개념 모두 스태틱 타이핑 언어가 가지는 한계를 극복하기 위해서 생겨난 개념이지요) 이 때문에 다이내믹 타이핑 객체지향 언어의 관점에서는 다형성이 접두어 생략 이상의 의미를 가지기 힘듭니다. 조금 다르게 설명드리자면, 다형성과 Generic Programming은 스태틱 타이핑 언어에 다이내믹 타이핑 기능을 일부 추가한 것이라고 말할 수 있을 것 같습니다.

    Smalltalk가 모든 객체지향 언어의 원형인 만큼, Smalltalk 관점에서 OOP를 이해하는 것이 조금 더 자연스럽지 않을까요? 자바나 C++ 관점에서 OOP를 바라보는 것은 OOP를 필요 이상으로 복잡하게 만드는 경향이 있는 것 같습니다.


  4. 4.
    홍민희 said about 20 hours later:

    저는 정적 타입 언어라고는 C++과 Java, C# 외에는 거의 접한 적이 없고, 그들 중에서도 C++ 외에는 잘 알지 못합니다. 저는 오히려 덕 타입 언어에 능숙합니다. ㅎ 주로 사용하는 것은 Python이구요. Io와 같은 Prototype-based OO에도 관심이 많습니다. 정적 타입 언어에는 별 관심이 없답니다.


  5. 5.
    홍민희 said about 20 hours later:

    아, 그리고 별 것 아니지만… Smalltalk가 정식 표기법입니다(보통 talk의 t를 대문자로 표기하는 경우가 많더군요).


  6. 6.
    mkseo said about 20 hours later:

    뭐 생각하기 나름이지만, 그래도 OOP의 정의는 추상 데이터 타입 + 폴리모피즘이죠;;;

    전 오히려 ducktyping 같은 경우를 OOP의 본질이라고 말하기보다는, 걔네가 오히려 특이한 경우로 분류되야 할거라 생각되요.


  7. 7.
    mkseo said about 20 hours later:

    그런데 여기는 코멘트에서 줄바꾸기를 어떻게 해야되죠?

    계속 한줄로 붙어서 나오는데..


  8. 8.
    wookay said about 21 hours later:

    좋은글이네요


  9. 9.
    大山 said about 22 hours later:

    @홍민희: 제가 넘겨짚어 생각을 했었네요, 사과드립니다. 그리고 Smalltalk가 옳바른 표기법이 맞군요, 지적 감사합니다~ ^^;;

    @mkseo: 그냥 html 태그 사용하시면 됩니다.

    @wookay: 감사합니다~ :)


Trackbacks

Use the following link to trackback from your own site:
http://beyond.daesan.com/articles/trackback/1188

  1. From
    상속,다형성,캡슐화에 대하여...
    大山님의 객체지향 프로그래밍에 대한 오해와 진실이라는 글을 읽었는데, 그 글에서처럼 동적타입을 지원하는 OOP 언어에서라면 클래스라는게 네임스페이스 이상의 의미를 가지기 어려

Comments are disabled