이 페이지에서

QML 문서의 구조

QML 문서는 다음 세 부분으로 구성된 독립적인 QML 소스 코드 조각입니다:

  • 선택 사항인 프래그마 목록
  • import 문
  • 단일 루트 객체 선언

관례에 따라, 임포트 문과 객체 계층 구조 정의 사이에는 하나의 빈 줄이 삽입됩니다.

QML 문서는 항상 UTF-8 형식으로 인코딩됩니다.

프래그마

프래그마는 QML 엔진 자체에 대한 명령어로, 현재 파일 내 객체의 특정 특성을 지정하거나 엔진이 코드를 해석하는 방식을 수정하는 데 사용할 수 있습니다. 다음 프래그마들에 대해서는 아래에서 자세히 설명합니다.

pragma값기본값사용 시작 시기
싱글톤5.2부터
ListPropertyAssignBehavior추가X6.3
바꾸기6.3
기본값이 아닐 경우 교체6.3
ComponentBehavior바운드6.4
바인딩 해제됨X6.4
함수 시그니처 동작무시됨6.5
적용됨X6.5
NativeMethodBehavior이 객체 수락6.5
이 객체 거부X6.5
값 유형 동작참조X6.5
복사6.5
주소 지정 가능6.6
비주소 지정 가능X6.6
어세르트 가능6.8
번역기<번역 컨텍스트><파일 이름>6.7

싱글톤

pragma Singleton QML 문서의 루트에 정의된 컴포넌트를 싱글톤으로 선언합니다. 자세한 내용은 QML의 싱글톤을 참조하십시오.

ListPropertyAssignBehavior

이 프래그마를 사용하면 QML 문서에 정의된 컴포넌트에서 리스트 속성에 대한 할당 처리를 어떻게 처리할지 정의할 수 있습니다. 기본적으로 리스트 속성에 값을 할당하면 리스트에 항목이 추가됩니다. Append 값을 사용하여 이 동작을 명시적으로 요청할 수 있습니다. 또는 Replace 을 사용하여 리스트 속성의 내용을 항상 대체하도록 요청하거나, ReplaceIfNotDefault 을 사용하여 해당 속성이 기본 속성이 아닐 경우에만 대체하도록 요청할 수 있습니다.

Base.qml 문서에 있는 기본 유형을 예로 들어 보겠습니다:

pragma ListPropertyAssignBehavior: ReplaceIfNotDefault
import QtQuick

Item {
    objectName: "outer"

    default property list<Item> d: [
        Item { objectName: "inner" }
    ]

    property list<Item> notDefault: [
        Item { objectName: "one" }
    ]
}

이때, Base를 상속받아 리스트 속성을 수정하면 ListPropertyAssignBehavior가 적용됩니다. 이 경우:

Base {
    // The new item is appended to the list even though you're assigning.
    // The (default) property "d" now contains "inner" and "inner2".
    d: [
        Item { objectName: "inner2" }
    ]

    // The list is replaced by the list given here.
    // The (non-default) property "notDefault" now contains only "two".
    notDefault: [
        Item { objectName: "two" }
    ]
}

ListPropertyAssignBehavior 가 지정되지 않았거나 Append 가 지정된 경우, “two” 객체는 대신 notDefault 속성에 추가되어, 결과적으로 “one”과 “two”가 모두 포함된 목록이 생성됩니다.

Replace 가 지정된 경우, 기본 속성 "d"의 내용도 대체되어 "inner2"만 포함된 목록이 생성됩니다.

참고: C++에서 정의된 유형의 경우에도 클래스 선언에 QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND, QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE, QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT 매크로를 추가하여 동일한선언을 할 수 있습니다. 예를 들어:

class MyType : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE

    Q_PROPERTY(QQmlListProperty<QObject> a READ a)
    [...]
};

ComponentBehavior

동일한 QML 파일에 여러 컴포넌트를 정의할 수 있습니다. QML 파일의 루트 범위는 컴포넌트이며, 여기에 QQmlComponent 유형의 요소나 명시적 또는 암시적으로 속성으로 생성된 요소, 또는 인라인 컴포넌트가 추가로 포함될 수 있습니다. 이러한 컴포넌트들은 중첩되어 있습니다. 각 내부 컴포넌트는 하나의 특정 외부 컴포넌트 내에 위치합니다. 대부분의 경우, 외부 컴포넌트에 정의된 ID는 그 안에 중첩된 모든 내부 컴포넌트에서 접근할 수 있습니다. 그러나 다른 컨텍스트에서 컴포넌트의 요소를 생성할 수 있으며, 이때는 다른 ID가 사용될 수 있습니다. 이렇게 하면 외부 ID를 사용할 수 있다는 가정이 깨집니다. 따라서 엔진과 QML 툴링은 일반적으로 런타임 시 이러한 ID가 어떤 유형으로 해결될지(해결된다면) 미리 알 수 없습니다.

