QML 및 Qt Quick

QML과 Qt Quick 이 제공하는 모든 이점에도 불구하고 특정 상황에서는 어려울 수 있습니다. 다음 섹션에서는 애플리케이션 개발 시 더 나은 결과를 얻는 데 도움이 되는 몇 가지 모범 사례에 대해 자세히 설명합니다.

사용자 지정 UI 컨트롤

유동적이고 현대적인 UI는 오늘날 모든 애플리케이션의 성공을 위한 핵심 요소이며, 디자이너나 개발자에게 QML은 바로 이 점에서 매우 유용합니다. Qt는 유동적이고 현대적인 UI를 만드는 데 필요한 가장 기본적인 UI 컨트롤을 제공합니다. 자신만의 사용자 정의 UI 컨트롤을 만들기 전에 이 UI 컨트롤 목록을 살펴보는 것이 좋습니다.

Qt Quick 에서 제공하는 이러한 기본 UI 컨트롤 외에도 Qt Quick Controls 에서 다양한 UI 컨트롤 세트를 사용할 수 있습니다. 이 컨트롤은 가장 일반적인 사용 사례를 변경 없이 충족하며 사용자 정의 옵션을 통해 훨씬 더 많은 가능성을 제공합니다. 특히 Qt Quick Controls 에서는 최신 UI 디자인 트렌드에 맞는 스타일링 옵션을 제공합니다. 이러한 UI 컨트롤이 애플리케이션의 요구 사항을 만족시키지 못한다면 사용자 지정 컨트롤을 만드는 것이 좋습니다.

Qt Design Studio 에서 UI를 디자인할 때 컨트롤을 사용할 수 있습니다. 또한 타임라인 기반 애니메이션, 시각 효과, 레이아웃 및 애플리케이션 프로토타이핑을 위한 실시간 미리 보기를 제공합니다.

코딩 규칙

QML 코딩 규칙을 참조하세요.

애플리케이션 리소스 번들

대부분의 애플리케이션은 풍부한 사용자 경험을 제공하기 위해 이미지 및 아이콘과 같은 리소스에 의존합니다. 대상 OS에 관계없이 애플리케이션에서 이러한 리소스를 사용할 수 있도록 하는 것은 종종 어려울 수 있습니다. 대부분의 인기 OS는 파일 시스템에 대한 액세스를 제한하는 엄격한 보안 정책을 채택하고 있기 때문에 이러한 리소스를 로드하기가 더 어렵습니다. 이에 대한 대안으로 Qt는 애플리케이션 바이너리에 내장된 자체 리소스 시스템을 제공하여 대상 OS에 관계없이 애플리케이션의 리소스에 액세스할 수 있도록 합니다.

예를 들어 다음 프로젝트 디렉토리 구조를 생각해 보겠습니다:

MyModule
├── images
│   ├── image1.png
│   └── image2.png
├── CMakeLists.txt
└── main.qml

이 구조를 다음과 같은 방식으로 CMake QML 모듈로 표현할 수 있습니다:

qt_add_qml_module(my_module
   URI MyModule
   VERSION 1.0
   QML_FILES
       main.qml
   RESOURCES
       images/image1.png
       images/image2.png
   # ...
)

QML_FILES 아래에 나열된 모든 QML 파일은 자동으로 미리 컴파일됩니다.

QML 파일은 CMakeLists.txt와 같은 디렉터리에 qt_add_qml_module을 사용하여 보관해야 합니다. 그렇지 않으면 암시적 임포트가 해당 파일이 속한 QML 모듈과 달라집니다. 이는 실수의 빈번한 원인입니다.

비즈니스 로직과 UI 분리

대부분의 애플리케이션 개발자가 달성하고자 하는 주요 목표 중 하나는 유지 관리가 가능한 애플리케이션을 만드는 것입니다. 이 목표를 달성하는 방법 중 하나는 사용자 인터페이스와 비즈니스 로직을 분리하는 것입니다. 다음은 애플리케이션의 UI를 QML로 작성해야 하는 몇 가지 이유입니다:

  • 선언적 언어는 UI를 정의하는 데 매우 적합합니다.
  • QML 코드는 C++보다 덜 장황하고 강력하게 타이핑되지 않기 때문에 작성하기가 더 간단합니다. 또한 프로토타입을 만들기에 훌륭한 언어이며, 이는 예를 들어 디자이너와 협업할 때 매우 중요한 특성입니다.
  • 자바스크립트는 QML에서 이벤트에 응답하는 데 쉽게 사용할 수 있습니다.

