본문 바로가기

개발 Note/it 이야기

C에서 C++ 그리고 framework

반응형

프로그래밍 역사에서 빼놓을 수 없는 C와 C++ 언어에 대해서 얘기해 보고자 합니다.

1. C에서 C++



C 언어는 벨 연구소에 일하던 데니스 리치가 B언어(Bell 연구소에서 따와서 B라고 명명함)를 개선하여 만들었습니다.

이당시 상황은 Unix에서 사용할 프로그래밍 언어가 필요한 상황이었고 이 언어가 개발됨에 따라 Unix의 바탕이 되는 프로그램들은 거의 모두 코드가 C언어로 만들어지게 됩니다.

리눅스 역시 Unix를 모델로 만들어지면서, 리눅스의 바탕 역시 C언어로 만들어지게 됩니다.

(리눅스는 리누스 토발즈가 헬싱키 대학원생 시절 교수가 교육용으로 만든 미닉스의 기능에 만족하지 못하고 새로 개발하게 된 OS입니다.)

때문에 C언어가 크게 확산되고 발전된 것은 Unix나 Linux같은 OS의 개발과 확산에 의한 영향이 크다고 봅니다.

C 언어는 이처럼 System programming에 적합한 언어로 자리 잡았고, 현재까지도 Linux나 Unix는 사용되고 있는 OS이고 그 외의 여러가지 Kernel 들이나, OS들 역시 System level의 code들은 거의 C언어로 이뤄졌다고 볼 수 있습니다.


그 후 S/W OS의 발전은 system S/W에서 점점 Ui, Network, Service, Game, Graphics, Application 등 다양한 영역 들로 넓혀가게 됩니다.

그중 대표적인 것이 GUI 환경이죠. 

이 GUI 환경은 Zerox 연구소에서 시작이 되어, Macintoch, MS window, OS/2, Nextstep  등등 수많은 OS들이 GUI 환경을 제공하게되고, 사용자 입력 역시 keyboard에서 Keyboard+mouse 로 바뀌게 되었죠.

이를 우리는 보통 Window System이라고 부릅니다. 아무튼 이로서 프로그램들은 더 복잡하고, 인터랙티브 한 기능들을 제공해야 했습니다.


기존의 어떤 특정 기능을 처리하는 방식의 절차적인 프로그래밍 방식으로는 이런 환경에서 다양한 사용자 요구사항과 여러가지 입력들을 체계적으로 처리하기에는 무리가 있었습니다.

이때부터 나오기 시작한 개념들이, 객체지향 설계, 이벤트 기반 방식(Event driven), 등등의 개념이 나오게 됩니다.

그러면서 실제로 객체지향 설계를 받아들일 수 있는 시뮬라 67이라는 언어가 만들어졌고 , 이 언어는 다른 언어들에 영향을 미치게 됩니다.

C 언어 역시 객체지향 패러다임을 적용하기 위해서 C++이라는 C언어 트랜슬레이터가 개발됩니다. 향후 C++은 단순 트랜슬레이터가 아니라 독립된 언어로 그 과정에서 C언어와의 Code 호환성을 유지하면서 멀티 페러다임 언어로 자리잡게되죠.


즉 C++은 C언어가 복잡하고 고도화 되어가는 S/W 환경에서 객체 지향 설계라는 획기적인 S/W설계방식을 받아들이 위해 만들어졌다고 보시면 되겠습니다.


 !!!!:  C++ 언어는 초창기 C언어의 트랜슬레이터로 구현되었었고, 때문에 C++로 작성된 코드는 C로변환된뒤 컴파일이 되었습니다.

(참고 wikipedia : ko.wikipedia.org/wiki/C++) 

그래서 지금도 C->C++로의 환성이 유지되고 있고 C언어의 문법을 그대로 받아들이고 있습니다. 즉 C++은 객체지향 언어라기 보다는 절차지향 언어에 객체지향 패러다임이 추가된 멀티 패러다임 언어라고 하는게 좀더 잘 표현한 것이라 할 수 있겠네요.(여러 자료들에서도 이런 표현을 사용하고 있죠.)

C에서C++로 확장된 같은 지류의 언어라고 인식하는 것도 이런 이유일 것입니다.


2. "C++이 느리다." 


