Marco Cantu의 블로그에서 흥미로운 주제가 있어서 번역하였습니다. 본문에는 해당 요소들에 대한 링크가 있어서 더 깊이있게 이해할 수 있습니다.

제네릭 타입은 델파이 2009 버전에 추가되었습니다. 델파이의 런타임 라이브러리 (RTL)에는 제네릭 컬렉션 유닛이 들어간 것도 이때부터입니다. 하지만 RTL에는 제네릭 컬렉션 뿐만 아니라 기존에 있던 클래식 컬렉션도 여전히 남아 있습니다. 최근에 저는 예전 컬렉션과 새 컬렉션 중 어느 것을 사용하면 더 좋은 지에 대한 질문을 받고 심도있는 토론을 이어갔습니다. 이 토론의 개요를 이 글로 정리합니다.

 

클래식 컨테이너 클래스

RTL에 있는 가장 기본적인 컬렉션 클래스는 (System.Classes 유닛에 있는) TList 클래스입니다. 이것은 포인터들 (또는 개체의 참조들)을 담는 일반적인 리스트입니다. 같은 계열인(System.Contnrs 유닛에 있는) 클래식 컨테이너 클래스(들)로는 다음과 같은 것들이 있습니다:

  • TObjectList는 TObject의 참조들을 담는 TList로, 객체에 대한 소유권(Ownership)* 지원을 포함
  • TComponentList 또한 소유권을 가지며, 컴포넌트 알림(Notification: 생성 및 해제 알림)**을 지원
  • TClassList
  • TOrderedList
  • TStack과 TQueue, TObjectStack과 TObjectQueue
  • 다양한 BucketList(해시 테이블)

위 컨테이너들을 사용할 때에는 종종 여러분이 다루고 있는 개체의 타입을 변환(cast)하여 해당 리스트가 지원해주는 타입에 맞추게 되기 때문에 오류가 생길 가능성이 발생합니다. 만약 여러분이 해당 리스트에서 꺼낸 개체의 타입을 계속 확인하기 위해 “as” 와 같이 동적 변환(dynamic cast)을 사용한다면 프로그램 실행이 느려지는 원인이 되기도 합니다.

myList: TList;
myList.Get(3) as TMyObject

소유권(Ownership)*: 소유권을 위임하면 소유주(Owner) 객체 해재시 소유권을 위임한 객체를 함께 해제합니다. 즉 TObjectList에 소유권 위임 설정(OwnsObjects := True)하면 TObjectList 해제 시 등록된 객체를 함께 해제합니다.

컴포넌트 알림(Notification)**: TComponent는 Notification 메소드를 제공합니다. Notification 메소드는 소유하고 있는 모든 컴포넌트에 소유권 추가와 삭제 메시지를 전달합니다.

 

제네릭 컬렉션 클래스

언어에 제네릭 타입(들)이 추가되면서 델파이에는 제네릭 컬렉션(들) 기본 세트가 추가되었습니다. 이 세트는 System.Generics.Collections 유닛에 있으며, 컨테이너에 담고 싶은 데이터 타입을 여러분이 직접 지정할 있도록, 제네릭한 (, 컨테이너에 담길 타입이 사전에 특정되지 않은) 컨테이너의 밑그림을 제공합니다. 제네릭 컬렉션(들)에는 다음과 같은 것들이 있습니다:

  • TList<T>, 기본 제네릭 리스트로 정렬과 열거(enumeration) 지원합니다.
  • TThreadList<T>, 쓰래드에 안전한 리스트로서 잠금(locking)을 지원합니다.
  • TQueue<T>, TStack<T>
  • TDictionary<TKey,TValue>, 상당히 막강한 딕셔너리이며, 키(key)와 값(value)의 타입을 필요에 맞게 지정할 수 있습니다.
  • TObjectList<T: class> 객체 타입을 담을 수 있으며 소유권을 지원합니다.(아래의 컨테이너들도 동일)
  • TObjectQueue<T: class>, TObjectStack<T: class>
  • TObjectDictionary<TKey,TValue>
  • TThreadedQueue<T>

제네릭 컬렉션의 장점

제네릭스 컬렉션(들)을 사용하면 여러분이 사용하고자 하는 데이터 타입을 담을 특정 컨테이너(들)을 정의할 수 있습니다. 그러면 해당 데이터 타입에 부합하는 지를 컴파일러가 확인하므로 실행 중에 데이터 타입을 확인하지 않아도 됩니다. 그 결과, 코드가 더 깔끔하고 읽기도 더 쉽습니다. 애플리케이션은 더 견고해지고, 실행 시점에 확인할 필요가 줄어들기 때문에 실행 속도도 빨라집니다:

myList: TList <TMyObject>;
myList.Get(3); // TMyObject 반환

델파이에서 새로 추가되는 라이브러리와 서브시스템들은 모두 제네릭 컬렉션(들)을 사용합니다. 예를 들어 파이어몽키는 전통적인 코딩 스타일이 아니라 제네릭 컬렉션(들)을 주로 활용합니다.

 

제네릭 컬렉션을 사용하면 안될 이유는 어떤것이 있나요?

제네릭 컬렉션(들)을 사용하면 안되는 경우는 기본적으로 다음 두 가지가 있습니다.

첫째, 작동하고 있는 기존 코드가 있다면 여러분은 굳이 변경하고 싶지 않을 것입니다. 특히 VCL과 같은 라이브러리에 들어있는 기존 코드를 변경하면, 해당 라이브러리를 사용하는 코드(들)에서 타입 불일치 문제가 발생될 수 있습니다.