ComponentBehavior 프래그마를 사용하면, 파일 내에 정의된 모든 내부 컴포넌트가 원래의 컨텍스트 내에서만 객체를 생성하도록 제한할 수 있습니다. 컴포넌트가 해당 컨텍스트에 바인딩된 경우, 동일한 파일 내의 외부 컴포넌트에서 정의된 ID를 해당 컴포넌트 내에서 안전하게 사용할 수 있습니다. 그러면 QML 툴링은 특정 유형을 가진 외부 ID를 사용할 수 있다고 가정합니다.

컴포넌트를 해당 컨텍스트에 바인딩하려면 Bound 인수를 지정하십시오:

pragma ComponentBehavior: Bound

이는 이름 충돌이 발생할 경우, 바인딩된 컴포넌트 외부에서 정의된 ID가 해당 컴포넌트에서 생성된 객체의 로컬 속성을 재정의함을 의미합니다. 그렇지 않다면, 모듈의 후속 버전에서 컴포넌트에 더 많은 속성이 추가될 수 있으므로 ID를 사용하는 것이 실제로 안전하지 않을 것입니다. 컴포넌트가 바인딩되지 않은 경우, 로컬 속성이 컴포넌트 외부에서 정의된 ID보다 우선하지만, 컴포넌트 내부에서 정의된 ID보다 우선하지는 않습니다.

아래 예제는 사각형( ListView ) 객체의 id가 color인 r 속성을 출력하며, 사각형 자체의 color 속성이 아닌, 해당 객체의 r 속성을 출력합니다.

pragma ComponentBehavior: Bound
import QtQuick

ListView {
 id: color
 property int r: 12
 model: 1

 delegate: Rectangle {
  Component.onCompleted: console.log(color.r)
 }
}

ComponentBehavior 의 기본값은 Unbound 입니다. 이를 명시적으로 지정할 수도 있습니다. 향후 Qt 버전에서는 기본값이 Bound 로 변경될 예정입니다.

컨텍스트에 바인딩된 델리게이트 컴포넌트는 인스턴스화 시 자체적인 비공개 컨텍스트를 받지 않습니다. 즉, 이 경우 모델 데이터는 필수 속성을 통해서만 전달될 수 있습니다. 컨텍스트 속성을 통해 모델 데이터를 전달하는 것은 작동하지 않습니다. 이는 예를 들어 Instantiator, Repeater, ListView, TableView, GridView, TreeView 및 일반적으로 내부적으로 DelegateModel 를 사용하는 모든 델리게이트에 해당합니다.

예를 들어, 다음 코드는 작동하지 않습니다:

pragma ComponentBehavior: Bound
import QtQuick

ListView {
 delegate: Rectangle {
     color: model.myColor
 }
}

ListView 의 delegate 속성은 컴포넌트입니다. 따라서 여기에서는 Rectangle 주위에 Component 가 암시적으로 생성됩니다. 이 컴포넌트는 자체 컨텍스트에 바인딩되어 있습니다. 이 컴포넌트는 ListView 에서 제공하는 model 컨텍스트 속성을 수신하지 않습니다. 정상적으로 작동하게 하려면 다음과 같이 작성해야 합니다:

pragma ComponentBehavior: Bound
import QtQuick

ListView {
 delegate: Rectangle {
     required property color myColor
     color: myColor
 }
}

QML 파일 내에서 컴포넌트를 중첩할 수 있습니다. 이 프래그마는 중첩 깊이와 상관없이 파일 내의 모든 컴포넌트에 적용됩니다.

FunctionSignatureBehavior

이 프래그마를 사용하면 함수의 타입 어노테이션 처리 방식을 변경할 수 있습니다. Qt 6.7부터는 함수 호출 시 타입 어노테이션이 강제 적용됩니다. 이전에는 Qt QML Compiler만 타입 어노테이션을 강제 적용했으며, 인터프리터와 JIT 컴파일러는 이를 무시했습니다. 유형 주석을 항상 강제 적용하는 것은 이전 버전과 비교해 동작이 변경된 점입니다. 이전에는 인수가 일치하지 않는 함수를 호출할 수 있었기 때문입니다.