사람들이 C 언어를 다른 언어와 비교할때 주로 C++과 비교를 많이 하는 반면 Java를 같은 선상에 놓고 비교하지는 않습니다. 

이유는 언어의 성격 상 C는 system programming을 하기 위한 것, Java는 application 개발 또는 application programming을 하기 편한 것으로 인식하고 있기 때문에 이에 대한 비교는 별로 하지 않는 반면, C / C++에 대해서는 같은 선상에 놓고 비교할 때가 많습니다.


이런 비교의 바탕은 사실상 System level의 programming을 하는 쪽에서 가 많이 나오는 편입니다.

(C++로 System software를 개발할 필요성이 있는가를 염두해 둔것 이라고 봐야 할까요?, 아니면 C에 익숙해있는 System S/W개발자들은 C++언어가 못마땅한걸까요?) 

비교의 주된 내용이 모두 Performance에 맞춰져 있습니다. 즉, C++은 C보다 느리다는 것입니다.


이런 성능 를 하게 되면, 그리고 왜 일부 사람들은 C가  C++ 보다 성능이 좋다고 생각하는 것일까요?

C++언어는 객체지향 언어가 아니라 멀티 패러다임 언어입니다. 즉, 용도에 맞춰 코드를 작성 할 수 있기 때문에, 퍼포먼스를 해치는 그런 코드는 굳이 객체화 하거나 할 필요가 없다는 것인데 C++은 무조건 객체로 만들어야 한다는 선입견이 적용된 경우가 아닌가 싶습니다.


일단 성능 얘기가 나왔으니 이야기를 이어가 보겠습니다. 성능 의 주요 주제는 virtual function에 대한 얘기를 합니다.

자, 그럼 아래의 code를 테스트 해보면 어떤 결과를 얻을까요?
loop 1000만번 을 돌면서 tempbuf에 hello라는 단어를 copy 하는 코드입니다.
조금이라도 공정하게 테스트 하기 위해서, test_tool()이라는 동일한 함수를 부르도록 하였습니다.
virtual funtion 테스트는 class 는 inherit 해서 virtual 함수를 상속받아 구현한 코드이고,
function pointer 테스트는 일반적으로 function pointer를 사용할 때 null 채크를 하기 때문에 이 코드를 포함하여 넣었습니다.
  - 이 부분에서 논란이 있을 수 있는데 제 생각은 이렇습니다.

C++ compiler는 compile time에 virtual function을 syntax를 검사하는 형태로  pure virtual 함수를 사용하는 경우를 필터링 해줍니다.

하지만 C의 경우 function pointer의 안정성 검사가 이뤄지지 않죠. 따라서 실제 사용될때는 사용자에 의해 어디선가 해야 합니다.

때문에 아래와 같이 가장 기본적인 null 채크를 추가하였고 일반적으로 실사용에서 함수 포인터를 사용한다면  꼭 해야하는 기본적인 로직이라 생각해서 넣은 구문입니다.

 (사실 C의 function pointer 임의의 function으로 대처될 수도 있어서 c++ virtual function에 비해 risk가 더 있기 때문에 실제 현업에서는 더 많은 컨디션 체크를 하고 있다고 생각됩니다.)


돌려보셨나요? 결과는 어떤가요?

#include <stdio.h>
#include <sys/time.h>
#include <iostream>

using namespace std;

class _ElapsedTime
{
public:
    _ElapsedTime(const char* tag = NULL)
    {
        struct timeval tv;

        tagName = tag;

        gettimeofday(&tv, NULL);
        start_time = (long long)tv.tv_sec * 1000000LL + (long long)tv.tv_usec / 1LL;
    }

    ~_ElapsedTime(void)
    {
        long long end_time;
        struct timeval tv;
        gettimeofday(&tv, NULL);
        end_time = (long long)tv.tv_sec * 1000000LL + (long long)tv.tv_usec / 1LL;

        fprintf(stderr, "%s: elapsed time: %lld us\n",tagName,  end_time - start_time);
    }


public:
    long long start_time;
    const char* tagName;
};



char tembuf[2048];

void test_tool()
{
  sprintf(tembuf,"%s","hello");
}


// test for virtual function

class test
{
public:
  virtual void test_func()=0;
};



class test_inherit : public test
{
public:
  virtual void test_func();

};
void test_inherit::test_func()
{
  test_tool();
}