강력한 타이핑 언어인 C++는 애플리케이션의 비즈니스 로직에 가장 적합합니다. 일반적으로 이러한 코드는 복잡한 계산이나 데이터 처리와 같은 작업을 수행하는데, 이러한 작업은 QML보다 C++에서 더 빠릅니다.

Qt는 애플리케이션에서 QML과 C++ 코드를 통합하기 위한 다양한 접근 방식을 제공합니다. 일반적인 사용 사례는 사용자 인터페이스에 데이터 목록을 표시하는 것입니다. 데이터 세트가 정적이거나 단순하거나 작은 경우 QML로 작성된 모델로 충분할 수 있습니다.

다음 스니펫은 QML로 작성된 모델의 예를 보여줍니다:

model: [ "Item 1", "Item 2", "Item 3" ]

model: 10

규모가 크거나 자주 수정되는 동적 데이터 집합에는 C++를 사용하세요.

C++에서 QML로 데이터 노출하기

QML 리팩터링은 C++ 리팩터링보다 훨씬 쉽기 때문에 유지보수를 수월하게 하려면 가능한 한 C++ 유형이 QML을 인식하지 못하도록 노력해야 합니다. 이는 C++ 유형에 대한 참조를 QML로 '푸시'함으로써 달성할 수 있습니다.

이는 필요한 속성을 사용하고 QQmlApplicationEngine::setInitialProperties 을 통해 설정하면 됩니다. 또한 하나 또는 여러 개의 singletons 을 생성하여 C++ 측에서 QML에 제공하고자 하는 모든 데이터를 반환할 수도 있습니다.

이 접근 방식을 사용하면 향후 QML을 리팩터링해야 하는 경우에도 C++는 변경되지 않은 상태로 유지됩니다.

C++ 유형을 QML에 노출하기 위한 올바른 접근 방식을 선택하는 방법에 대한 빠른 가이드는 C++와 QML 간의 올바른 통합 방법 선택하기를 참조하세요.

사용 Qt Design Studio

Qt Design Studio 는 파일 확장자가 .ui.qml인 UI 파일을 사용하여 UI의 시각적 부분을 .qml 파일에서 구현하는 UI 로직과 분리합니다. Qt Design Studio2D 보기에서만 UI 파일을 편집해야 합니다. 다른 도구를 사용하여 Qt Design Studio 에서 지원하지 않는 코드를 추가하면 오류 메시지가 표시됩니다. 오류를 수정하여 UI 파일을 다시 시각적으로 편집할 수 있도록 합니다. 일반적으로 지원되지 않는 코드는 .qml 파일로 이동해야 합니다.

Qt Quick 보기 사용

모델에 상태 저장

Avoid Storing State in Delegates 을 참조하세요.

Qt Quick 레이아웃 사용하기

Qt는 Qt Quick 항목을 레이아웃에 시각적으로 배열하기 위해 Qt Quick 레이아웃을 제공합니다. 대안인 아이템 포지셔너와 달리 Qt Quick 레이아웃은 창 크기 조정 시 자식들의 크기를 조정할 수도 있습니다. Qt Quick 레이아웃은 대부분의 사용 사례에서 원하는 선택이지만, 사용 시 다음과 같은 해야 할 일과 하지 말아야 할 일을 고려해야 합니다:

해야 할 일

  • anchors 또는 widthheight 속성을 사용하여 레이아웃이 아닌 상위 항목에 대한 레이아웃의 크기를 지정합니다.
  • Layout 첨부 속성을 사용하여 레이아웃의 바로 아래 자식의 크기 및 정렬 속성을 설정합니다.

