시그널(Signals)과 슬롯(Slots)의 이해
by
gg582 · 2026-07-02 01:06:20 · 33 views
목차
시그널(Signals)과 슬롯(Slots)의 이해
이전 강의에서는 QObject::connect()를 사용하여 푸시 버튼과 팝업 대화상자를 연결해 보았습니다. 애플리케이션은 기대한 대로 동작했지만, 우리는 이 연결 과정을 하나의 블랙박스처럼 사용했을 뿐 그 내부 동작은 살펴보지 않았습니다.
이번 강의에서는 Qt 프레임워크의 핵심 이벤트 기반 통신 메커니즘인 시그널(Signals) 과 슬롯(Slots) 을 통해 Qt 객체들이 서로 어떻게 통신하는지 알아보겠습니다.
1. 객체 간 통신 이해하기
일반적인 C++ 프로그램에서는 객체가 다른 객체의 포인터나 참조를 가지고 직접 멤버 함수를 호출하는 방식으로 동작합니다.
하지만 GUI 애플리케이션은 조금 다르게 설계됩니다. 버튼은 자신이 클릭된 이후 어떤 일이 일어나는지 알 필요가 없습니다. 대신, 단순히 "클릭되었다" 라는 사실만 알려주면 됩니다.
Qt는 이러한 구조를 시그널(Signals) 과 슬롯(Slots) 이라는 개념으로 구현합니다.
시그널(Signal) 은 어떤 이벤트가 발생했음을 알리는 역할을 합니다.
슬롯(Slot) 은 그 이벤트에 반응하여 실행되는 함수입니다.
그리고 QObject::connect()가 두 요소를 연결하여 통신이 이루어지도록 합니다.
전체적인 흐름은 다음과 같습니다.
사용자가 버튼 클릭
│
▼
QPushButton가 clicked() 시그널 발생
│
▼
QObject::connect()
│
▼
연결된 슬롯 실행
│
▼
팝업 대화상자 표시
이러한 구조 덕분에 객체들은 서로를 직접 의존하지 않고도 통신할 수 있으며, 결과적으로 프로그램을 더욱 확장하기 쉽고 유지보수하기 쉬운 형태로 만들 수 있습니다.
2. 시그널과 슬롯 연결하기
이전 강의에서 작성한 프로그램에는 이미 시그널과 슬롯을 연결하는 데 필요한 모든 요소가 포함되어 있습니다.
소스 코드: main.cpp
#include <QApplication>
#include <QPushButton>
#include <QMessageBox>
int main(int argc, char **argv) {
QApplication app(argc, argv);
QPushButton button("Hello, Popup!");
button.resize(300, 100);
QObject::connect(
&button,
&QPushButton::clicked,
[&button]() {
QMessageBox::information(
&button,
"Qt 6",
"Hello, Popup!"
);
}
);
button.show();
return app.exec();
}
비교적 짧은 코드이지만, Qt의 시그널과 슬롯 메커니즘이 어떻게 동작하는지를 모두 담고 있는 예제입니다.
QObject::connect() 이해하기
QObject::connect(...)
이 함수는 시그널과 실행할 코드를 서로 연결하는 역할을 합니다.
한 번 연결이 완료되면, 해당 시그널이 발생할 때마다 Qt가 자동으로 연결된 콜백을 호출합니다.
시그널 이해하기
&QPushButton::clicked
clicked()는 QPushButton 클래스에 정의되어 있는 시그널입니다.
사용자가 버튼을 클릭하면 Qt가 자동으로 이 시그널을 발생(emits)시킵니다.
버튼은 이후 어떤 작업이 수행되는지 알지 못합니다. 단지 "버튼이 클릭되었다" 는 사실만 전달할 뿐입니다.
슬롯 이해하기
[&button]() {
QMessageBox::information(
&button,
"Qt 6",
"Hello, Popup!"
);
}
이 람다 함수가 슬롯의 역할을 합니다.
clicked() 시그널이 발생하면 Qt는 이 람다 함수를 실행합니다.
최신 Qt에서는 간단한 작업을 위해 별도의 콜백 함수를 만들 필요 없이, 람다 표현식을 슬롯으로 직접 사용할 수 있습니다.
3. 이벤트 전달 과정
사용자가 마우스로 버튼을 클릭하면, 팝업이 나타나기까지 내부적으로 다음과 같은 과정이 진행됩니다.
운영체제가 마우스 클릭을 감지합니다.
Qt가 이벤트 루프를 통해 운영체제로부터 이벤트를 전달받습니다.
해당 이벤트가 적절한 위젯으로 전달됩니다.
QPushButton이clicked()시그널을 발생시킵니다.Qt가 해당 시그널에 연결된 모든 슬롯을 찾습니다.
연결된 각 슬롯을 순서대로 실행합니다.
이와 같은 이벤트 기반 구조는 사용자 인터페이스와 프로그램의 동작을 분리하여, 서로 직접 의존하지 않는 독립적인 구성 요소들이 자연스럽게 협력할 수 있도록 해 줍니다.
4. 애플리케이션 빌드하기
이번 예제에서는 프로그램의 동작만 변경되었으므로 프로젝트 구조는 이전과 동일합니다.
빌드 설정: CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(HelloPopup)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 REQUIRED COMPONENTS Widgets)
add_executable(HelloPopup main.cpp)
target_link_libraries(HelloPopup PRIVATE Qt6::Widgets)
소스 코드를 수정한 후 프로젝트를 다시 빌드합니다.
mkdir -p build
cd build
cmake ..
make -j$(nproc)
./HelloPopup
프로그램을 실행한 뒤 버튼을 클릭하면, Qt가 clicked() 시그널을 발생시키고, 연결된 슬롯을 실행하여 팝업 대화상자를 화면에 표시합니다.
구성 요소별 역할 정리
- 시그널(Signal): 특정 이벤트가 발생했음을 알립니다.
- 슬롯(Slot): 시그널에 반응하여 실행되는 함수입니다.
QObject::connect(): 시그널과 슬롯을 서로 연결합니다.- 람다 함수(Lambda Function): 간단한 슬롯을 별도의 함수 없이 직접 구현하는 방법입니다.
- 이벤트 루프(
app.exec()): 운영체제로부터 이벤트를 받아 적절한 Qt 객체에 전달하고 처리합니다.
다음 강의에서는 첫 번째 QMainWindow 애플리케이션을 만들어 보며, Qt가 메인 윈도우, 중앙 위젯(Central Widget), 그리고 레이아웃(Layout) 을 사용하여 보다 규모가 큰 GUI 애플리케이션을 어떻게 구성하는지 살펴보겠습니다.