1강. Signal & Slot: 구조 이해

0. 학습 목표
이번 단계에서는 QPushButton 버튼 클릭을 기준으로 Qt의 Signal / Slot 구조를 이해합니다.
Qt 프로그램에서는 사용자가 버튼을 클릭하거나, 키보드를 입력하거나, 창을 닫는 것처럼 다양한 동작이 발생합니다.
이런 동작을 GUI 프로그램이 처리하려면 어떤 일이 발생했는지 알리고, 그 다음 어떤 함수를 실행할지 연결해야 합니다.
Qt에서는 이 구조를 Signal / Slot이라고 부릅니다.
| 학습 목표 | 내용 |
| 위젯과 함수 연결 이해 | 버튼 위젯과 실행될 함수를 연결하는 구조를 이해합니다. |
| Signal 개념 이해 | QPushButton에는 clicked라는 Signal이 미리 정의되어 있음을 이해합니다. |
| Slot 개념 이해 | Signal이 발생했을 때 실행되는 함수를 Slot으로 이해합니다. |
| connect() 사용법 이해 | Signal → Slot을 연결하는 기본 문법을 학습합니다. |
| 기본 GUI 이벤트 처리 구현 | 버튼 클릭 시 콘솔에 문장을 출력하는 가장 기본적인 이벤트 처리를 구현합니다. |

이번 단계의 핵심
버튼을 클릭하면 clicked Signal이 발생하고, connect()로 연결된 함수가 자동으로 실행됩니다.
1. Signal / Slot 개념 이해하기
1.1 QPushButton 기준으로 이해하기
이번 예제에서는 QPushButton을 사용합니다.
QPushButton은 Qt에서 제공하는 버튼 위젯입니다.
사용자가 버튼을 클릭하면 QPushButton 내부에서 clicked라는 Signal이 발생합니다.
사용자가 버튼 클릭
↓
QPushButton의 clicked Signal 발생
↓
connect()로 연결된 함수 실행
즉, Signal / Slot 구조는 버튼과 함수가 서로 연결되는 방식이라고 생각하면 됩니다.
1.2 Signal
Signal은 어떤 일이 발생했다는 것을 알려주는 신호입니다.
예를 들어 버튼을 클릭하면 버튼은 스스로 clicked라는 Signal을 발생시킵니다.
이때 개발자가 직접 clicked Signal을 만드는 것이 아니라,
QPushButton 안에 이미 정의되어 있는 Signal을 사용하는 것입니다.
| 구분 | 설명 |
| Signal | 어떤 일이 발생했음을 알려주는 신호입니다. |
| 예시 | 버튼이 클릭되면 clicked Signal이 발생합니다. |
| 발생 시점 | 사용자가 버튼을 클릭했을 때 자동으로 발생합니다. |
1.3 Slot
Slot은 Signal이 발생했을 때 실행되는 함수입니다.
PySide6에서는 특별한 문법을 사용하지 않아도 일반 Python 함수를 Slot처럼 사용할 수 있습니다.
예를 들어 아래 함수는 버튼 클릭 후 실행될 Slot 함수로 사용할 수 있습니다.
def button_clicked():
print("버튼을 클릭하셨네요!")
이 함수는 혼자서는 자동으로 실행되지 않습니다. 버튼의 clicked Signal과 연결해야 버튼을 클릭했을 때 실행됩니다.
1.4 connect()
connect()는 Signal과 Slot을 연결하는 메서드입니다.
button.clicked.connect(button_clicked)
위 코드는 다음과 같은 의미입니다.
button의 clicked Signal이 발생하면
↓
button_clicked 함수가 자동으로 실행된다
주의할 점
connect() 안에는 button_clicked()처럼 괄호를 붙이지 않습니다.
괄호를 붙이면 버튼을 클릭하기 전에 함수가 바로 실행될 수 있습니다.
| 개념 | 설명 |
| Signal | 이벤트 발생을 알리는 메시지입니다. 예: clicked |
| Slot | Signal을 받았을 때 실행되는 함수입니다. |
| connect() | Signal과 Slot을 연결하는 Qt의 핵심 메서드입니다. |
2. 예제 코드
2.1 실습 준비
이번 예제는 PyCharm에서 진행합니다.
새 Python 프로젝트를 만들고, 프로젝트 가상환경에 PySide6가 설치되어 있는 상태에서 진행합니다.
예제 파일명은 main.py로 작성합니다.
2. PyCharm 프로젝트 생성
1. 일반 프로젝트 생성하기더보기 2. 커스텀 가상환경으로 프로젝트 시작하기 더보기 PyCharm에서 Custom environment를 선택하는 이유 기본 Project venv를 그대로 사용하지 않고, Virtualenv, Conda, Poetry, uv 같
basiclike.tistory.com
2.2 main.py 예제 코드
import sys
from PySide6.QtWidgets import QApplication, QPushButton
def button_clicked():
print("버튼을 클릭하셨네요!")
app = QApplication(sys.argv)
button = QPushButton("버튼을 클릭하세요.")
button.clicked.connect(button_clicked)
button.show()
sys.exit(app.exec())

