이 페이지에서

QML과 C++ 간의 데이터형 변환

QML과 C++ 간에 데이터 값이 교환될 때, QML 엔진은 해당 데이터가 QML 또는 C++에서 사용하기에 적합한 올바른 데이터 유형을 갖도록 변환합니다. 이를 위해서는 교환되는 데이터가 엔진에서 인식할 수 있는 유형이어야 합니다.

Qt Qml 엔진은 수많은 Qt C++ 데이터 유형에 대한 내장 지원을 제공합니다. 또한 사용자 정의 C++ 유형을 Qml 유형 시스템에 등록하여 엔진에서 사용할 수 있도록 할 수 있습니다.

C++ 및 다양한 QML 통합 방법에 대한 자세한 내용은 C++ 및 QML 통합 개요 페이지를 참조하십시오.

이 페이지에서는 QML 엔진이 지원하는 데이터 유형과 QML과 C++ 간에 이러한 유형이 어떻게 변환되는지에 대해 설명합니다.

데이터 소유권

데이터가 C++에서 QML로 전송될 때, 데이터의 소유권은 항상 C++에 남아 있습니다. 이 규칙의 예외는 명시적인 C++ 메서드 호출에서 ` QObject `가 반환되는 경우입니다. 이 경우, `QQmlEngine::CppOwnership`을 지정하여 ` QQmlEngine::setObjectOwnership()`를 호출함으로써 객체의 소유권이 C++에 남도록 명시적으로 설정되지 않은 한, QML 엔진이 객체의 소유권을 인수합니다.

또한, QML 엔진은 Qt C++ 객체의 일반적인 QObject 부모 소유권 세미오틱을 준수하며, 부모가 있는 QObject 인스턴스는 절대 삭제하지 않습니다.

기본 Qt 데이터 유형

기본적으로 QML은 다음 Qt 데이터 유형을 인식하며, 이러한 유형은 C++에서 QML로, 또는 그 반대로 전달될 때 해당 QML 값 유형으로 자동 변환됩니다:

참고: Qt GUIQColor, QFont, QQuaternion 및 QMatrix4x4 와 같은 클래스는 Qt Quick 모듈이 포함된 경우에만 사용할 수 있습니다.

편의상, 이러한 유형 중 상당수는 QML에서 문자열 값이나 QtQml::Qt 객체가 제공하는 관련 메서드를 통해 지정할 수 있습니다. 예를 들어, Image::sourceSize 속성은 size 유형(이는 자동으로 QSize 유형으로 변환됨)이며, "widthxheight" 형식의 문자열 값이나 Qt의size() 함수를 통해 지정할 수 있습니다:

Item {
    Image { sourceSize: "100x200" }
    Image { sourceSize: Qt.size(100, 200) }
}

자세한 내용은 QML 값 유형(QML Value Types ) 항목에서 각 개별 유형에 대한 문서를 참조하십시오.

QObject에서 파생된 유형

QObject 에서 파생된 모든 클래스는 해당 클래스가 QML 타입 시스템에 등록되어 있는 경우, QML과 C++ 간의 데이터 교환을 위한 타입으로 사용할 수 있습니다.

엔진은 인스턴스화 가능한 유형과 인스턴스화 불가능한 유형 모두를 등록할 수 있도록 지원합니다. 클래스가 QML 유형으로 등록되면, QML과 C++ 간의 데이터 교환을 위한 데이터 유형으로 사용할 수 있습니다. 유형 등록에 대한 자세한 내용은 “QML 유형 시스템에 C++ 유형 등록하기”를 참조하십시오.

Qt와 JavaScript 유형 간의 변환

Qt Qml 엔진은 QML과 C++ 간에 데이터를 전송할 때 여러 Qt 유형을 관련 JavaScript 유형으로, 또는 그 반대로 변환하는 기능을 기본적으로 지원합니다. 이를 통해 데이터 값 및 해당 속성에 대한 액세스를 제공하는 사용자 정의 유형을 구현할 필요 없이, 이러한 유형을 사용하고 C++ 또는 JavaScript에서 해당 데이터를 수신할 수 있습니다.

(QML의 JavaScript 환경은 추가 기능을 제공하기 위해 String, Date 및 Number 를 포함한 네이티브 JavaScript 객체 프로토타입을 수정한다는 점에 유의하십시오. 자세한 내용은 JavaScript 호스트 환경을 참조하십시오.)