하지 말아야 할 사항

  • 묵시적 크기가 만족스럽지 않은 경우, 묵시적 폭 및 묵시적 높이를 제공하는 항목에 대해 기본 크기를 정의하지 마세요.
  • 레이아웃의 직계 자식인 항목에 앵커를 사용하지 마세요. 대신 Layout.preferredWidthLayout.preferredHeight 을 사용하세요:
    RowLayout {
        id: layout
        anchors.fill: parent
        spacing: 6
        Rectangle {
            color: 'orange'
            Layout.fillWidth: true
            Layout.minimumWidth: 50
            Layout.preferredWidth: 100
            Layout.maximumWidth: 300
            Layout.minimumHeight: 150
            Text {
                anchors.centerIn: parent
                text: parent.width + 'x' + parent.height
            }
        }
        Rectangle {
            color: 'plum'
            Layout.fillWidth: true
            Layout.minimumWidth: 100
            Layout.preferredWidth: 200
            Layout.preferredHeight: 100
            Text {
                anchors.centerIn: parent
                text: parent.width + 'x' + parent.height
            }
        }
    }

참고: 레이아웃과 앵커는 모두 메모리와 인스턴스화 시간이 더 많이 걸리는 객체 유형입니다. 특히 목록 및 테이블 델리게이트와 컨트롤의 스타일에서는 x, y, 너비 및 높이 속성에 대한 간단한 바인딩으로 충분할 때 사용하지 마세요.

유형 안전

QML에서 프로퍼티를 선언할 때 "var" 유형을 사용하는 것이 쉽고 편리합니다:

property var name
property var size
property var optionsMenu

하지만 이 방식에는 몇 가지 단점이 있습니다:

  • 잘못된 유형의 값이 할당되면 보고되는 오류는 속성이 할당된 위치가 아니라 속성 선언의 위치를 가리킵니다. 이렇게 하면 오류를 추적하기가 더 어려워져 개발 프로세스가 느려집니다.
  • 위에서 언급한 것과 같은 오류를 포착하기 위한 정적 분석은 불가능합니다.
  • 프로퍼티의 실제 기본 유형이 항상 독자에게 즉시 명확하지는 않습니다.

대신 가능하면 항상 실제 유형을 사용하세요:

property string name
property int size
property MyMenu optionsMenu

성능

QML의 성능에 대한 자세한 내용은 Qt Quick 에서 QML 성능 고려 사항 및 제안 사항을 참조하세요.

명령형 할당보다 선언적 바인딩을 선호하기

QML에서는 입력 이벤트에 응답하거나 네트워크를 통해 데이터를 전송하는 등의 작업을 수행하기 위해 명령형 JavaScript 코드를 사용할 수 있습니다. 명령형 코드는 QML에서 중요한 위치를 차지하지만 언제 사용하지 말아야 하는지 아는 것도 중요합니다.

예를 들어 다음 명령형 할당을 생각해 보세요:

Rectangle {
    Component.onCompleted: color = "red"
}

여기에는 다음과 같은 단점이 있습니다:

  • 느립니다. 색상 속성은 먼저 기본으로 구성된 값으로 평가된 다음 나중에 "빨간색"으로 다시 평가됩니다.
  • 빌드 시점에 발견될 수 있는 오류를 런타임으로 지연시켜 개발 프로세스를 느리게 합니다.
  • 기존에 있던 모든 선언적 바인딩을 덮어씁니다. 대부분의 경우 이는 의도된 것이지만 때로는 의도하지 않은 경우도 있습니다. 자세한 내용은 바인딩 덮어쓰기 디버깅을 참조하세요.
  • 예를 들어 Qt Quick 디자이너는 JavaScript를 지원하지 않습니다.

대신 선언적 바인딩으로 코드를 다시 작성할 수 있습니다:

Rectangle {
    color: "red"
}

델리게이트에 상태 저장하지 않기

델리게이트에 상태를 저장하지 마세요. 여기서 문제는 델리게이트가 여러 번 생성 및 소멸되므로 저장된 상태가 손실된다는 것입니다.

// Wrong approach:
ListView {
    // ...

    delegate: Button {
        // ...
        property bool someStateProperty
        onClicked: someStateProperty = true
    }
}

대신 델리게이트 외부에 상태를 저장하세요. 예를 들어 모델에 저장합니다. 델리게이트가 파괴되어도 저장된 상태는 손실되지 않습니다.

// Right approach:
ListView {
    // ...

    delegate: Button {
        // ...
        onClicked: model.someStateProperty = true
    }
}