이 코드를 실행하면 화면에 버튼을 클릭하세요 버튼이 나타납니다.

버튼을 클릭하면 PyCharm 실행창에 다음 문장이 출력됩니다.
버튼을 클릭하셨네요!
2.3 예제에서 확인할 핵심 구조
| 코드 | 의미 |
| QPushButton("버튼을 클릭하세요") | 화면에 표시할 버튼을 생성합니다. |
| button.clicked | 버튼이 클릭되었을 때 발생하는 Signal입니다. |
| button_clicked | 버튼 클릭 후 실행될 Slot 함수입니다. |
| connect() | clicked Signal과 button_clicked Slot 함수를 연결합니다. |
2.4 예제 파일
3. 코드 분석
3.1 주석 포함 전체 코드
import sys # [1] 파이썬 인터프리터 관련 기능을 제공하는 sys 모듈을 가져옴
from PySide6.QtWidgets import ( # [2] PySide6의 위젯 관련 클래스들 중에서
QApplication, # - QApplication: 전체 어플리케이션(프로그램)을 관리하는 클래스
QPushButton # - QPushButton: 화면에 보이는 버튼 위젯 클래스
)
# [3] 버튼 클릭 시 실행될 함수 정의
# - 이 함수는 버튼이 클릭되었을 때 실행될 함수
# - Qt에서는 이런 함수를 Slot(슬롯)이라고 부름
def button_clicked():
print("버튼을 클릭하셨네요!") # [4] 버튼 클릭 시 콘솔에 출력될 문장
app = QApplication(sys.argv) # [5] QApplication 객체 생성
# - 모든 Qt GUI 프로그램은 QApplication 객체가 필요함
# - sys.argv: 실행 시 명령줄 인자 리스트
# (예: python main.py arg1 arg2 ...)
# - 일부 Qt/PySide 옵션을 명령줄에서 받을 수 있기 때문에
# 관례적으로 sys.argv를 넣어 줌
button = QPushButton("버튼을 클릭하세요") # [6] 버튼 위젯 객체 생성
# - "버튼을 클릭하세요"는 버튼 위에 표시될 텍스트
button.clicked.connect(button_clicked) # [7] Signal과 Slot 연결
# - button.clicked:
# * 버튼이 클릭되었을 때 발생하는 Signal
# - connect(button_clicked):
# * clicked Signal이 발생하면
# button_clicked 함수가 실행되도록 연결
# - 주의:
# * button_clicked()처럼 괄호를 붙이지 않음
# * 괄호를 붙이면 버튼 클릭 전에 함수가 바로 실행될 수 있음
button.show() # [8] 버튼을 실제로 화면에 보이도록 함
# - show()를 호출해야 화면에 나타남
# - 호출하지 않으면 프로그램은 실행되지만 버튼이 보이지 않음
sys.exit(app.exec()) # [9] 이벤트 루프(Event Loop) 시작
# - app.exec():
# * 마우스 클릭, 키보드 입력, 창 닫기 등
# 각종 이벤트를 계속해서 처리하는 루프
# * 사용자가 창을 닫으면 이 함수가 종료되면서
# 종료 코드를 int 값으로 반환
# - sys.exit(...):
# * 반환된 종료 코드를 운영체제에 전달하며
# 프로그램을 깔끔하게 종료</code></pre>
3.2 단계별 분석
1단계: 라이브러리 가져오기
import sys
from PySide6.QtWidgets import QApplication, QPushButton
PySide6 GUI 프로그램을 만들기 위해 필요한 클래스를 가져옵니다.
| 이름 | 역할 |
| sys | 프로그램 실행 인자와 종료 처리를 위해 사용합니다. |
| QApplication | Qt 애플리케이션 실행 환경을 만듭니다. |
| QPushButton | 화면에 표시할 버튼 위젯을 만듭니다. |
2단계: Slot 함수 정의
def button_clicked():
print("버튼을 클릭하셨네요!")
이 함수는 버튼이 클릭되었을 때 실행될 함수입니다.
Qt에서는 Signal이 발생한 뒤 실행되는 함수를 Slot이라고 부릅니다.
PySide6에서는 일반 Python 함수도 Slot처럼 사용할 수 있습니다.
따라서 이 함수 자체에는 특별한 문법이 필요하지 않습니다.
3단계: QApplication 생성
app = QApplication(sys.argv)
모든 Qt GUI 프로그램은 QApplication 객체가 필요합니다.
QApplication은 GUI 프로그램 전체의 실행 환경을 관리합니다.
특히 마우스 클릭, 키보드 입력, 창 닫기 같은 사용자 입력을 처리하는 이벤트 루프와 관련이 있습니다.
4단계: 버튼 생성
button = QPushButton("버튼을 클릭하세요")
QPushButton 객체를 생성합니다. "Press Me"는 버튼 위에 표시될 텍스트입니다.
5단계: Signal과 Slot 연결
button.clicked.connect(button_clicked)
이 코드가 이번 예제의 핵심입니다.
button.clicked
→ 버튼 클릭 Signal
connect(button_clicked)
→ Signal이 발생했을 때 실행할 함수 연결
즉, 사용자가 버튼을 클릭하면 clicked Signal이 발생하고, 이 Signal과 연결된 button_clicked 함수가 자동으로 호출됩니다.
6단계: 버튼 화면에 표시
button.show()
생성한 버튼을 화면에 표시합니다. 위젯을 생성했다고 해서 자동으로 화면에 나타나는 것은 아닙니다. 화면에 표시하려면 show()를 호출해야 합니다.
7단계: 앱 실행
sys.exit(app.exec())
app.exec()는 Qt 이벤트 루프를 시작합니다.
이벤트 루프가 실행되어야 GUI 창이 유지되고, 사용자의 클릭이나 키보드 입력을 처리할 수 있습니다.
4. Qt Designer에서 구현할 때의 구조
4.1 코드로 만든 버튼과 Designer로 만든 버튼의 차이
앞의 예제에서는 Python 코드에서 직접 버튼을 만들었습니다.
button = QPushButton("버튼을 클릭하세요")
button.clicked.connect(button_clicked)
하지만 Qt Designer를 사용하면 버튼을 코드로 직접 만들지 않고, Designer 화면에서 버튼을 배치한 뒤 form.ui 파일로 저장합니다.
그 다음 form.ui 파일을 Python 코드로 변환하면 ui_form.py 파일 안에 버튼 객체가 만들어집니다.
이때 버튼은 보통 다음과 같은 형태로 접근합니다.
self.ui.pushButton
4.2 Qt Designer 기반 작업 흐름
Qt for Python 프로젝트 생성
↓
Qt Designer에서 Push Button 배치
↓
form.ui 파일 저장
↓
form.ui 파일을 ui_form.py로 변환
↓
Widget 클래스에서 self.ui.pushButton 접근
↓
self.ui.pushButton.clicked.connect(self.button_clicked)
구조는 앞의 예제와 같습니다.
차이점은 버튼을 직접 코드로 생성하느냐, Designer에서 만든 버튼을 가져와 사용하느냐입니다.
| 구분 | 코드 방식 | Qt Designer 방식 |
| 버튼 생성 | QPushButton 코드로 직접 생성 | Designer에서 버튼 배치 |
| 버튼 접근 | button | self.ui.pushButton |
| Slot 함수 | 일반 함수 | 클래스 내부 메서드 |
| connect 구조 | button.clicked.connect(button_clicked) | self.ui.pushButton.clicked.connect(self.button_clicked) |
4.3 GUI Designer 작업



