37-1-나.STL의 특징

일반화 프로그래밍 기법의 역사도 짧지는 않지만 구조화나 객체 지향에 비해서 세인들의 주목을 받기 시작한지는 얼마 되지 않았다. 일반화는 다른 기법들과는 뚜렷이 구분되는 여러 가지 특징들을 가지고 있다. 이 특징과 장단점에 대해 정리해 보자.

 

가장 큰 특징은 역시 이름이 의미하듯이 일반화를 지원한다는 점이다. 하나의 단일 알고리즘으로 복수 개의 컨테이너에 동일한 작업을 똑같은 방법으로 수행할 수 있다. 아직 일반화의 의미를 직감적으로 파악하기는 어렵겠지만 자료 구조마다 조작 방법이 특수한 기법과 반대의 의미라고 생각하면 된다.

컴파일 타임 메커니즘을 사용하기 때문에 실행시의 효율 저하가 거의 없다. STL을 쓰지 않았을 때의 코드에 비해 현격한 속도 차이가 없으며 어떤 경우는 오히려 더 빠르기도 하다. 그러나 고수준 라이브러리의 특성상 제대로 쓸 때만 이상적인 효율이 발휘된다는 제약도 존재한다.

객체 지향적이지 않다. 객체를 사용하기는 하지만 STL 자체가 객체를 반드시 요구하는 것은 아니다. 알고리즘 함수들은 대부분 전역 함수이며 멤버 함수로 제공되는 경우는 상대적으로 드물다. 상속의 개념도 많이 사용하지 않으며 동적 결합하는 가상 함수는 느리다는 이유로 사용하지 않는다. 모든 선택은 컴파일 중에 정적으로 결정된다.

표준이므로 이식성이 당연히 확보된다. STL로 작성한 코드는 표준을 준수하는 어떠한 컴파일러로도 문제없이 컴파일할 수 있다. 아직까지 모든 컴파일러들이 표준을 제대로 지키지 않으므로 일시적인 이식성의 문제가 있기는 하지만 모든 컴파일러가 표준을 완벽히 준수하는 미래에는 완전한 이식성이 확보될 것이다.

확장 가능하다. 소스가 공개되어 있으므로 STL 라이브러리를 분석하여 원하는 컨테이너와 알고리즘을 직접 작성하여 사용할 수 있다. 표준에 없는 요소들이 제 3 자에 의해 확장된 예는 아주 많으며 이 중 일부는 성능이 우수해서 다음 표준에 채택될 가능성이 높다.

 

이런 장점들은 라이브러리 제작자와 그 추종자들에 의해 주장되는 것인데 장점만 읽어 보면 마치 세상에서 최고의 라이브러리인 것처럼 보인다. 훌륭한 라이브러리인 것은 분명하지만 단점도 만만치 않다. 다음은 많은 사람들에 의해 흔히 지적되는 단점 또는 STL이 대중화되기 어려운 이유이다.

 

템플릿에 기반하기 때문에 타입마다 함수와 클래스가 매번 구체화되어 코드가 비대해지는 고질적인 문제가 있다. 완전히 똑같은 컨테이너라도 타입이 바뀌면 두 벌의 거대한 코드 집합이 따로 생성된다. 물론 요즘같이 풍부한 메모리 환경에서 이는 별 문제가 안될 수도 있지만 낭비의 정도가 좀 심한 편이다. 극단적으로 표현하자면 약간의 속도 향상을 위해 크기는 아예 완전히 포기한 셈이다.

STL로 작성한 코드는 가독성이 심하게 떨어진다. 템플릿 자체가 익숙치 않은 문법인데다 템플릿 클래스의 타입명이 길어 얼른 의미를 파악하기 어렵다. 게다가 이중 삼중으로 템플릿이 중첩되면 만든 사람조차도 거의 해석 불가능할 정도다. 소스의 가독성도 문제지만 에러 메시지도 의미를 해석하기 쉽지 않다. 소스가 난해하기 때문에 팀 프로젝트에 불리하며 디버깅도 어렵고 유지 보수 비용이 증가한다.

배우기에 결코 쉽지 않다. C++ 문법을 어느 정도 터득한 사람이라면 STL의 전체 개요를 보는데 일주일이면 족하다. 그러나 단순히 아는 정도가 아니라 익숙하게 사용하려면 반년 정도가 소요된다. 구조에 대한 전반적인 이해가 필요하며 최소한 한 번씩은 사용해 봐야 자신감이 붙는다. 게다가 함정도 많고 잘못 이해하면 안정성까지 위협하므로 배우려면 확실히 정석대로 배워야 한다. 익숙해지면 생산성 향상에는 크게 기여하지만 쉽게 배워서 금방 활용할 수 있는 라이브러리는 아니다. 즉, 공짜는 아니라는 얘기다.

 