값으로 ` Ignored `를 지정하면 QML 엔진과 QML 스크립트 컴파일러가 모든 타입 어노테이션을 무시하게 되며, 결과적으로 인터프리터와 JIT의 6.7 이전 동작이 복원됩니다. 그 결과, C++로 미리 컴파일되는 코드의 양이 줄어들고, 더 많은 코드가 인터프리팅되거나 JIT 컴파일되어야 합니다.

Enforced 를 값으로 지정하면 기본값을 명시적으로 지정하는 것이며, 즉 유형 어노테이션이 항상 적용됩니다.

NativeMethodBehavior

역사적인 이유로 인해, C++ 메서드를 호출할 때 해당 메서드를 가져온 것과 다른 ` this ` 객체를 사용하는 것은 정상적으로 작동하지 않습니다. 원본 객체가 ` this ` 객체로 사용됩니다. ` pragma NativeMethodBehavior: AcceptThisObject`를 설정하면 지정된 ` this ` 객체가 사용되도록 허용할 수 있습니다. ` RejectThisObject `를 지정하면 기존 동작이 유지됩니다.

이에 대한 예시는 C++ 메서드 및 'this' 객체 항목에서 확인할 수 있습니다.

ValueTypeBehavior

이 프래그마를 사용하면 값 유형과 시퀀스가 처리되는 방식을 변경할 수 있습니다.

일반적으로 자바스크립트 코드에서는 소문자 이름을 유형 이름으로 사용할 수 없습니다. 값 유형 이름은 소문자이므로 이는 문제가 됩니다. 이 프래그마의 값으로 Addressable 를 지정하여 이를 변경할 수 있습니다. Addressable 를 지정하면 JavaScript 값을 명시적으로 특정 명명된 값형으로 강제 변환할 수 있습니다. 이는 객체 유형에서와 마찬가지로 as 연산자를 사용하여 수행됩니다. 또한 instanceof 연산자를 사용하여 값형을 확인할 수도 있습니다:

pragma ValueTypeBehavior: Addressable
import QtQml

QtObject {
 property var a
 property real b: (a as rect).x
 property bool c: a instanceof rect

 property var rect // inaccessible. "rect" is a type name.
}

위 예제에서 rect 는 이제 유형 이름이 되었으므로, rect 라는 이름의 모든 속성을 가리게 됩니다.

원하는 유형으로 명시적으로 형변환을 수행하면 도구 활용에 도움이 됩니다. 이를 통해 Qt Quick Compiler 그렇지 않으면 생성할 수 없었을 효율적인 코드를 생성할 수 있게 해줍니다. qmllint를 사용하여 이러한 사례를 찾을 수 있습니다.

기본 동작을 명시적으로 지정하는 데 사용할 수 있는 Inaddressable 값도 있습니다.

ValueTypeBehavior 프래그마의 또 다른 속성인 Assertable 는 Qt 6.8에서 도입되었습니다. Qt 6.6 및 6.7의 오류로 인해 위의 a as rect 는 a 가 rect 인지 확인하는 것뿐만 아니라, a 가 호환되는 유형일 경우 rect 를 생성하기도 합니다. 이는 분명히 유형 어설션이 수행해야 할 동작이 아닙니다. Assertable 를 지정하면 이러한 동작을 방지할 수 있으며, 값 유형에 대한 타입 어설션을 해당 타입만 확인하도록 제한합니다. as 와 함께 값 유형을 사용할 경우 항상 이를 지정해야 합니다. 어쨌든, 값 유형에 대한 타입 어설션이 실패하면 결과는 undefined 가 됩니다.

instanceof 는 가능한 모든 형 변환을 확인하는 것이 아니라 상속 관계만 확인하므로 이러한 문제가 발생하지 않습니다.

참고: as 을 int 및 double 유형과 함께사용하는 것은 권장되지 않습니다. JavaScript 규칙에 따르면, 계산 결과는 정수형과 동일한 값을 가질지라도 부동 소수점 숫자이기 때문입니다. 반대로, JavaScript에서 선언한 정수 상수는 QML의 유형 매핑 규칙에 따라 double이 아닙니다. 또한, int 및 double 은 예약어입니다. 이러한 유형은 유형 네임스페이스를 통해서만 참조할 수 있습니다.

값 유형과 시퀀스는 일반적으로 참조로 취급됩니다. 즉, 속성에서 값 유형 인스턴스를 가져와 로컬 변수에 할당한 후, 해당 로컬 변수의 값을 변경하면 원래 속성의 값도 변경됩니다. 또한, 원래 속성을 명시적으로 작성하면 로컬 변수의 값도 업데이트됩니다. 이러한 동작은 여러 면에서 직관적이지 않으므로, 이에 의존해서는 안 됩니다. ` ValueTypeBehavior ` 프래그마의 ` Copy ` 및 ` Reference ` 값은 이 동작을 변경하기 위한 실험적인 옵션입니다. 이 옵션들을 사용해서는 안 됩니다. ` Copy `을 지정하면 모든 값 형식이 실제 복사본으로 처리됩니다. ` Reference `을 지정하면 기본 동작을 명시적으로 나타냅니다.