QVariantList 및 QVariantMap을 JavaScript의 배열 및 객체와 유사하게 변환

QML 엔진은 QVariantList 와 자바스크립트 배열 유사체 간, 그리고 QVariantMap 와 자바스크립트 객체 간에 자동 형 변환을 제공합니다.

ECMAScript 용어로 배열과 유사한 객체( array-like)란 배열처럼 사용되는 객체를 의미합니다. QVariantList (및 기타 C++ 순차적 컨테이너)에서 변환되어 생성된 배열과 유사한 객체는 단순히 배열처럼 사용되는 것뿐만 아니라 일반적인 배열 메서드를 제공하며 length 속성을 자동으로 동기화합니다. 이러한 객체는 실질적인 용도에서 JavaScript 배열과 똑같이 사용할 수 있습니다. 하지만 Array.isArray() 메서드는 여전히 이들에 대해 false를 반환합니다.

예를 들어, 아래 QML에 정의된 함수는 배열과 객체라는 두 개의 인자를 기대하며, 배열 및 객체 항목 액세스를 위한 표준 자바스크립트 구문을 사용하여 해당 내용을 출력합니다. 아래 C++ 코드는 이 함수를 호출하여 QVariantList 와 QVariantMap 를 전달하며, 이들은 각각 자바스크립트 배열 유사 객체와 객체 값으로 자동 변환됩니다:

QML
// MyItem.qml
Item {
    function readValues(anArray, anObject) {
        for (var i=0; i<anArray.length; i++)
            console.log("Array item:", anArray[i])

        for (var prop in anObject) {
            console.log("Object item:", prop, "=", anObject[prop])
        }
    }
}
C++
// C++
QQuickView view(QUrl::fromLocalFile("MyItem.qml"));

QVariantList list;
list << 10 << QColor(Qt::green) << "bottles";

QVariantMap map;
map.insert("language", "QML");
map.insert("released", QDate(2010, 9, 21));

QMetaObject::invokeMethod(view.rootObject(), "readValues",
        Q_ARG(QVariant, QVariant::fromValue(list)),
        Q_ARG(QVariant, QVariant::fromValue(map)));

그러면 다음과 같은 출력이 생성됩니다:

Array item: 10
Array item: #00ff00
Array item: bottles
Object item: language = QML
Object item: released = Tue Sep 21 2010 00:00:00 GMT+1000 (EST)

마찬가지로, C++ 타입이 속성 타입이나 메서드 매개변수로 QVariantList 또는 QVariantMap 타입을 사용하는 경우, 해당 값은 QML에서 JavaScript 배열이나 객체로 생성될 수 있으며, C++로 전달될 때 자동으로 QVariantList 또는 QVariantMap 로 변환됩니다.

Qt 6.5부터는 QML 코드를 통해 C++ 유형의 QVariantList 속성을 그 자리에서 변경할 수 있습니다. Qt 6.9부터는 QML 코드를 통해 C++ 유형의 QVariantMap 속성을 그 자리에서 변경할 수 있습니다.

QDateTime을 JavaScript Date로 변환

QML 엔진은 QDateTime 값과 JavaScript Date 객체 간의 자동 형 변환 기능을 제공합니다.

예를 들어, 아래 QML에 정의된 함수는 JavaScript Date 객체를 인수로 받으며, 현재 날짜와 시간을 가진 새로운 Date 객체를 반환합니다. 아래의 C++ 코드는 이 함수를 호출하며, QDateTime 값을 전달합니다. 이 값은 readDate() 함수로 전달될 때 엔진에 의해 자동으로 Date 객체로 변환됩니다. 이에 따라 readDate() 함수는 Date 객체를 반환하며, 이 객체는 C++에서 수신될 때 자동으로 QDateTime 값으로 변환됩니다:

QML
// MyItem.qml
Item {
    function readDate(dt) {
        console.log("The given date is:", dt.toUTCString());
        return new Date();
    }
}
C++
// C++
QQuickView view(QUrl::fromLocalFile("MyItem.qml"));

QDateTime dateTime = QDateTime::currentDateTime();
QDateTime retValue;

QMetaObject::invokeMethod(view.rootObject(), "readDate",
        Q_RETURN_ARG(QVariant, retValue),
        Q_ARG(QVariant, QVariant::fromValue(dateTime)));