// test for function pointer

typedef void (*test_func)();

void test_try_func()
{
  test_tool();
}



int main()
{

  test_inherit test;
  test_func func_pointer = &test_try_func;

  int i = 0;
  const int loop_end = 10000000;

  sleep(1);

  {
    _ElapsedTime try1("function pointer");
  for(i=0;i<loop_end;i++) // test function pointer
    {
      if(func_pointer)func_pointer();
    }
  }

  {
    _ElapsedTime try2("virtual function");
    for(i=0;i<loop_end;i++)  // test virtual function
    {
      test.test_func();
    }
  }

  return 0;
}



여러번 돌려봤을때 아래와 같은 결과를 얻었습니다. 위의 if 문이 큰 영향을 주더군요.

if 문이 빠졌을때는 비슷합니다.


&"warning: GDB: Failed to set controlling terminal: \353\266\200\354\240\201\354\240\210\355\225\234 \354\235\270\354\210\230\n"

function pointer: elapsed time: 41011 us

virtual function: elapsed time: 31175 us

Debugging has finished


Debugging starts

&"warning: GDB: Failed to set controlling terminal: \353\266\200\354\240\201\354\240\210\355\225\234 \354\235\270\354\210\230\n"

function pointer: elapsed time: 39163 us

virtual function: elapsed time: 31143 us

Debugging has finished


Debugging starts

&"warning: GDB: Failed to set controlling terminal: \353\266\200\354\240\201\354\240\210\355\225\234 \354\235\270\354\210\230\n"

function pointer: elapsed time: 39903 us

virtual function: elapsed time: 31362 us

Debugging has finished


Debugging starts

&"warning: GDB: Failed to set controlling terminal: \353\266\200\354\240\201\354\240\210\355\225\234 \354\235\270\354\210\230\n"

function pointer: elapsed time: 35646 us

virtual function: elapsed time: 31281 us

Debugging has finished


두번째 성능 이슈는 객체의 생성 소멸에 따른 비용 문제입니다.
C++ 로 class를 작성하게 되면, 생성과 소멸시 constructor 와 destructor 가 불리게 되고, 함수에서 객체를 return 하거나 operator에 의해 임시객체사 생성, 임시객체 복사, 삭제가 발생합니다.

C++11 에서는 r-value reference가 지원되어 move semantic 등을 통해 임시객체에 대한 overhead는 약간은 해결했지만, 기본적으로 객체의 생성 삭제 부분의 오버해드는 존재하게 됩니다. 이는 퍼포먼스에 영향을 주기 마련입니다.


특히 Integer, Float, Char과 같은 basic type들을  class로 정의해서 사용한다면, 여러가지 operator들을 제정의 해서 사용하게 되고, 객체를 return하게 될때 객체 copy가 일어나고, 만약 임시객체를 만들게 되면,임시객체 생성, 소멸, 복사가 일어나게 오버해드가 발생합니다.

c++ 가 그동안 이런 측면에서 어택을 받아왔던 부분들 일것입니다. 


기본 타입(primitive type)에 대해서는 언어의 차이에 대해서 오버해드는 없겠지만, 객체를 만들어서 다루는 부분에 대해서는 분명 오버헤드라고 볼 수 있습니다.

이 부분은 객체 라는 설계요소가 포함되어 발생하는 부분으로 같은 설계를 놓고 본다면, C나 C++이나 아마 크게 차이나지 않을 것 입니다.

예를 들면 이런거죠.


// A를 다루는 List 형태의 manager 설계

struct A{...};

struct Node{struct A a; struct B* pNext;};

struct Manager{ struct A* pcurrent; struct Node* pList; } ;


void clear_A(A* a);


Manager* create_manager();

//destroy 함수는 모든 node를 살펴보면 삭제하는 코드.

void destroy_manager(Manager* p){

   if(p == NULL) return;

   p->pcurrent = NULL;

   struct Node*pNode = pList;

   while (pNode){

      struct Node* pCur = pNode->pNext; 

      pNode= pNode->pNext;

      clear_A(&pCur->a);

      free(pCur);

   }

}


class A{...  ; A(); ~A();};

class Node{

public:

    A a;   Node* pNext; 

    Node(); 

    ~Node(); 

    Node* getNext();

};