사용자 대면 문자열을 번역 가능하게 만들기

사용자 대면 문자열은 처음부터 번역이 가능하도록 만드는 것이 좋습니다. 번역을 위한 소스 코드 작성을 참조하세요.

ToolButton {
    id: selectionToolButton
    // ...
    icon.source: "qrc:/images/selection.png"

    Tooltip.Text: qsTr("Select pixels within an area and move them")

    onClicked: canvas.tool = ImageCanvas.SelectionTool
}

기본 스타일 사용자 지정하지 않기

기본 스타일(Windows 및 macOS 스타일)은 사용자 지정을 지원하지 않습니다. 기본 스타일을 사용자 지정하지 않도록 하세요.

// Wrong approach:
import QtQuick.Controls.Windows

// Don't customize a native style
Button {
    background: Rectangle { /*...*/ }
}

대신 항상 모든 플랫폼에서 사용할 수 있는 단일 스타일(예: 기본 스타일, 퓨전 스타일, 상상 스타일, 재질 스타일, 범용 스타일)을 기반으로 사용자 지정 컨트롤을 만드는 것이 좋습니다. 이렇게 하면 애플리케이션이 어떤 스타일로 실행되든 항상 동일하게 보이도록 보장할 수 있습니다. 다른 스타일을 사용하는 방법을 알아보려면 Qt Quick Controls 에서 스타일 사용을 참조하세요. 또는 자신만의 스타일을 만들 수도 있습니다.

// Right approach:
import QtQuick.Controls.Basic

// You can customize a commonly available style
Button {
    background: Rectangle { /*...*/ }
}

도구 및 유틸리티

QML 및 Qt Quick 작업을 더 쉽게 해주는 유용한 도구 및 유틸리티에 대한 자세한 내용은 Qt Quick 도구 및 유틸리티를 참조하세요.

씬 그래프

Qt Quick 의 씬 그래프에 대한 자세한 내용은 Qt Quick 씬 그래프를 참조하세요.

확장 가능한 사용자 인터페이스

디스플레이 해상도가 향상됨에 따라 확장 가능한 애플리케이션 UI의 중요성이 점점 더 커지고 있습니다. 이를 달성하기 위한 접근 방식 중 하나는 다양한 화면 해상도에 맞게 UI의 여러 복사본을 유지한 다음 사용 가능한 해상도에 따라 적절한 복사본을 로드하는 것입니다. 이 방법은 꽤 잘 작동하지만 유지 관리 오버헤드가 증가합니다.

Qt는 이 문제에 대한 더 나은 해결책을 제공하며 애플리케이션 개발자에게 다음 팁을 따르도록 권장합니다:

  • 앵커 또는 Qt Quick 레이아웃 모듈을 사용하여 시각적 항목을 배치합니다.
  • 시각적 항목의 너비와 높이를 명시적으로 지정하지 마십시오.
  • 애플리케이션이 지원하는 각 디스플레이 해상도에 맞는 이미지 및 아이콘과 같은 UI 리소스를 제공하세요. Qt Quick Controls 갤러리 예제는 @2x, @3x, @4x 해상도에 대해 qt-logo.png 을 제공하여 애플리케이션이 고해상도 디스플레이에 대응할 수 있도록 함으로써 이를 잘 보여줍니다. 높은 DPI 스케일링 기능이 명시적으로 활성화되어 있다면 Qt는 주어진 디스플레이에 적합한 적절한 이미지를 자동으로 선택합니다.
  • 작은 아이콘에는 SVG 이미지를 사용합니다. 큰 SVG는 렌더링 속도가 느릴 수 있지만 작은 SVG는 잘 작동합니다. 벡터 이미지를 사용하면 비트맵 이미지에서처럼 여러 버전의 이미지를 제공할 필요가 없습니다.
  • Font Awesome과 같은 글꼴 기반 아이콘을 사용합니다. 이러한 아이콘은 모든 디스플레이 해상도에 맞게 조정되며 색상도 지정할 수 있습니다. Qt Quick Controls 텍스트 편집기 예시가 이를 잘 보여줍니다.

이렇게 하면 제공되는 디스플레이 해상도에 따라 애플리케이션의 UI가 확장되어야 합니다.

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.