qDebug() << "Value returned from readDate():" << retValue;

마찬가지로, C++ 유형이 속성 유형이나 메서드 매개변수로 ` QDateTime `를 사용하는 경우, 해당 값은 QML에서 JavaScript ` Date ` 객체로 생성될 수 있으며, C++로 전달될 때 자동으로 ` QDateTime ` 값으로 변환됩니다.

참고: 월 번호 매기기의 차이에주의하십시오 . 자바스크립트에서는 1월을 0으로, 12월을 11로 표기하는 반면, Qt에서는 1월을 1로, 12월을 12로 표기하므로 1의 차이가 있습니다.

참고: JavaScript에서 문자열을 ` Date ` 객체의 값으로 사용할때 , 시간 필드가 없는 문자열(즉, 단순한 날짜)은 해당 날짜의 UTC 시작 시각으로 해석되는 반면, ` new Date(y, m, d) `는 해당 날짜의 현지 시간 시작 시각을 사용한다는 점에 유의하십시오. 자바스크립트에서 ` Date ` 객체를 생성하는 대부분의 다른 방법은, 이름에 UTC가 포함된 메서드를 사용하지 않는 한 현지 시간을 반환합니다. 프로그램이 UTC보다 뒤처진 시간대(명목상 본초자오선 서쪽)에서 실행되는 경우, 날짜만 포함된 문자열을 사용하면 ` getDate() ` 값이 문자열의 일 번호보다 1 적은 ` Date ` 객체가 생성됩니다. 이 객체의 ` getHours()` 값은 일반적으로 매우 큰 값을 가집니다. 이러한 메서드의 UTC 변형인 ` getUTCDate() ` 및 ` getUTCHours()`는 이러한 ` Date ` 객체에 대해 기대하는 결과를 반환합니다. 다음 섹션도 참조하십시오.

QDate와 JavaScript Date

QML 엔진은 날짜를 해당 날짜의 UTC 시작 시각으로 표현함으로써 QDate 와 JavaScript Date 유형 간에 자동으로 변환합니다. 날짜는 QDateTime 를 통해 QDate 로 다시 매핑되며, 이때 date() 메서드를 선택하여 날짜의 현지 시간 형식을 사용합니다. 단, UTC 형식이 다음 날의 시작 시각과 일치하는 경우에는 UTC 형식이 사용됩니다.

이 다소 특이한 구성 방식은, 이전 절의 마지막에 있는 주석에서 설명한 바와 같이, JavaScript가 날짜만 포함된 문자열로부터 ` Date ` 객체를 생성할 때는 하루의 시작을 UTC 기준으로 사용하지만, ` new Date(y, m, d) `는 지정된 날짜의 시작을 현지 시간 기준으로 사용하기 때문에 이를 우회하기 위한 해결책입니다.

결과적으로, QDate 속성이나 매개변수가 QML에 노출되는 경우, 그 값을 읽을 때 주의해야 합니다. Date.getUTCFullYear(), Date.getUTCMonth() 및 Date.getUTCDate() 메서드는 이름에 UTC가 포함되지 않은 해당 메서드들보다 사용자가 기대하는 결과를 반환할 가능성이 더 높습니다.

따라서 일반적으로 QDateTime 속성을 사용하는 것이 더 안정적입니다. 이를 통해 QDateTime 측에서 날짜(및 시간)가 UTC로 지정될지, 아니면 현지 시간으로 지정될지를 제어할 수 있습니다. JavaScript 코드가 동일한 표준에 따라 작성되어 있다면 문제를 피할 수 있을 것입니다.

QTime과 자바스크립트 Date

QML 엔진은 ` QTime ` 값을 JavaScript ` Date ` 객체로 자동 변환해 줍니다. ` QTime ` 값에는 날짜 구성 요소가 포함되어 있지 않으므로, 변환 시에만 해당 구성 요소가 생성됩니다. 따라서 결과로 생성된 `Date` 객체의 날짜 구성 요소에 의존해서는 안 됩니다.

내부적으로는 JavaScript Date 객체를 QTime 로 변환할 때, (현지 시간을 사용하여) QDateTime 객체로 변환한 다음 해당 객체의 time() 메서드를 호출하는 방식으로 이루어집니다.

시퀀스 타입을 자바스크립트 배열로 변환

