2. Qt의 기능 및 활용전략
Qt의 설계자체가 Platform Independent한 설계를 위해 작성된 라이브러리여서 GUI 뿐만 아니라 GUI외적인 요소들을 포함하여 플랫폼 독립적으로 동작 가능하도록 설계되어 있습니다. 이러한 설계자체가 Embedded Linux특화된 제품에 있어서 그다지 큰 메리트는 아니지만, X11/Mac/Windows용 프로그램을 작성할 때 큰 이점이 될 수 있습니다.
Embedded Linux측면에서 본다면 개략적인 초안을 Windows나 X11환경에서 작업해놓고 포팅을 할 수 있다는 의미와 같습니다.
Qt가 단순 GUI를 표현하는 것 외에 추가 기능을 가지고 있다면 프로그램 개발에 있어서 사용하지 않을 이유는 없을 것 입니다. 하지만 경우에 따라서 Embedded 기기에서 실행시키기에는 너무나 부하가 많이 걸리는 부분이나 필요없다고 판단하는 부분은 잘 선별해서 검토를 해야합니다.
가령 Ethernet이 없는 기기에서 동작되는 프로그램을 개발하거나 DB가 필요치 않는 프로그램을 개발하는데 Qt가 가지는 Network, DB 관련 클래스는 필요없이 존재하고 있는 부하가 될 소지가 있습니다. Embedded 기기자체가 작은양의 NOR/NAND의 저장장치, 메모리를 사용하고있는 상황에서 개발비 상승을 가지고 올 수 있는 부분을 제거 하는 것이 올바른 선택이라고 생각합니다.
Qt는 필자 제 나름대로 크게 두 가지로 나누어 보고 각각의 항목에 대해서 추가적으로 나누어 보았습니다. 앞서 언급한대로 GUI와 GUI외적인 요소인데 그 내용은 아래와 같습니다. 아래에서는 간략히 큰 흐름과 간략한 설명을 하고 추후에 다시 이에 대한 자세한 내용을 살펴보도록 하겠습니다.
2.1 GUI
Qt의 GUI시스템은 Core System과 Widget set을 갖습니다. Core System은 QApplication객체로서 main()함수를 통해 프로그램을 처음 시작할 때 QApplication객체를 생성하고 이 생성된 객체의 exec()함수를 호출해서 message dispatch 루틴을 호출합니다.
Message dispatch는 계속 반복적으로 loop을 수행하며 사용자의 입력(마우스(터치패드),키보드, 기타)장치로부터 받은 것을 처리하거나, GUI 동작에 필요한 각종 제어들이 수행됩니다.
QApplication 위에는 실제 화면에 보여주기 위한 Widget들이 화면에 표시되는데 이러한 Dialog, Tab, Button, Label, List등등의 일반적으로 볼 수 있는 Widget들이 갖추어져 있습니다.
만약 PDA, Windows 운영체제와 유사한 기기를 개발한다면 이를 그대로 사용해도 무리가 없겠지만 만약 TV나 PDA, Windows운영체가 아닌 가전의 느낌을 가지도록 해야한다면 새롭게 작성되어야 합니다.
새롭게 작성된다는 의미가 처음부터 새로 개발하는 것이 아나라 이미 잘 갖추어진 Qt의 Widget들을 재 상속받아서 필요한 부분만 재정의해서 구현한다면 큰 힘을 들이지 않고 이용을 할 수 있습니다.
Qt가 내세우고 있는 signal/slot이라는 개념은 Win32 API등에서 볼 수 있었던 무수한 switch case의 노동(?)에서 자유로울 수 있습니다. Signal/slot이라는 간결하고도 쉬운구조로 인해서 GUI 프로그래밍에서 메시지처리의 지저분한 디자인을 한층더 간결하게 만들어 줍니다.
2.2 Non GUI
GUI외적인 요소들은 크게 다음과 같이 정리할 수 있습니다.
2.2.1 Thread
만약 Multi Thread로 작성되는 프로그램을 개발해야 한다면 GUI가 수행중에 다른 Thread를 생성해서 이를 처리해야 할 것 입니다. 이때 QThread라는 pthread wrapper class는 design측면에서 또한 GUI요소들과 병행해서 처리해야 할 때 동기화 문제 및 thread safe문제들을 쉽고 명확하게 해결해 줄 수 있습니다.
pthread로 처리해야할 때 난무하는 각종 처리부분들이 하나의 thread class로 구분되어 작성된다면 디버깅이 난해한 thread처리에 있어서 많은 이점을 가져다 줄 수 있습니다.
2.2.2 Network
최근 Ethernet이 기본장착된 제품이 많은 상황에서 요구되는 TCP/UDP 프로토콜 기반처리를 쉽게 처리할 수 있는 기반을 제공합니다. 동기/비동기 처리에 있어서 굳이 Multi thread환경으로 작성하지 않아도 될 정도로 깔끔하게 잘 정돈되어 있습니다.
2.2.3 DB
DB를 처리해야 하는 부분이 있다면 Qt의 단일화된 인터페이스로 여러가지 DB에대해서 일관된 인터페이스로 처리할 수 있도록 되어 있습니다.(ODBC와 같은 개념) 따라서 DB관련 처리부분에 있어서도 이를 적극활용하면 각각의 DB마다 조금씩 다른 특성을 Qt의 하나의 일관된 스타일로 처리할 수 있습니다.
2.2.4 기타 Helper class(Date, Time, STL등)
GUI 프로그램을 작성하다보면 현재시간을 구해서 시간차이를 계산하는 경우, Queue, List등의 자료구조를 이용해야 하는일이 빈번합니다. 이러한 것 역시 여러가지 형태의 클래스로 제공을 하고 있습니다.
Qt의 STL의 경우에는 Standard Template Library와 성능에 있어서는 조금 비효율적일 수 있으나 MFC의 afxtempl.h 에 정의된 Template Library와 같은 이유에서 존재하고 있습니다.(여러가지 의견이 있을 수 있으나 필자의 견해로는 Naming Notation등을 맞추어서 깔끔하게 처리할 수 있다는 점과 STL에서 제공하지 못하는 추가적인 기능을 부여해서 편하게 하는데 있다고 생각합니다.
Standard STL의 경우 알고리즘의 효율을 위해서 편리성보다는 성능을 중시하는 방면(가령, std::vector에서는 MFC의 CArray처럼 가운데 삽입자체가 불가능) 일반 응용프로그램 작성에 있어서 vector의 가운데 삽입으로 인한 성능저하가 쉽게 일어나지 않는점을 반영한 지원의 경우가 있을 수 있다고 생각합니다. )
위와같이 Qt의 각 요소들을 살펴보았다면 실제 개발에 있어서의 활용범위를 정하고 이를 적극적으로 이용하는 것이 타당하다고 생각합니다. 이미 자신만이 가진 솔루션이 있다고 할지라도 이미 많은 사람들에 의해서 검증되고 있는 부분을 적용하는 것이 현명한 생각이라고 봅니다.
가령 내가 대학교다닐적 linked list 알고리즘을 배우고 구현했던 그대로를 제품 그대로 적용하는것과 잘 만들어진 std::list 를 적용하는 문제와 같다고 봅니다.
또하나의 예를들면 아래와 같은 두개의 예제코드를 보면
예1)
int fd = ::open(“/xxx.dat”, …);
/// 처리…
close(fd);
예2)
QFile f;
f.open(“/xxx.dat”, …);
위와같이 두가지 예제는 언뜻보면 별 차이도 없고 Qt로 해도 무슨관계가 있냐고 하실지 모르겠지만 예2)와 같은 코드는 프로그램을 안전하게 만들어 줍니다.
예1)의 상황윽 open과 close로 항상 pair로 동작되어야 안전합니다. 하지만 만약, open을 해서 handle을 얻은후 각종 if등의 제어구조 때문에 close함수를 처리못하는 버그가 있고 이를 발견하지 못한체 계속 수행된다면 handle leak으로 인해 프로그램이 정상적으로 수행되지 못하는 불운의 사태를 맞이하게 됩니다.(실제로 이 문제 때문에 엄청 고생한적이 있습니다.)
하지만 예2)의 경우 설령 open뒤에 제어구조로 인해 close를 호출못했다고 할지라도 QFile 의 destructor에서 자동으로 close()를 호출하므로 절대 handle leak이 발생하지 않을 것입니다.
간단한 차이지만 이러한 차이점들이 실제 제품개발에 있어서 최종 제품 양산직전에 고생하게 만드는 골치로 작용될 것 입니다. 비록 간단한 예이지만 Qt의 잘 설계된 클래스들은 우리가 직접 설계한 그것보다 system call원형호출보다 실 수할 가능성을 줄여줍니다.
자료 출처
korone.net programming 사이트를 운영하고 계시는 조병완님의 글, 세 번째 시간
"[03] Embedded C++ GUI Programming with Qt - Qt의 기능 및 활용전략" 입니다.
No comments:
Post a Comment