VEDA 주간 학습 정리
[4주차] Qt 프레임워크
이번 주 학습을 한 문장으로 정리하면: Qt 프레임워크의 핵심 개념, 애플리케이션 종류별 진입 클래스, Qt Creator 기반 앱 제작 흐름 이해
작성일: 2026.04.18
이번 주 학습 목표
- Qt 프레임워크 이해하기
- Qt 설치 과정과 Qt Creator 개발 흐름 익히기
- 콘솔 앱과 GUI 앱의 구조 차이 이해하기
1. Qt 프레임워크 이해하기
개요
- 정의: Qt는 C++ 기반의 크로스플랫폼 애플리케이션 개발 프레임워크이다
- 역사: 1995년 Trolltech에서 시작되어 Nokia, Digia를 거쳐 현재는 The Qt Company가 관리한다
- 철학:
Write once, compile anywhere를 지향하며 동일한 코드베이스를 여러 플랫폼에서 재활용할 수 있게 한다
주요 특징
- 크로스플랫폼: 데스크톱, 모바일, 임베디드, WebAssembly까지 단일 코드베이스로 대응 가능하다
- 두 가지 UI 패러다임: 전통적인 데스크톱 UI를 위한
QWidget, 선언형 UI를 위한Qt Quick / QML을 제공한다 - 시그널과 슬롯: 객체 간 이벤트를 타입 안전하게 연결하는 Qt의 대표 메커니즘이다
- 모듈형 구조: 필요한 모듈만 선택적으로 링크하여 빌드 크기를 조절할 수 있다
- 그래픽 백엔드 지원: OpenGL, Vulkan, Metal 등과 연계해 고성능 렌더링이 가능하다
라이선스 관련 메모
- 오픈소스 버전은 LGPL 조건을 확인해야 하며, 동적 링크 사용 시 사용자 교체권 보장이 자연스럽게 충족된다
- 배포 시 프로그램 정보 창이나 문서에 Qt 사용 사실과 라이선스 고지를 함께 넣는 습관이 중요하다
2. 설치 및 시작하기
- 공식 사이트 qt.io에서 계정을 생성하고 설치 파일을 받는다
Qt User Portal에서 Open Source 버전을 선택해 설치를 진행한다- 설치할 때는 사용할 컴파일러(MSVC, MinGW 등)와 Qt 버전 확인하고 설치한다
- 설치 옵션을 잘못 골랐다면 설치 후 별도의 Qt Maintenance Tool 앱으로 구성 요소를 다시 추가하거나 수정할 수 있다
Qt 설치 화면 예시. 필요한 툴체인과 버전을 함께 선택해야 이후 빌드 오류를 줄일 수 있다.
3. Qt Creator로 앱 제작하기
콘솔 애플리케이션 예제
Qt의 콘솔 앱은 일반 C++ 코드와 매우 비슷하지만, QCoreApplication이 이벤트 루프와 타이머 같은 운영체제 레벨 이벤트 처리를 맡아준다는 차이가 있다.
#include <QCoreApplication>
#include <QTimer>
#include <iostream>
#include <string>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
if (argc != 3 || std::string(argv[1]) != "-w") {
std::cout << "사용법: ./ConsoleApp -w <초>\n";
return 1;
}
int waitSeconds = 0;
try {
waitSeconds = std::stoi(argv[2]);
} catch (const std::exception&) {
std::cout << "오류: 초 단위는 정수로 입력해주세요.\n";
return 1;
}
std::cout << waitSeconds << "초 기다리겠습니다." << std::endl;
QTimer::singleShot(waitSeconds * 1000, &app, &QCoreApplication::quit);
return app.exec();
}
./ConsoleApp -w 5
5초 기다리겠습니다.
핵심 정리
콘솔 앱에서도 Qt를 쓰는 이유는 단순히 GUI 때문만이 아니다. 이벤트 루프, 타이머, 네트워크, 스레드 같은 기능을 Qt 방식으로 일관되게 다룰 수 있다는 장점이 있다.
| 클래스 | 용도 | GUI 지원 | 언제 쓰면 좋은가 |
|---|---|---|---|
QCoreApplication |
콘솔, CLI, 서버, 백그라운드 서비스 | ❌ | GUI 없는 도구나 배치 프로그램 |
QGuiApplication |
QML, OpenGL 기반 창, 네이티브 윈도우 | 부분 지원 | QML 기반 앱이나 커스텀 렌더링 앱 |
QApplication |
전통적인 QWidget 기반 데스크톱 앱 | ✅ | 버튼, 메뉴, 다이얼로그가 있는 일반 GUI 프로그램 |
주의
QWidget 기반 UI를 만들면서 QCoreApplication을 사용하면 창 시스템 초기화가 제대로 되지 않아 빈 창이나 런타임 오류가 날 수 있다. GUI 앱은 반드시 QApplication으로 시작해야 한다.
4. Qt GUI 앱의 기본 구조
| 구성 요소 | 역할 | 대표 클래스 |
|---|---|---|
| 메인 함수 | 프로그램 진입점, 이벤트 루프 실행 | main(), QApplication |
| 위젯 클래스 | 창과 UI 요소의 기본 단위 | QWidget, QMainWindow, QDialog |
| 컨테이너 | 여러 위젯을 담는 부모 UI | QWidget, QFrame, QGroupBox |
| 레이아웃 | 위젯 배치와 크기 관리 | QVBoxLayout, QHBoxLayout, QGridLayout |
| 입력 위젯 | 사용자 입력 수집 | QLineEdit, QPushButton, QCheckBox |
| 출력 위젯 | 텍스트나 상태 표시 | QLabel, QTextBrowser |
| 디자이너 폼 | UI 구조를 XML 형태로 저장하는 설계도 | .ui 파일 |
Connect 함수
connect()는 객체 간의 이벤트 연결을 담당하는 Qt의 핵심 함수이다. 시그널을 보내는 객체와 시그널 함수, 시그널을 받는 객체와 처리할 슬롯 함수를 연결해 준다.
함수 인자들은 C언어에서 배운대로 함수 포인터로 준다.
connect(보내는_객체, &클래스::시그널, 받는_객체, &클래스::슬롯);
로그인 다이얼로그 예제
/* main.cpp
앱의 시발점이자 핵심 로직들이 들어감
화면을 구성하는 화려한 창들도 메인함수 안의 지역변수일 뿐! */
#include "mainwindow.h"
#include "dialog.h"
#include <QMessageBox>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog d;
int result = d.exec();
if(result == QDialog::Accepted){
QString id = d.getId();
QString pw = d.getPw();
QString pwConfirm = d.getPwConfirm();
if(pw != pwConfirm)
QMessageBox::warning(&d, "경고", "패스워드와 확인이 다릅니다.", QMessageBox::Ok);
else{
QMessageBox::information(&d, "정보", QString("ID:\t%1\n\nPW:\t%2").arg(id).arg(pw));
}
}
MainWindow w;
w.show();
return QCoreApplication::exec();
}
/* Dialog.h
로그인창을 구성하는 클래스.
앱을 실행하면서 네가 본 로그인창은 이 클래스 객체
*/
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLineEdit>
class Dialog : public QDialog {
Q_OBJECT
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
QString getId();
QString getPw();
QString getPwConfirm();
private:
QLineEdit *idLineEdit;
QLineEdit *pwLineEdit;
QLineEdit *pwConfirmLineEdit;
};
#endif // DIALOG_H
// Dialog.cpp
// 위젯 클래스의 생성자에서 다른 위젯들을 조물딱거리면서 화면을 구성한다.
// 디자인너로 만들면 이 모든 작업이 ui 객체 초기화, ui.setupUi(this) 두 줄로 끝난다...
#include "dialog.h"
#include <QVBoxLayout>
#include <QFormLayout>
#include <QDialogButtonBox>
Dialog::Dialog(QWidget *parent) :
QDialog(parent)
{
// 레이아웃 및 위젯 생성
QVBoxLayout *mainLayout = new QVBoxLayout(this);
QFormLayout *formLayout = new QFormLayout();
idLineEdit = new QLineEdit(this);
pwLineEdit = new QLineEdit(this);
pwLineEdit->setEchoMode(QLineEdit::Password);
pwConfirmLineEdit = new QLineEdit(this);
pwConfirmLineEdit->setEchoMode(QLineEdit::Password);
formLayout->addRow("아이디:", idLineEdit);
formLayout->addRow("비밀번호:", pwLineEdit);
formLayout->addRow("비밀번호 확인:", pwConfirmLineEdit);
// OK / Cancel 버튼 박스 생성
QDialogButtonBox *buttonBox = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
mainLayout->addLayout(formLayout);
mainLayout->addWidget(buttonBox);
setWindowTitle("Login");
}
Dialog::~Dialog()
{
}
QString Dialog::getId()
{
return idLineEdit->text();
}
QString Dialog::getPw()
{
return pwLineEdit->text();
}
QString Dialog::getPwConfirm()
{
return pwConfirmLineEdit->text();
}
// mainwindow.h
// 로그인 이후 메인 창을 구성하면 된다.
// 지금은 아무것도 없어서 빈 창이 나옴.
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
private:
Ui::MainWindow *ui; // 컴파일 시 mainwindow.ui 디자인너 폼 내용으로 채워진다.
};
#endif // MAINWINDOW_H
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
실행 결과 캡처
아래 이미지는 위 로그인 다이얼로그 코드가 실제로 실행된 화면이다.
로그인 다이얼로그에 아이디와 비밀번호를 입력한 실행 화면.
입력한 정보가 메시지 박스로 출력된 실행 결과.
5. 예제
6. 문제 및 해결 과정
문제 1. 리소스 파일이 프로젝트에 추가되지 않음
문제
이미지나 리소스 파일을 프로젝트에 넣었는데 실행 시 반영되지 않거나, 리소스 경로를 찾지 못하는 상황이 생겼다.
원인 분석
CMake 프로젝트에서 Qt의 자동 처리 옵션이 빠져 있으면 .ui, moc, .qrc 관련 파일이 자동으로 처리되지 않는다. 특히 리소스 파일은 CMAKE_AUTORCC가 빠져 있으면 빌드 결과에 포함되지 않을 수 있다.
해결 방법
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
위 옵션을 켜고 다시 빌드하면 UI, 메타 오브젝트, 리소스 스크립트가 자동 처리되어 문제를 해결할 수 있었다.
리소스 설정과 프로젝트 구성을 점검하던 과정.
문제 2. Windows 보안 경고 때문에 실행 파일이 막힘
문제
빌드된 실행 파일이 정상적으로 만들어졌는데도 Windows에서 보안 경고가 떠서 프로그램 실행이 차단될 수 있다.
원인 분석
스마트 앱 컨트롤이나 보안 정책이 새로 빌드된 실행 파일을 신뢰하지 못해 차단하는 경우가 있다. 이때는 코드 문제가 아니라 운영체제 보안 정책이 실행을 막고 있는 상황일 수 있다.
해결 방법
Windows 설정에서 스마트 앱 컨트롤 상태를 확인하고 필요하면 조정한다. 그 뒤 Qt Creator에서 Build → Clean을 실행하고 다시 빌드하면 꼬인 산출물까지 함께 정리할 수 있다.
Windows 보안 정책 때문에 실행이 막힐 때 확인할 수 있는 설정 화면.