둘째, 델파이에 있는 제네릭(들)은 상당한 코드 비대화(Code bloat)을 유발합니다. 컬렉션에서 사용되는 데이터 타입이 거의 같더라도 다양한 데이터 타입을 위한 메소드들이 매번 복제되기 때문입니다. 이점은 굉장히 규모가 큰 애플리케이션에서라면 컴파일 시간과 링크 시간 그리고 실행 파일 크기 측면에서 부정적인 영향을 끼칩니다.

 

 

또 다른 제네릭 컬렉션

마지막으로, 전하고 싶은 점이 있습니다. 만약 여러분이 제네릭 컬렉션(들)을 상당히 많이 사용한다면 스프링4D (Spring4D) 라이브러리에 있는 것들을 고려하시기 바랍니다. 이 라이브러리는 RTL에 있는 것들을 확장한 것입니다. 관련 도움말은 https://bitbucket.org/sglienke/spring4d/wiki/Collections 에 있습니다.

 

다시 말씀드리지만 이 글은 짧은 요약입니다. 훨씬 더 광범위하고 세밀하게 설명할 수도 있겠으나 델파이의 제네릭 컬렉션(들)을 충분히 알지 못해서 예전 방식만 사용하고 있는 개발자들이 있다면 이 요약 만으로도 도움이 되기를 바랍니다.

 

 

참고자료


번호 제목 글쓴이 날짜 조회 수
공지 [DelphiCon 요약] 코드사이트 로깅 실전 활용 기법 (Real-world CodeSite Logging Techniques) 관리자 2021.01.19 15442
공지 [UX Summit 요약] 오른쪽 클릭은 옳다 (Right Click is Right) 관리자 2020.11.16 13962
공지 [10.4 시드니] What's NEW! 신기능 자세히 보기 관리자 2020.05.27 16499
공지 RAD스튜디오(델파이,C++빌더) - 고객 사례 목록 관리자 2018.10.23 22055
공지 [데브기어 컨설팅] 모바일 앱 & 업그레이드 마이그레이션 [1] 관리자 2017.02.06 23268
공지 [전체 목록] 이 달의 기술자료 & 기술레터 관리자 2017.02.06 18923
공지 RAD스튜디오(델파이, C++빌더) - 시작하기 [1] 관리자 2015.06.30 39257
공지 RAD스튜디오(델파이,C++빌더) - 모바일 앱 개발 사례 (2020년 11월 업데이트 됨) 험프리 2014.01.16 174713
563 [고객 사례- 의료, 델파이] COVID-19 - 검사 결과 실시간 확인 앱 관리자 2020.03.25 788
562 웹 영역으로의 확장을 위한 크로스-플랫폼 웹 애플리케이션 개발 방법 - Ext JS 관리자 2018.12.11 785
561 [업데이트][핫픽스][10 시애틀] OS X 앨 캐피텐 지원과 iOS SDK 호환성 강화를 위한 PAServer 핫픽스 출시 험프리 2015.10.02 783
560 [기술백서] 델파이와 Windows 개발 현황 (Windows 개발 관련 핵심 사항 정리) 관리자 2020.05.29 783
559 이 달의 기술자료 - 2016년 03월 [1] file 험프리 2016.02.25 779
» 델파이 RTL: 새로운 제네릭 컬렉션 vs 기존 클래식 컬렉션 험프리 2020.01.06 777
557 이 달의 기술자료 - 2018년 03월 file 험프리 2018.02.23 775
556 [다음 버전 정보] 안드로이드 서비스로 백그라운드 작업을 실행할 수 있습니다. Humphery 2015.08.25 774
555 [고객사례-브라우저, 델파이] BriskBard 관리자 2018.05.10 770
554 [10.3 리오] High DPI가 적용된 이미지 리스트로 다양한 해상도의 이미지를 지원할 수 있습니다. 험프리 2018.12.05 769
553 파이어닥(FireDAC)으로 IBLite 연결 시 "unavaliable database." 오류 발생에 대한 대응 file Humphery 2015.05.15 768
552 [고객 사례- 3D, 이미지스캐너, 델파이] mimix 3D 프로필 스캐너 관리자 2017.04.13 768
551 [DelphiCon 요약] High DPI 고해상도를 VCL에서 활용하기 (Leveraging High DPI in VCL Applications) 관리자 2021.01.13 767
550 C++빌더와 파이어몽키로 정말 멋진 UI 완성하기: 앱 템플릿 관리자 2018.06.20 767
549 [시애틀] 알림, 계약(Contract) 등의 윈도우 10 서비스 기능을 컴포넌트와 API로 쉽게 활용할 수 있습니다. 험프리 2015.09.02 766
548 1차 공개 중고생 강의용 앱 소스 및 메뉴얼입니다. file 쭈니아빠 2016.07.16 762
547 델파이용 벡터 컨테이너 file 김원경 2020.04.14 760
546 [고객 사례- 솔루션, 델파이] Beyond Compare - 데이터, 시스템 비교/병합/관리 프로그램 관리자 2020.05.14 758
545 [고객사례-비콘, 위치 추적, RAD스튜디오, RAD서버] BEAM 관리자 2018.04.18 757
544 RAD Studio(델파이/C++빌더) 모바일 앱 배포하기 관리자 2017.01.16 757