2007년 01월 26일
[STL] 개요
1. 특징
일반화 프로그래밍 기법의 역사도 짧지는 않지만 구조화나 객체 지향에 비해서 세인들의 주목을 받기 시작한지는 얼마 되지 않았다. 일반화는 다른 기법들과는 뚜렷이 구분되는 여러 가지 특징들을 가지고 있다. 이 특징과 장단점에 대해 정리해 보자.
① 가장 큰 특징은 역시 이름이 의미하듯이 일반화를 지원한다는 점이다. 하나의 단일 알고리즘으로 복수 개의 컨테이너에 동일한 작업을 똑같은 방법으로 수행할 수 있다. 아직 일반화의 의미를 직감적으로 파악하기는 어렵겠지만 자료 구조마다 조작 방법이 특수한 기법과 반대의 의미라고 생각하면 된다.
② 컴파일 타임 메커니즘을 사용하기 때문에 실행시의 효율 저하가 거의 없다. 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없이도 지금까지 잘 살아왔다는 것이다. 사람들의 습관은 정말 무시 무시해서 한 번 익힌 것이 큰 문제가 없으면 계속 그 기술만 고집하기 마련이다.
2. STL 구조
컨테이너, 알고리즘, 반복자가 가장 중요한 세 요소이며 STL 학습의 대부분이 이 세 요소에 치중된다. 네 번째 요소인 함수 객체는 알고리즘의 활용성을 높이는 역할을 하며 다섯 번째 요소인 어댑터는 다른 요소들을 약간만 수정하여 형태를 변형한다. 마지막 구성 요소인 할당기는 컨테이너의 메모리를 관리하는 객체인데 디폴트가 잘 작성되어 있으므로 거의 신경쓸 필요가 없다.
3. 컨테이너의 종류
컨테이너(Container)를 뜻 그대로 직역하면 통, 그릇이다. 쌀통에 쌀을 담고 술통에 술을 저장하듯이 컨테이너는 무엇인가를 저장하는 것이다. STL의 컨테이너는 타입이 같은, 즉 동질적인 객체의 집합을 저장하고 관리하는 역할을 하는데 C와 C++에서 배웠던 배열, 연결 리스트, 스택 따위가 컨테이너의 좋은 예이다.STL의 컨테이너는 자료를 저장하는 방식과 삽입, 정렬, 삭제하는 관리 방식에 따라 여러 가지가 있는데 크게 세 가지 부류로 구분된다.
① 시퀀스 컨테이너(Sequence Container) : 자료의선형적인 집합이며 자료를 저장하는 기본 임무에 충실한 가장 일반적인 컨테이너이다. 삽입된 자료를 무조건 저장하며 입력되는 자료에 특별한 제약이나 관리 규칙은 없다. 사용자는 시퀀스의 임의 위치에 원하는 요소를 마음대로 삽입, 삭제할 수 있다. STL에는 벡터, 리스트, 데크 세 가지의 시퀀스 컨테이너가 제공된다.
② 연관 컨테이너(Associative Container) : 자료를 무조건 저장하기만 하는 것이 아니라 일정한 규칙에 따라 자료를 조직화하여 관리하는 컨테이너이다. 정렬이나 해시 등의 방법을 통해 삽입되는 자료를 항상 일정한 기준(오름차순, 해시 함수)에 맞는 위치에 저장해 놓으므로 검색 속도가 빠른 것이 장점이다. 표준 STL에는 정렬 연관 컨테이너인 셋, 맵 등의 컨테이너가 제공된다.
③ 어댑터 컨테이너(Adapter Container) : 시퀀스 컨테이너를 변형하여자료를 미리 정해진 일정한 방식에 따라 관리하는 것이 특징이다. 스택, 큐, 우선 순위 큐 세 가지가 있는데 스택은 항상 LIFO의 원리로 동작하며 큐는 항상 FIFO의 원리로 동작한다. 자료를 넣고 빼는 순서를 외부에서 마음대로 조작할 수 없으며 컨테이너의 규칙대로 조작해야 한다.
세 부류의 컨테이너는 삽입, 삭제 규칙에 있어서 차이가 있다. 시퀀스는 삽입, 삭제에 별 제약이 없지만 연관 컨테이너는 신속한 검색을 위해 찾기 좋은 위치에 자동 삽입되며 어댑터는 FIFO, LIFO 등의 미리 정한 규칙의 통제를 따른다. 그러나 자료의 집합을 저장한다는 기능적인 면에서는 동일하며 그래서 제공하는 함수가 거의 비슷하고 사용 방법도 유사하다
4. 컨테이너의 선택
각 컨테이너들은 고유의 장단점을 가지고 있으며 모든 경우에 최적인 이상적인 컨테이너는 존재하지 않는다. 만약 모든 면에서 우월한 컨테이너가 존재한다면 나머지 컨테이너들은 더 이상 존재할 가치가 없을 것이다. 그러나 특정한 상황에 가장 잘 어울리며 성능상 가장 유리한 컨테이너는 존재할 수 있다. 컨테이너별로 잘난 점과 못난 점이 있다는 얘기다.
개발자는 관리하고자하는 데이터의 특성과 응용 프로그램의 요구에 맞는 컨테이너를 주의 깊게 선정해서 사용해야 하며 그러기 위해서는 각 컨테이너의 자료 저장 방식과 관리 방법에 대해 잘 파악하고 있어야 한다. 예를 들어 리스트는 검색은 느리지만 삽입, 삭제가 빠르므로 수시로 변하는 자료에 적합하고 벡터는 삽입, 삭제가 느리지만 읽기 속도가 빠르므로 대용량의 참조용 자료에 적합하다.
컨테이너 선택이 잘못되면 프로그램의 전체적인 성능은 보장할 수 없으며 안전성에도 많은 차이가 발생한다.
이 글과 관련있는 글을 자동검색한 결과입니다 [?]
- STL 컨테이너 정리 by 쌩쥐
- 어떤 컨테이너에 어떤 객체를 넣을 때... by 쌩쥐
- 컨테이너에서 데이터를 삭제할 때에도 조심조심 by 쌩쥐
- 상등성(equality)과 동등성(equivalen.. by 쌩쥐
- vector<bool>에는 실제로 bool이 들어 .. by 쌩쥐
# by | 2007/01/26 18:11 | └STL | 트랙백 | 덧글(0)





☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]