4.4 form.ui를 ui_form.py로 변환하기
Qt Designer에서 만든 form.ui 파일은 그대로 Python 코드에서 사용할 수 없습니다.
일반적으로 다음 명령으로 form.ui → ui_form.py 파일로 변환합니다.

pyside6-uic form.ui -o ui_form.py


변환이 끝나면 ui_form.py 파일이 생성됩니다.
이 파일 안에는 Designer에서 배치한 버튼, 라벨, 입력창 같은 위젯 정보가 Python 코드로 들어 있습니다.
4.4 ui_form.py 파일 적용하기
Qt Designer 방식에서는 화면 구성을 담당하는 ui_form.py를 가져온 뒤,
Widget 클래스 안에서 Signal과 Slot을 연결합니다.

import sys
from PySide6.QtWidgets import QApplication, QWidget
from ui_form import Ui_Widget
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_Widget()
self.ui.setupUi(self)
# [✓] 클래스 내부 메서드는 self로 연결해야 함
self.ui.pushButton.clicked.connect(self.button_clicked)
# [✓] 클래스 내부에서 호출될 슬롯은 self 인자를 가져야 함
def button_clicked(self):
print("버튼을 클릭하셨네요!")
if __name__ == "__main__":
app = QApplication(sys.argv)
widget = Widget()
widget.show()
sys.exit(app.exec())