class Manager{ 

    A* pcurrent;     Node* pList; 

    Manager(); 

    ~Manager();

}; 


Manager::~Manager(){

  pcurrent =  nullptr;

  Node* pNode = pList;

  while(pNode){

    pCur = pNode;

    pNode = pNode->getNext();

   delete pCur;  <-- 이 부분이 왼쪽의 clear_A() free() 를 호출한 부분과 같은 부분

  }

}




이 다음 주제가 설계를 반영하는 부분에 대한 얘기 입니다.



3."C로도 OO를 구현할 수 있다."


C와 C++의 비교 내용은 주로 Performance 대한 이슈 또 하나가 C로도 객체지향을 구현할수 있다는 의견이 주 내용 일 것입니다.

이를 단순히 표현하면, "C 는 C++보다 빠르고 C로도 객체지향적으로 구현할 수 있다" 가 되죠.

그럼 아키텍쳐링 측면에서 좀 살펴봐야 할것 같습니다.


요즘은 어플리케이션이든 아니면 서비스 모듈이든 상당히 복잡해졌고 규모가 큰 편입니다.
그래서 소프트웨어의 구조적인 측면을 중요하게 생각합니다. 그리고 S/W를 소개할때에도 이런 부분들이 잘 반영되도록 해서 구조 설명을 해야되어있습니다. 때문에 설계는 S/W에서 빠질 수 없는 부분입니다.

객체지향 프로그래밍이라는 개념이 나오고 나서 S/W의 설계 분야는 OO 기반으로 상당한 발전들이 있었습니다.
Component, OOAD, Design pattern 등이 대표적인 예인데, 이러한 개념들은 UML 과 더불어 강력한 프로그래밍 설계 툴이 되었습니다.

C, C++ 은 모두 절차적 프로그래밍 언어이긴 하지만 C++ 객체지향 페러다임을 담고 있는 언어라고 얘기 합니다.
그래서 C++는 UML이나 객체지향 설계의 내용을 코드로 옮기기가 쉽습니다.
그렇기 때문에 설계와 코드를 동일한 퀄리티로 유지 할 수 있고, S/W의 구조적인 문제점들을 파악하거나 개선 방향을 잡는데 매우 편리합니다.


이런 얘기가 나오면, "C로도 OO 개념을 적용할 수 있다" 라고 합니다.

하지만 언어적인 한계가 있기 때문에 아무리 구조적으로 잘 작성한다 하더라도, OO를 지원 하는 언어와 동일한 편의성을 제공 할 수 없습니다. 안타까운 현실이죠.

예를 들면, 아래와 같이 구조를 잡아나가면 c 나 c++이나 다를게 없다고 생각 할 수도 있습니다.
그렇지만 자세히 뜯어보면 그렇지 못하다는 것을 알 것입니다.

<test.c>

typedef struct
{
  int (*getter)();
  int (*setter)();

  int value;
}CStructPrototype;


void test_struct()
{
  CStructPrototype st;
  st.getter();  <- 올바른 동작일까요?
  st.setter();

}



실제 정상적인 코드를 작성하려면 아래와 같이 되어야 할 것입니다.


<test.c>


typedef struct _CSTRUCT
{
  int (*getter)(struct _CSTRUCT* self);
  void (*setter)(struct _CSTRUCT* self, int value);

  int value;
}CStructPrototype;

int CStructPrototype_Getter(struct _CSTRUCT* self)
{
  return self->value;
}

void CStructPrototype_Setter(struct _CSTRUCT* self, int value)
{
  self->value = value;
}

void CStructPrototype_Construct(CStructPrototype* st)
{
  st->getter  = &CStructPrototype_Getter;
  st->setter  = &CStructPrototype_Setter;

  st->value = 0;
}

void test_struct()
{
  CStructPrototype st;
  CStructPrototype_Construct(st);
  st.getter(&st); 
  st.setter(&st, 10);

}



자, 이러면 된걸 까요?

멤버 함수 처럼 보이는 getter와 setter에 인자로 자기자신(st&)이 들어가도록 되어있습니다.


여전히 문제는 있습니다. 다음 코드를 봅시다.



void test2_struct()

{
  CStructPrototype st;
  CStructPrototype st2;
  CStructPrototype_Construct(st);
  st.getter(&st);
  st.setter(&st, 10);
  st.setter(&st2, 10); // (A)<- st2의 data가 변경됨. 
}