시퀀스 유형에 대한 일반적인 설명은 QML 시퀀스 유형을 참조하십시오. ` QtQml module `에는 사용자가 활용할 수 있는 몇 가지 시퀀스 유형이 포함되어 있습니다.

QJSEngine::newArray()를 사용하여 QJSValue 를 생성함으로써 목록과 유사한 데이터 구조를 만들 수도 있습니다. 이러한 JavaScript 배열은 QML과 C++ 간에 전달할 때 별도의 변환이 필요하지 않습니다. C++에서 JavaScript 배열을 조작하는 방법에 대한 자세한 내용은 QJSValue#Working With Arrays 를 참조하십시오.

QByteArray를 JavaScript ArrayBuffer로 변환

QML 엔진은 QByteArray 값과 JavaScript ArrayBuffer 객체 간의 자동 형 변환 기능을 제공합니다.

값 유형

QPoint 와 같은 Qt의 일부 값 유형은 C++ API와 동일한 속성과 함수를 가진 객체로 JavaScript에서 표현됩니다. 사용자 정의 C++ 값 유형에서도 동일한 표현이 가능합니다. QML 엔진에서 사용자 정의 값 유형을 사용하려면 클래스 선언에 Q_GADGET 어노테이션을 추가해야 합니다. JavaScript 표현에서 노출되도록 의도된 속성은 Q_PROPERTY 로 선언해야 합니다. 마찬가지로 함수는 Q_INVOKABLE 로 표시해야 합니다. 이는 QObject 기반 C++ API와 동일합니다. 예를 들어, 아래의 Actor 클래스는 gadget으로 어노테이션되어 있으며 다음과 같은 속성을 가지고 있습니다:

class Actor
{
    Q_GADGET
    Q_PROPERTY(QString name READ name WRITE setName)
public:
    QString name() const { return m_name; }
    void setName(const QString &name) { m_name = name; }

private:
    QString m_name;
};

Q_DECLARE_METATYPE(Actor)

일반적인 패턴은 속성의 유형으로 가젯 클래스를 사용하거나, 신호 인수로 가젯을 전달하는 것입니다. 이러한 경우, 가젯 인스턴스는 C++과 QML 간에 값으로 전달됩니다(가젯이 값형이기 때문입니다). QML 코드가 가젯 속성의 값을 변경하면, 전체 가젯이 재 생성되어 C++ 속성 세터로 다시 전달됩니다. Qt 5에서는 QML에서 직접 선언하여 가젯 유형을 인스턴스화할 수 없습니다. 반면, ` QObject ` 인스턴스는 선언할 수 있으며, ` QObject ` 인스턴스는 항상 C++에서 QML로 포인터를 통해 전달됩니다.

열거형

사용자 정의 열거형을 데이터 유형으로 사용하려면 해당 클래스를 등록해야 하며, Qt의 메타 객체 시스템에 등록하기 위해 Q_ENUM()을 사용하여 열거형을 선언해야 합니다. 예를 들어, 아래의 Message 클래스에는 Status 열거형이 있습니다:

class Message : public QObject
{
    Q_OBJECT
    Q_PROPERTY(Status status READ status NOTIFY statusChanged)
public:
    enum Status {
        Ready,
        Loading,
        Error
    };
    Q_ENUM(Status)
    Status status() const;
signals:
    void statusChanged();
};

Message 클래스가 QML 유형 시스템에 등록되어 있다면, Status 열거형을 QML에서 사용할 수 있습니다:

Message {
    onStatusChanged: {
        if (status == Message.Ready)
            console.log("Message is loaded!")
    }
}

QML에서 열거형을 ` flags ` 유형으로 사용하려면 ` Q_FLAG()`을 참조하십시오.

참고: QML에서 열거형 값에 접근하려면 열거형 값의이름이 대문자로 시작해야 합니다.

...
enum class Status {
          Ready,
          Loading,
          Error
}
Q_ENUM(Status)
...

열거형 클래스는 QML에서 범위 지정 속성(scoped) 및 범위 미지정 속성(unscoped)으로 등록됩니다. Ready 값은 Message.Status.Ready 및 Message.Ready 로 등록됩니다.