Copy 를 사용하는 대신, 부수 효과의 영향을 받았을 가능성이 있는 경우마다 값 유형 및 시퀀스에 대한 참조를 명시적으로 다시 불러와야 합니다. 부작용은 함수를 호출하거나 속성을 명령형 방식으로 설정할 때마다 발생할 수 있습니다. qmllint는 이에 대한 지침을 제공합니다. 예를 들어, 다음 코드에서 f 변수는 width 를 작성한 후 부작용의 영향을 받습니다. 이는 width 가 변경될 때 font 를 업데이트하는 바인딩이 파생형이나 Binding 요소 내에 존재할 수 있기 때문입니다.

import QtQuick
Text {
 function a() : real {
     var f = font;
     width = f.pixelSize;
     return f.pointSize;
 }
}

이 문제를 해결하려면, width 에 대한 쓰기 작업이 진행되는 동안 f 를 보유하지 않도록 할 수 있습니다:

import QtQuick
Text {
 function a() : real {
     var f = font;
     width = f.pixelSize;
     f = font;
     return f.pointSize;
 }
}

이는 다음과 같이 간소화할 수 있습니다:

import QtQuick
Text {
 function a() : real {
     width = font.pixelSize;
     return font.pointSize;
 }
}

font 속성을 다시 가져오는 데 비용이 많이 든다고 생각할 수 있지만, 실제로 QML 엔진은 값형 참조를 읽을 때마다 자동으로 갱신합니다. 따라서 이 방법은 첫 번째 버전보다 비용이 더 들지 않으면서도 동일한 작업을 더 명확하게 표현할 수 있는 방법입니다.

번역자

이 프래그마를 사용하면 파일 내 번역에 대한 컨텍스트를 설정할 수 있습니다.

pragma Translator: myTranslationContext
pragma Translator: "myTranslationContext"

QML을 이용한 국제화에 대한 자세한 내용은 QML에서 번역을 위한 소스 코드 작성을 참조하십시오.

임포트

문서는 엔진에서 문서 내에서 참조되는 QML 객체 유형을 로드할 수 있도록 필요한 모듈이나 유형 네임스페이스를 임포트해야 합니다. 기본적으로 문서는 동일한 디렉토리에 있는 .qml 파일을 통해 정의된 모든 QML 객체 유형에 액세스할 수 있습니다. 문서가 다른 객체 유형을 참조해야 하는 경우, 해당 유형이 등록된 유형 네임스페이스를 임포트해야 합니다.

QML에는 C나 C++과 달리, QML engine 에 문서를 전달하기 전에 문서를 수정하는 전처리기가 없습니다. import 문은 문서 내의 코드를 복사하여 앞에 추가하는 것이 아니라, 문서에서 발견된 유형 참조를 해결하는 방법을 QML 엔진에 지시합니다. Rectangle 나 ListView 와 같이 QML 문서에 존재하는 모든 타입 참조( JavaScript 블록 내부나 속성 바인딩 내에서 이루어진 참조 포함)는 전적으로 import 문에 따라 해결됩니다. import QtQuick 2.0 와 같은 import 문이 적어도 하나 이상 존재해야 합니다.

QML 임포트에 대한 자세한 내용은 ‘QML 구문 - 임포트 문’ 문서를 참조하십시오.

루트 객체 선언

QML 문서는 인스턴스화될 수 있는 객체의 계층 구조를 기술합니다. 각 객체 정의는 특정 구조를 가지며, 타입을 갖고, ID와 객체 이름을 가질 수 있으며, 속성, 메서드, 시그널 및 시그널 핸들러를 가질 수 있습니다.

QML 파일에는 단 하나의 루트 객체 정의만 포함되어야 합니다. 다음은 유효하지 않으며 오류를 발생시킵니다:

// MyQmlFile.qml
import QtQuick 2.0

Rectangle { width: 200; height: 200; color: "red" }
Rectangle { width: 200; height: 200; color: "blue" }    // invalid!

이는 .qml 파일이 단일 QML 객체 정의를 캡슐화하는 QML 타입을 자동으로 정의하기 때문입니다. 이에 대한 자세한 내용은 ‘문서’ 섹션의 ‘QML 객체 타입 정의’에서 다룹니다.

‘타입 어노테이션 및 어설션’항목도 참조하십시오 .

© 2026 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.