프로그래밍/C 2013. 3. 15. 09:40

써 몇 년이 지난 이야기다. 교육을 받던 분이 굳이 C언어를 배워야 할 필요가 있냐고 물어보셨다. 그에 대한 개인적인 생각을 적어보도록 하겠다.



1. 체계화된 프로그래밍 순서를 익힐 수 있다.

모든 프로그래밍은 기본적으로 연산에 필요한 데이터를 메모리에 적재(load)하고 일련의 계산 결과를 저장(store)하게 된다. 이 후에 결과 데이터를 특정 위치로 전송하거나 복제하기도 한다. 이런 기본적인 계산 단위가 논리적으로 분기되고 복합적으로 연결된 것이 바로 프로그래밍이 되겠다.


그러나 가장 중요한 연산의 기본 단위는 읽고 계산하고 쓰는 작업이라는 점은 변하지 않는다.


프로그래밍 언어의 발전은 바로 이 읽고 계산하고 쓰는 작업을 편리하게 하거나 빠르게 하는 목적으로 발전해왔다. 편리함을 목적으로 하는 인터프리터 언어나 자바와 같은 언어들은 언어적인 측면에서 위 작업들을 간소화시켜준다. 예를 들어 A라는 위치에 있는 메모리를 B라는 변수로 복사한다고 치자. 몇몇 인터프리터 언어는 간단하게 '=' 기호로 이를 가능하게 한다.


1# python같은 인터프리터는 다음과 같이 선언된다.
2# B에 A를 저장한다.
3B = A


위와 같이 인터프리터 언어는 한 줄로 메모리를 읽을 수 있다. 그러나 한 줄의 코드에는 많은 내용이 함축되어있다. 예를 들어 B 변수에 메모리가 할당되어있지 않다면 할당해주고, 변수의 길이를 체크하여 부족하다면 재할당해주는 것도 포함된다. 또한 변수의 타입이 숫자인지 문자인지 변환하는 것도 가능하다.


그러면 위와 똑같은 작업을 C언어로 한다고 치자.

먼저 B의 메모리의 할당 여부 및 크기를 확인해야 할 것이다. 만일 작다면 reallocation으로 overflow를 막아야 하기 때문이다. 이를 위해 realloc을 사용해야 하며, 메모리 크기를 내부 로직에서 관리해야만 한다.


그 다음은 뭘 또 해야 할까? 음... A의 타입이 문자열인지, 문자열로 표시되는 숫자인지 다양한 검사를 해야 하는 경우도 있다. 데이터 오류를 막기 위해 여러 복잡한 검사를 해야 할지도 모른다. 이를 위해 정규표현식(REGEX)이나 바이트 단위로 데이터를 읽어야 하는 일까지 생길 수 있다.


결국 "B=A"의 한 줄로 표현되는 간단한 인터프리터 코드가 C언어에서는 수십줄이 넘어가게 된다는 것이다. 이 과정에서 버그도 심심찮게 일어날 수 있다. 이렇듯 인터프리터는 복잡한 작업을 간단하게 해주는 장점이 있다.


하지만 인터프리터 언어는 장점외에 단점도 분명히 존재한다!!


장점은 위와 같이 편리한 코딩, 즉 생산성이 높다는 점은 확실하다. 단점은 그와 반대로 너무 편리해서 어려운 프로그래밍을 못하게 된다는 점이다. 인터프리터 언어와 같이 언어가 대신해주는 작업이 많을수록 프로그래머는 쉬운 것에 익숙해지고 성능을 높이기 위해서 해야 하는 메모리, 연산기법들에 대해 둔감해지게 된다.


좀 멋진 말로 포장하면 transparency 때문에 하부 구조를 제대로 이해하지 못하게 된다는 것이다.


왜 메모리의 데이터 타입이나 경계를 검사해야 하는지? 즉 오버플로우를 신경써야 하는지 생각하지 않아서 편리하겠지만 그와 반대로 제한적인 메모리와 자원으로 프로그래밍 하는 환경에 적응하지 못할 수 있다는 점이다


또한 인터프리터와 같은 언어는 데이터를 옮길 때마다 메모리의 검사와 재할당 등이 발생하는 경우가 많으므로 생각보다 오버헤드가 커지기 십상이다. 이 때문에 일정 성능 이상 올릴 수 없는 구조적 문제도 따라온다.


물론 고급 레벨의 프로그래밍이 전혀 필요하지 않은 프로그래머라면 방금 한 말은 무시해도 된다. 하지만 전문적으로 프로그래밍을 하려고 한다면 언젠가는 고급 레벨을 접근해야만 하고, 그것은 메모리, 하드웨어에 대한 지식이 필요하다는 것을 의미한다.



2. 왜 어려운 프로그래밍 언어를 알아야 하는가?

C언어는 어려운 프로그래밍 언어다. 물론 과거에 사용되던 기계어나 어셈블리어보다는 쉽겠지만 평균적으로는 어려운 언어다. 이에 비해 다른 쉬운 언어들은 빠르게 익힐 수 있지만 덜 고민하게 되고 추상화된 프로그래밍 모델로 인해 쉬운 인터페이스에 집착하는 프로그래밍 스타일을 만들게 된다.


하지만 추상화나 쉬운 인터페이스에만 병적으로 집착하면 성능은 뒷전으로 내팽개치게 되는 성향이 생길 수 있기 때문에 조심해서 접근해야 한다. 이런 말을 하면 성능 문제는 하드웨어의 발전으로 커버할 수 있다고 말하는 사람도 있지만 비용대비 성능으로 볼 때 단순히 하드웨어의 발전만으로 커버되지 않는다. (하드웨어의 발전이 더뎌진 것도 하나의 이유가 된다.[2])


이런 연유로 인해 추상화되지 않은 프로그래밍 언어, 사람보다 컴퓨터가 어떻게 작동하는지 알 수 있는 언어를 알아 둘 필요가 있는 법이다. 


물론 십수년이 지나면 이런 환경도 사라지고 새로운 패러다임이 나올 지도 모르겠지만, 아직까지 C언어가 쌓아올린 컴퓨팅 환경은 견고하고, 컴퓨팅 환경을 이해하는데 있어 C언어를 대체할 만한 것도 없기 때문에 C언어는 꼭 배워두면 좋은 언어라고 생각된다. (물론 C언어를 배운 뒤에 다른 언어를 배워두는 것은 강력 추천한다. 개인적으로 파이썬은 정말 매력적인 언어다.)

'프로그래밍 > C' 카테고리의 다른 글

포인터? 포인터변수? 포인터의 이해  (0) 2013.04.19
Double linked list with using array  (0) 2013.04.19
함수 포인터  (0) 2013.04.19
linked list [펌]  (0) 2013.04.19
Double linked list  (0) 2013.04.19
//