(A)를 보면 st의 member함수처럼 보이는 setter에 st2가 들어갑니다. 그래서 st2의 내부 변수이 value가 변경되게 됩니다.

setter의 구현체인, CStructPrototype_Setter 의 내부에서도 인자로 받은 st가 this 인지를 확인 할 방법도 없습니다.

즉 function pointer는 member함수가 될수 없는 이유입니다.



또, 만약 상속을 생각한다면,
 getter와 setter의 prototype이 좀 바뀌어야 합니다.

  int (*getter)(void* self);
  void (*setter)(void* self, int value);

그리고 구현부에서 void* 를 casting해서 사용해야 합니다.

함수 overriding 구현을 위해서는 더욱 더 복잡해지기 마련이고, 이를 표기할때 단순화 시키기 위해 macro를 작성해 사용한다면, 코드의 가독성이 떨어지게 되고,  함수 pointer와 연결된 함수를 직관적 알아보기 힘들게 됩니다.



그외 ,

operator overloading 과 function overloading 등은 방법이 없습니다.

또 exception handling 역시 지원되지 않기 때문에 error handling 방법이 유일하게 return값을 확인 하는 방법과, 모듈 내부에서 last error 와 같은 로직을 추가로 해결 할 수 밖에 없습니다.

(exception에 대한 안좋은 선입견을 가지신 분들도 있을 수 있는데요. exception은 결함 내성(fault-torelant) 소프트웨어를  쉽게 작성할 수 있도록 도와주는 것입니다. - 참고 : 왜 예외를 쓰는 게 좋을까요? 

 : 논점에서 좀 벗어난 얘기라 서 읽는데 혼란을 줄 수도 있는 내용이라 gray 로 덮었습니다.


오히려, 이런 코드는 

CStructPrototype_Getter(&st);

CStructPrototype_Setter(&st, 10);

함수 자체를 호출하도록 하는 것이 훨씬 C 스럽고 안정성을 높이고 시인성을 높이는 것입니다.


그런데 종종 위와 같이 struct과 function pointer를 이용해서 OO 구조를 잡는 코드들을 볼수 있습니다.

왜 C programming을 할때 위와 같이 struct과 function pointer를 가지고 class 와 비슷한 구조를 갖추려고 할까요?
제 생각에는 이런 프로그래밍을 하는 사람은 아마도 OOP를 알고 있는 사람일 것입니다.

그래서 C언어 밖에 사용할 수 없는 환경에서 OO를 흉내내고 싶어 하는 것 입니다.

(물론 그렇지 않은 경우도 있습니다 만, 때때로 과도하게 이런 흉내를 내는 코드를 볼때가 있습니다.)


만약 그러시다면, C++을 사용하십시오.


<test.cpp>


class CppClsss
{
public:
   int getter(){return value;}
   void setter(int v){ value = v;}
private:
int value;
}

void test2_struct()
{
  CppClass st;
  st.getter();
  st.setter(10);
}


더 이상 struct를 class 처럼 꾸밀 필요도 없고, 아래와 같이 OO로 작성된 module 들은 객체의 member function을 사용하면 되고,
C function 제공하는 것들에 대해선 C function을 사용하면 되기 때문에, C 개발자 입장에서는 C 사용성이 확대되었다 정도로 인식만 하면 되지, 기존의 로직 구조를 변경할 필요는 없습니다.




자 그럼 다음 질문, 왜 C++로 작성하지 않을까요?
이 질문이 C 언어를 주로 다루는 개발자 분들은  C로 작성된 모듈을 모두 OO 기반으로 바꾸지 않는가? 라고 오해의 소지가 있습니다.

Refactoring 관점이나 Architecturing 관점에서 접근하더라도 C로 코딩 되어 있는 코드들을 객체 기반으로 코드로 모두 바꾼다는 것은 잘못된 설계가 될 가능성이 있고 모듈의 동작 변화도 발생할 가능성이 높습니다. 그만큼 리스크가 있는 작업입니다.

이런 리스크를 안고 굳이 기존의 코드를 OO 기반의 코드로 변경할 필요는 없다고 봅니다.


잠시 프로그래밍 언어와 용도에 대해서 잠시 고민해 봅시다.
C로 되어있는 system call을 처리하는 모듈이 있는데, 이 모듈은 system call에 의한 interrupt 루틴이 함수 하나로 작성되어있고,  runtime 에 system service 에 등록 되도록 되어있습니다.

그럼 C++ compiler로 교체 함으로 해서 이런 간결하고, 뛰어난 코드를 객체로 재 정의 하고 객체에 interface를 만들고, service call에 등록하기 전에 객체 instance를 생성하고, 연결해주는 static 함수를 service에 등록해야 할까요? 이런 코드들은 비록 객체로 바뀌었다고 하지만, 여전히 C로 구현했던 내용과 큰 차이가 없을 것이고 크게 개선될 것도 없을 것입니다.

C++ compiler로 변경 했다고 해서 기존의 코드를 모두 새로운 객체지향 페러다임으로 변경할 필요는 없다고 생각합니다.
대신 C 효율적으로 대처하지 못했던 부분들에 대해서 C++ 이 보완해 줄 수 있다는 것이 가장 중요한 핵심인것 같습니다.


4.Framework


가끔 "이 프래임워크는 Java로 되어있어", "Facebook 은 Social service framework 이다" 이런 표현들을 들어봤을 것입니다.


framework 비슷한 용어로 우리는 platform이란 단어를 사용합니다.

Platform은 뭐고 Framework은 무엇일까요? 이것들은 비슷하게 들리는데 어떤 차이가 있는 것일까요?


Platform이라는 용어는 Hardware architecture ,Operating system, runtime library를 포함한 용어로 많이 사용되고 있습니다. 따라서 어떤 디바이스가 동작하기 위한 모든 요소를 합쳐서 platform이라고 부릅니다.


Framework은 특정 platform위에서 어플리케이션이나 서비스를 개발할 수 있도록 제공되는 logic을 기능화하여 제공하는 것을 의미합니다.  library와의 차이가 뭐냐? 라고 한다면,

Library는 흔히 API들의 집합을 의미하는 것으로 그 이상의 의미는 별로 없습니다. 그러나 framework은 이런 library와 platform의 기능 들을 장 정리해서 특정 기능이나 서비스를 구현하는데 필요한 business logic을 제공하는 것을 입니다.


즉, 단순 API set이 아니라, logic을 포함한다고 보시면 됩니다. 잘 이해가 안 가나요?


쉽게 비교 표현 하자면, Windows platform, Graphics library, Ui framework 이렇게 봅시다.

Windows 는 desktop 기기나 mobile 기기를 구동하기 위한 architecture와 OS 를 담고 있기 때문에 platform이라고 부릅니다.

그 Windows 위 에는 수많은 library 들이 있습니다. socket, network library , openGL, graphics, GUI library등이 있죠.


그리고 Net framework 이나, MFC 와 같은 framework은 이런 graphics library와 open gl, socket, http등을 이용해서 application을 쉽게 구현 할 수 있도록 해주는 것입니다.

또, Facebook에서 자신들의 서비스를 쉽게 접근해서 사용할 수 있도록 제공하는 facebook framework 등과 같은 서드 파티에서 제공하는 framework이 있습니다.


즉 Framework은 어떤 기능을 구현하기 위한 low level의 API를 제공하는 library(socket,gl 과 같은) 가 아니라, network connection manager 나 game 개발을 쉽게 개발할 수 있도록 socket을 이용하여 http protocol을 쉽게 접근 할 수 있는 http class 를 제공하는 것이고, http class들을 이용해서 facebook에 쉽게 접근 할 수 있도록 facebook class나 facebook web api set을 제공하는 package를 말하는 것입니다.


OS 제조사(MS, Apple, Google등)에서 제공하는 application development framework(SDK)은 다양한 sub framework이나 module 들을 포함하고 있습니다.


또 .Net 이나 android의 framework들이 대표적이라고 할 수 있는데요. 크게 Application life cycle 을 handling 할 수 있는 runtime, Ui framework, content management, media, image , graphics , network , censor 등의 sub module들을 포함하고 있습니다.


이런 sub module( 또는 sub framework)등을 architecture 로 표현 할 때 흔히 package, class, namespace 등으로 표현하고, UML과 같은 디자인 툴로 각 class 및 package 들의 관계를 표현 합니다.


이정도로 정리해서 platform과 framework의 정의를 나눠봤고, 과연 C언어로 framework을 제공하는 것에 대해서 좀더 심도 있게 생각해보고 싶습니다.

이 의견은 객체지향 패러다임을 적용할 수 없는 언어가 과연 application 개발을 위한 framework으로 적합한가에 대한 물음으로 보시면 될것 같은데요. 제 의견은 만들 수는 있지만 좋은 사용성을 제공하기는 힘들 것이라 생각됩니다.

여러가지 framework들은 범용적인 형태가 아닙니다. 즉 어떤 목적에 맞는 ,그 목적에 잘 어울리는 방식으로 기능을 제공합니다.

하나의 programming 언어로만 제공되는 경우도 있지만, script, XML, Editor tool, 심지어는 programming 언어까지 새로 만들어서 제공되기도 합니다. 

이러한 다양한 형태까지는 아니더라도, 적어도 OO design을 적용한 framework은 적어도 OO 패러다임을 담고 표현할 수 있는 언어로 제공되는 것이 맞겠죠.



5. 맺음말

처음에 C와 C++언어에 대한 이야기로 시작 했는데 사실 framework과 language를 같이 얘기 하고 싶었습니다.
제가 프로그래밍 언어에 대해 전공을 한 것이 아니라 제 경험과 주관 그리고 블로그나 커뮤니티에서 활동하고 있는 고수분들이 적어놓은 자료들을 많이 읽어보고 나름 의견을 정리해봤는데요.하고자 했던 얘기는 프로그래밍 언어는 환경과 목적에 따라 잘 선택하는 것이 중요하다는 것입니다
System 하부의 device driver와 같은 코드를 개발하는데, java나 C# 보다는 C가 훨씬 더 효율적이고, system의 동작에 대해 예측이 쉽기 때문에 잘 어울린다고 볼 수 있습니다.
반면, Application framework이나 service framework을 개발하여 사용자에게 interface를 제공하는데 C 로 작성된 API들을 제공한다는 것은, OO 기반의 설계를 다시 구조적, 절차적인 code로 구현하고 Framework API를 C function으로 제공한다는 의미가 됩니다
이는 설계와 동작이 불일치 할 가능성이 있고, 편의성 측면에서도 문제가 될 소지가 있습니다. 
OO 기반의 S/W 설계가 20여년 이상 자리잡고 현재는 대세가 되었는데, 복잡한 framework구성이나 탄탄한 설계가 필요한 부분에서 OO를 지원하지 않는 언어로 framework 을 구현하고 API를 제공한다는 것은 잘못된 방향이 아닌가 싶습니다.  구현, 디버깅, 안정성, 사용성 어느 하나 더 낳을 것이 없으니까요.
저는 OO 관점에서 봤을 때 C++ 역시 pointer를 지원하기 때문에  framework interface로는 좋지 못하다고 생각합니다. pointer는 객체에 대한 접근 표현이 아니라 메모리에 직접적인 접근을 의미하기 때문에 값의 변경이나, type 이 모호해질 가능성이 매우 큽니다. C와 비교했을때 C++이 더 낳다 인것이지, 다른 프로그래밍 언어들과 비교 했을때, C++ 역시 상당히 조심해서 사용을 해야 하는 언어임은 맞습니다. 복잡하구요.
(대안이 없는 경우라면 ㅠ_ㅠ 어쩔 수 없겠죠.)

최근에 다시 C++ 언어가 재조명 되고 있다는 기사를 본적이 있는것 같습니다. 모던 C++이라는 이름을 쓰기도 하는것 같던데..
다양한 프로젝트들에서 C++로 framework을 작성하고 있고, C++ 표준화도 C++11, C++14와 같은 많은 변화들이 진행되고 있습니다.
최신 C++에서는 기존의 C++이 어택받아오던 임시객체 생성과 복제 등에 대한 대안들을 제공하고 있어서 framework을 어떻게 설계하는가에 따라 퍼포먼스에 대해서도 상당한 향상을 가져 올 수 있을것 으로 보입니다.
글쓰는데 소질이 없는 건지 마무리 맨트가 좀 그렇네요.  ㅎ. 나중에 시간되면 좀더 정리해보도록 하겠습니다.
이상 마칩니다.