열거형 클래스를 사용할 때, 동일한 식별자를 사용하는 여러 열거형이 존재할 수 있습니다. 범위가 지정되지 않은 등록은 가장 최근에 등록된 열거형에 의해 덮어쓰게 됩니다. 이러한 이름 충돌이 발생하는 클래스의 경우, 클래스에 특수한 Q_CLASSINFO 매크로를 주석으로 추가하여 범위가 지정되지 않은 등록을 비활성화할 수 있습니다. 범위가 지정된 열거형이 동일한 네임스페이스로 병합되는 것을 방지하려면 RegisterEnumClassesUnscoped 라는 이름에 false 값을 사용하십시오.

class Message : public QObject
{
    Q_OBJECT
    Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
    Q_ENUM(ScopedEnum)
    Q_ENUM(OtherValue)

public:
    enum class ScopedEnum {
          Value1,
          Value2,
          OtherValue
    };
    enum class OtherValue {
          Value1,
          Value2
    };
};

관련된 타입의 열거형은 일반적으로 해당 타입의 범위 내에 등록됩니다. 예를 들어, ` Q_PROPERTY ` 선언에서 다른 타입의 열거형을 사용하면 해당 타입의 모든 열거형이 QML에서 사용 가능하게 됩니다. 이는 일반적으로 장점이라기보다는 단점으로 작용합니다. 이러한 현상을 방지하려면, 클래스에 특수한 Q_CLASSINFO 매크로를 어노테이션으로 지정하십시오. RegisterEnumsFromRelatedTypes 라는 이름을 사용하고 값으로 false 을 지정하면, 관련 타입의 열거형이 이 타입에 등록되는 것을 방지할 수 있습니다.

QML에서 사용하려는 열거형의 상위 유형은, 해당 열거형이 다른 유형에 주입되기를 기대하기보다는 QML_ELEMENT 또는 QML_NAMED_ELEMENT 를 사용하여 명시적으로 등록해야 합니다.

class OtherType : public QObject
{
    Q_OBJECT
    QML_ELEMENT

public:
    enum SomeEnum { A, B, C };
    Q_ENUM(SomeEnum)

    enum AnotherEnum { D, E, F };
    Q_ENUM(AnotherEnum)
};

class Message : public QObject
{
    Q_OBJECT
    QML_ELEMENT

    // This would usually cause all enums from OtherType to be registered
    // as members of Message ...
    Q_PROPERTY(OtherType::SomeEnum someEnum READ someEnum CONSTANT)

    // ... but this way it doesn't.
    Q_CLASSINFO("RegisterEnumsFromRelatedTypes", "false")

public:
    OtherType::SomeEnum someEnum() const { return OtherType::B; }
};

중요한 차이점은 QML에서 열거형의 범위입니다. 관련 클래스의 열거형이 자동으로 등록되는 경우, 그 범위는 해당 열거형이 임포트된 타입이 됩니다. 위 예시에서, 추가적인 Q_CLASSINFO 없이 Message.A 를 사용하게 될 것입니다. 열거형을 포함하는 C++ 타입이 명시적으로 등록되고, 관련 타입의 열거형 등록이 억제되는 경우, 해당 C++ 타입에 대한 QML 타입이 모든 열거형의 범위가 됩니다. 이 경우 QML에서는 Message.A 대신 OtherType.A 을 사용하게 됩니다.

QML_FOREIGN 를 사용하여 수정할 수 없는 타입을 등록할 수 있다는 점에 유의하십시오. 또한 QML_FOREIGN_NAMESPACE 를 사용하여, 동일한 C++ 타입이 QML 값 타입으로도 등록되어 있더라도, 대문자로 시작하는 임의의 QML 네임스페이스에 해당 C++ 타입의 열거자를 등록할 수 있습니다.

신호 및 메서드 매개변수로 사용되는 열거형

열거형 매개변수를 갖는 C++ 신호 및 메서드는, 열거형과 해당 신호 또는 메서드가 모두 동일한 클래스 내에서 선언되어 있거나, 열거형 값이 Qt Namespace 에 선언된 값 중 하나인 경우에만 QML에서 사용할 수 있습니다.

또한, 열거형 매개변수를 갖는 C++ 신호를 connect() 함수를 사용하여 QML 함수에 연결하려면, 해당 열거형 유형을 qRegisterMetaType()을 사용하여 등록해야 합니다.

QML 신호의 경우, int 타입을 사용하여 열거형 값을 신호 매개변수로 전달할 수 있습니다:

Message {
    signal someOtherSignal(int statusValue)

    Component.onCompleted: {
        someOtherSignal(Message.Loading)
    }
}

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