게다가 템플릿은 C++의 예외 처리와 잘 맞지 않아 이 둘을 같이 사용하는 것은 대단히 어렵다. 하지만 STL에 이미 구현되어 있는 컨테이너와 알고리즘은 개발자로서 탐을 내지 않을 수 없을 정도로 매력적이며 일단 익숙해지면 생산성이 눈에 띄게 증가하는 것은 분명한 사실이다. 동적 배열, 연결 리스트, 스택 같은 자료 구조나 정렬, 검색, 대체 따위의 늘상 쓰는 알고리즘을 공짜로 쓸 수 있다니 이 유혹을 어찌 마다할 수 있겠는가?

이렇게 매력적인 라이브러리임에도 불구하고 STL이 아직까지도 그리고 앞으로도 대중화되는데 어려움이 있는 근본적인 원인은 대체물이 너무 많다는 것이다. STL 이전에 개발자들은 공짜로 쓸 수 있는 많은 컨테이너와 알고리즘들을 잘도 구해서 쓰고 있었다. 그 대표적인 예가 바로 MFC인데 이 안에는 STL의 컨테이너를 대체할 수 있는 동적 배열, 연결 리스트 들이 잘 작성되어 있으며 성능이나 신뢰성이 이미 확보되어 있다.

 

STL 요소

MFC 대체 요소

vector

CArray

list

CList

map

CMap

 

수많은 개발자가 이미 MFC 또는 그와 유사한 라이브러리에 익숙해져 있기 때문에 그 대체물인 STL을 반드시 배워야 할 필요가 없는 것이다. STL이 아니고서는 도저히 불가능한 그런 것은 없으며 STL없이도 지금까지 잘 살아왔다는 것이다. 사람들의 습관은 정말 무시 무시해서 한 번 익힌 것이 큰 문제가 없으면 계속 그 기술만 고집하기 마련이다.

앞으로는 언어의 표준 라이브러리인 STL이 점점 그 입지를 넓혀가리라 예상되지만 현재 상황은 STL에 대해 그다지 긍정적이지만은 않다. 그렇다면 공부를 하고 있는 우리는 STL에 대해 어떤 입장을 가져야 할까? 이 라이브러리를 쓸 것인가 아닌가는 개인의 취향에 따른 선택의 문제일 뿐이므로 사용 여부를 강제할 수는 없다.

그러나 배울 것인가 아닌가는 이제 더 이상 선택의 문제가 아니라 필수이다. 별 필요를 느끼지 않는다 하더라도 팀 내에서 이미 쓰는 사람이 있다면 원활한 협동 작업을 위해 팀원이 만든 소스를 최소한 읽을 수는 있어야 한다. 또한 천신만고 끝에 구한 귀중한 소스가 STL로 되어 있다면 이 또한 피할 수 없는 것이다. 더불어 사는 세상에서 최소한 개요라도 공부해 놓을 필요가 있으며 자체 검토를 한 후에 사용 여부를 결정하는 것이 합리적이다.

설사 실용적인 면에서 별 필요가 없다 하더라도 STL은 학술적으로 굉장히 큰 의미를 가지고 있다. 어디에나 두루 쓰일 수 있고 일반성과 이식성을 확보하면서도 성능을 잃지 않는 고급 기법들이 STL에 고스란히 담겨 있다. 그 똑똑한 사람들이 모여서 20년동안 다듬고 관리하고 실무에서 검증까지 거친 소스라는 점을 생각해 보면 이 만큼 좋은 연구 대상도 없는 셈이다. C++을 진정 깊이있게 연구해 보고 싶다면 STL을 연구해 보자.

STL이 C++의 표준이 된 이상, 그리고 실제 프로그래밍에 사용되고 있는 이상 STL 학습은 필수 코스임이 분명하다. 그러나 우선 순위는 조금 낮게 잡아도 상관없다. STL은 기법 자체가 고급스러워 선수 과목이 굉장히 많은 기술이다. C/C++ 언어에 대한 깊은 이해는 물론이고 자료 구조, 알고리즘에 대한 기본적인 개념이 있어야 STL을 제대로 공부할 수 있다. 만약 아직 C++로 프로젝트를 한 번도 해 본 적이 없다면 C++ 문법에 좀 더 익숙해진 후에 STL을 학습하는 것이 좋다.