QtGraphs 개선점 이해 및 활용하기 - 1편
2월 18, 2025 by Nicolas Jeon | Comments
안녕하세요, 반갑습니다.
이번 블로그 시리즈에선 Qt6에서 개편된 QtGraphs 모듈에 대하여 이야기하려 합니다. 목표로 하는 것은 QtGraphs 모듈의 기본 개념과 Qt6에서의 구조적 개선점들을 설명하여, 사용자들이 기술적 이해를 바탕으로 더 적극적으로 QtGraphs를 활용하도록 돕는 것입니다. 블로그 1편에서는 QtGraphs와 관련된 기본적인 개념들을 설명하고, 2편에서는 개선점의 구체적인 내용들을 이야기 합니다.
개요
QtGraphs는 데이터의 2D/3D 시각화를 지원하는 모듈입니다. 이 모듈은 Qt 5 버전에서 2D는 QtCharts 모듈, 3D는 Data Visualization 모듈로 각각 소개되었으나, Qt 6에서 QtGraphs라는 하나의 모듈로 통합이 되었습니다. Qt6에서의 통합은 단순한 기능 통합은 아니며, 내부 구조를 개선하여 전에 비해 더 많은 장점을 누릴 수 있게 되었습니다.
본 글에서는 Qt의 Model View Programming의 관점에서 QtGraphs 모듈을 이해해보고 각 요소들을 소개합니다. 또한 본 글에서 다룬 개념들을 연습하기 위해 파도의 최고점을 시각화하는 간단한 QtGraphs 예제를 작성해보는 시간을 가집니다. 예제 작성은 블로그 2편까지 이어서 진행되니, 끝까지 함께 해주시면 감사하겠습니다.
QtGraphs 주요 개선점은?
Qt5 대비 Qt6에서의 QtGraphs 모듈의 대표적인 장점을 먼저 요약하면 아래와 같습니다.
-
다양한 플랫폼에서의 성능 안정화
Qt5의 QtChart나 Data Visualization 모듈에서 OpenGL 외의 엔진을 활용한 성능 가속에는 어려움이 존재했습니다. Qt6의 큰 특징 중 하나는 Rendering Hardware Interface (이하 RHI) 를 통해 렌더링 인터페이스를 추상화하여 Mac, Linux, Window 등 다양한 플랫폼에서 Qt가 알맞은 Rendering 엔진을 선택할 수 있게 된 것입니다. 이것이 적용된 모듈 중 하나가 QtQuick3D 모듈입니다. QtGraphs 모듈은 QtQuick3D 모듈을 활용하도록 개편되었으며 자연스럽게 RHI의 이점을 누릴 수 있게 되었습니다. 즉, 다양한 플랫폼에서 QtGraphs 모듈을 사용하여도 적절한 Rendering 엔진이 선택되어 성능상의 안정성을 누릴 수 있습니다. -
향상된 3D 시각 효과와 확장성
QtGraph가 QtQuick3D를 사용함에 따라, Quick3D의 시각 효과들을 QtGraphs에 적용할 수 있게 되었습니다. 예를들어 Scene Environment, Light Control과 같은 기능들을 QtGraph에 적용할 수 있습니다. 또한 반대로 QtGraph를 Quick3D 어플리케이션에도 주입할 수 있게 됩니다. 이렇게 데이터의 3D 시각화 기능이 추가 되고 Quick3D와의 호환성이 확장되었으며, 앞으로 Quick3D에 추가될 기능들에 대해서도 적용 및 확장될 확률이 높습니다.
개선점에 대한 구체적인 내용은 블로그 2편에서 다루고 있으니 참고부탁드립니다.
QtGraphs 기본 개념
Model/View 관점에서의 QtGraphs
QtGraphs 모듈은 Qt Quick/Widget과 유사하게 Model/View Programming 구조를 따르고 있습니다. 이는 View를 Data로부터 분리하여 더 유연하고 확장성 있는 개발 구조를 제공하는 것을 목적으로 합니다. QtGraphs의 개발 방식을 이해하려면 각 View와 Model에 어떤 요소들이 있는지 식별하고 각 요소의 역할이 무엇인지 이해하는 것이 중요합니다. Qt 6.8 기준 QtGraphs 모듈의 요소들을 Model/View 관점에서 다이어그램으로 표현하면 아래와 같습니다.
위에서 보면 2D/3D의 View는 각각 GraphsView와 GraphsItem3D로 정의되어 있으며, Model의 경우 2D/3D는 각각 AbstractSeries와 Abstract3DSeries로 정의되어 있습니다. Series의 경우 기본적으로 데이터를 소유하고 있기에 Model이지만, View 역할도 수행을 합니다. QtGraphs의 최상위 View에서는 동시에 여러 개의 그래프들을 표현할 수 있고, 하나의 그래프를 대변하는 것이 하나의 Series입니다. 개별 그래프의 View 적인 요소를(예를 들면 delegate, visibility 등) Series에서 설정할 수 있습니다.
2D 데이터와 3D 데이터의 비교
3D 데이터는 일반적으로 2D 데이터에 비해 더 크고 복잡합니다. 보통 2D 데이터는 1차원 배열에, 3D의 경우 2차원 배열에 데이터가 저장됩니다. 2차원 배열의 경우 1차원 배열에 비해 용량도 크고 다루기도 더 복잡합니다. 이러한 특징 때문에 3D 그래프에서는 Data Proxy라는 추가적인 Model Layer가 존재합니다. 3D의 데이터 관리 비용이 높기 때문에, Data Proxy 레이어를 통해 복잡도를 줄이고자 함입니다. 이 Data Proxy들은 다양한 3D 데이터를 직접 해석하여 Series에 제공하는 역할을 하고 있습니다. 아래는 현재 지원되는 몇 가지 Proxy 유형들입니다:
- Item Model Proxy: ItemModel 타입의 데이터를 해석하는데 사용됨
- Height Map Proxy: HeighMap 데이터를 해석하는데 사용됨
아래는 뷰, 모델 및 데이터를 계층적으로 보여주는 Scatter3D 예제 코드입니다. Scatter3D는 하나의 3DSeries를 보유하고 있고, 3DSeries는 데이터 특성에 맞는 DataProxy를 보유하고 있습니다. ListModel은 궁극적으로 QAbstractItemModel을 상속 받기 때문에, ItemModelScatterDataProxy를 사용하고 있는 모습입니다. 아래의 ItemModelProxy에서는 데이터의 해석을 위해, ListModel의 각 요소에 X, Y, Z 값에 사용될 Role을 부여하고 있습니다.
Scatter3D {
anchors.fill: parent
Scatter3DSeries {
dataProxy: ItemModelScatterDataProxy {
itemModel: ListModel {
ListElement { x: 1; y: 2; z: 3 }
ListElement { x: 2; y: 4; z: 6 }
ListElement { x: 3; y: 6; z: 9 }
}
xPosRole: "x"
yPosRole: "y"
zPosRole: "z"
}
}
}
코딩 실습으로 개념 익히기
본 글에서 설명한 QtGraphs의 개념을 익히기 위해, 간단한 코딩 실습을 진행해보겠습니다. 실시간으로 파도의 최고점을 표시하는 간단한 QML 앱을 QtGraphs Surface3D를 사용해 만들어 보겠습니다. 이 예제를 통해 QtGraphs의 기본적인 활용 방법을 이해하고, 실시간 데이터 시각화에 대해 더 잘 이해할 수 있을 것입니다. 본 예제는 블로그 2편까지 이어서 작성됩니다. 🌊
본 편에서는 1단계와 2단계를 진행합니다:
- 그래프 모델 생성하기 (블로그 1편)
- 그래프 뷰 생성하기 (블로그 1편)
- 커스텀 3D 객체 추가해보기 (블로그 2편)
- 3D 시각 효과 적용해보기 (블로그 2편)
모든 실습 코드는 https://github.com/NicolasJeon/ocean_wave_peak/tree/main 에 있으니 참고 부탁드립니다.
그래프 모델 생성하기
먼저 파도를 표현하는 3D 데이터 모델을 설계해야 합니다. 앞서 QtGraphs의 3D 모델은 Series와 Data Proxy로 이루어져 있는 것을 확인했습니다. 우리의 파도 데이터는 QSurfaceDataProxy를 상속받아 WaveDataProxy라는 커스텀 Proxy를 만들 것 입니다. 그리고 이 WaveDataProxy가 Series에게 제공될 것 입니다. 성능을 고려하여 DataProxy는 C++ 코드로 구현할 것이며, QSurfaceDataProxy를 상속받아 WaveDataProxy라는 커스텀 Proxy 타입을 정의할 것 입니다. 아래는 C++ 헤더 파일입니다:
class WaveDataProxy : public QSurfaceDataProxy
{
Q_OBJECT
QML_ELEMENT
public:
WaveDataProxy();
void update();
private:
WaveDataGenerator m_dataGen;
};
WaveDataProxy 클래스는 데이터를 생성할 WaveDataGenerator를 가지고 있습니다. WaveDataGenerator는 별도의 스레드에서 가상의 파도 데이터를 생성하고 자신의 캐시에 이를 저장한 이후 dataGenerated 시그널을 생성할 것입니다. WaveDataProxy는 이 시그널을 받아 캐시로부터 데이터를 가져와 업데이트합니다.
파도 데이터를 생성하는 코드는 ChatGPT-4를 활용하여 작성하였습니다. 전체 코드는 아래 링크를 참조해주세요.
이제 데이터 모델에 대한 간단한 세팅이 되었습니다. 다음은 View를 생성하여 봅시다.
그래프 뷰 생성하기
앞서 우리는 전체 그래프 공간을 나타내는 메인 뷰, 그리고 하나의 그래프를 나타내는 Series가 존재하는 것을 확인했습니다. 메인 뷰인 Surface3D와 파도를 나타낼 Series를 각각 아래와 같이 생성합니다. 단순함을 위해 우리는 120x120 크기의 평면에 높이 -5 ~ 13M의 공간만을 사용한다고 가정하겠습니다:
import QtQuick
import QtGraphs
Item {
property alias seaSurfaceGraph : seaSurfaceGraphId
property alias surfaceSeriesId : surfaceSeriesId
anchors.fill: parent
Surface3D {
id: seaSurfaceGraphId
anchors.fill: parent
axisX: Value3DAxis { max: 120; min: 0 }
axisY: Value3DAxis { max: 13; min: -5 }
axisZ: Value3DAxis { max: 120; min: 0 }
Surface3DSeries {
id: surfaceSeriesId
}
}
}
이제 뷰와 데이터 모델을 통합하는 과정입니다. 우리가 생성한 Surface3DSeries에 우리가 생성한 WaveDataProxy를 아래와 같이 주입해줍니다.
import QtQuick
import SeaAnalysis
SeaSurfaceForm {
WaveDataProxy {
id: waveDataProxyId
}
Component.onCompleted: {
surfaceSeriesId.dataProxy = waveDataProxyId;
}
}
코드를 실행하면 아래와 같이 파도를 생성하는 Surface3D가 생성되는 것을 확인할 수 있습니다. 아직은 Custom 객체나 Texture, 시각 효과 등을 적용하지 않았기 때문에 가장 기본적인 형태만 갖추고 있습니다. 2편에서 추가적인 개념들을 설명하고 이를 예제에 적용하여, 바다 형태에 더 가깝게 하고 파도 최고점을 나타내는 지표를 추가할 것입니다.
정리하며
이번 글에서는 QtGraphs 모듈의 기본 개념들을 살펴보았습니다. 이는 기존의 Data Visualization 모듈에도 그대로 적용되는 개념입니다. QtGraphs에 적용된 모델/뷰 프로그래밍 개념을 살펴보고 각 요소가 어떤 역할을 하는지 확인해보았습니다. 또한, 3D 데이터 작업이 2D 데이터와 비교하여 가지는 복잡성과 3D 그래프를 위한 모델을 설계할 때 Data Proxy와 같이 추가적으로 고려해야 할 사항들을 탐구했습니다. 마지막으로, 이 글에서 다룬 개념들을 적용하여 QtGraphs를 사용한 파도 최고점 분석 앱을 부분적으로 만들어 보았습니다.
다음 2편에서는 QtGraphs 모듈로 개편되며 발생한 기술적 개선점에 대해 다루고, 이러한 개념들을 우리의 파도 최고점 분석 앱에 추가적으로 적용해볼 것입니다.
다음 편 읽어보기 > Qt Graphs 개선점 이해 및 활용하기 2편
더 자세히 알고 싶으신가요?
무료 10일 평가판을 통해 Qt Software를 직접 경험해보세요!
Blog Topics:
Comments
Subscribe to our newsletter
Subscribe Newsletter
Try Qt 6.8 Now!
Download the latest release here: www.qt.io/download.
Qt 6.8 release focuses on technology trends like spatial computing & XR, complex data visualization in 2D & 3D, and ARM-based development for desktop.
We're Hiring
Check out all our open positions here and follow us on Instagram to see what it's like to be #QtPeople.