4.5 self가 필요한 이유
Qt Designer 방식에서는 버튼이 Widget 클래스 내부에서 사용됩니다.
따라서 버튼도 self.ui.pushButton 형태로 접근하고, Slot 함수도 self.button_clicked 형태로 연결합니다.
중요한 점
클래스 내부에 있는 메서드를 Slot으로 연결할 때는 self.button_clicked처럼 self를 붙여야 합니다.
| 코드 | 설명 |
| self.ui = Ui_Widget() | Designer에서 만든 UI 클래스를 객체로 생성합니다. |
| self.ui.setupUi(self) | 현재 Widget 화면에 UI 구성을 적용합니다. |
| self.ui.pushButton | Designer에서 배치한 버튼 위젯에 접근합니다. |
| self.button_clicked | Widget 클래스 내부에 정의된 Slot 메서드입니다. |
5. 정리
이번 단계에서는 QPushButton을 사용하여 Qt의 Signal / Slot 구조를 처음으로 살펴보았습니다.
핵심 흐름은 다음과 같습니다.
버튼 클릭
↓
clicked Signal 발생
↓
connect()로 연결된 Slot 함수 호출
↓
button_clicked() 함수 실행
| 개념 | 정리 |
| Signal | 어떤 일이 발생했음을 알려주는 신호입니다. |
| Slot | Signal이 발생했을 때 실행되는 함수입니다. |
| connect() | Signal과 Slot을 연결합니다. |
| clicked | QPushButton에서 버튼 클릭 시 발생하는 대표적인 Signal입니다. |
이번 단계에서 기억할 문장
Qt GUI 프로그램은
사용자의 동작을 Signal로 알리고,
connect()로 연결된 Slot 함수를 실행하는 방식으로 동작합니다.