2025. 2. 28. 14:37ㆍ프로그래밍 언어/Python
6. 실전 프로젝트와 최적화
이번 주차에서는 대규모 GUI 애플리케이션 설계, 성능 최적화, 멀티스레딩, 비동기 작업 처리를 배웁니다.
특히 모듈화, 이벤트 루프 최적화, 데이터베이스 연동 및 백그라운드 작업 처리를 적용하여 고급 TODO 리스트 애플리케이션을 제작하고, 개인 프로젝트를 기획 및 구현하는 것이 목표입니다.
이론
1. 대규모 애플리케이션 설계
간단한 GUI 애플리케이션은 단일 파일로 작성해도 문제가 없지만, 기능이 많아질수록 코드의 유지보수와 성능 관리가 어려워지므로 모듈화와 클래스 기반 설계가 필요합니다.
✅ 모듈화 적용
애플리케이션을 기능별로 분리하면 코드의 가독성이 좋아지고 유지보수가 쉬워집니다.
예를 들어, 데이터베이스, UI, 이벤트 처리를 각각의 파일로 분리하면 관리가 더 용이해집니다.
📁 프로젝트 구조 예시
/todo_app
├── main.py # 애플리케이션 실행 파일
├── database.py # 데이터베이스 관리 모듈
├── ui.py # Tkinter UI 구성 모듈
├── requirements.txt # 패키지 목록
database.py (데이터베이스 관련 코드)
import sqlite3
class Database:
def __init__(self, db_name="todo.db"):
self.conn = sqlite3.connect(db_name)
self.cur = self.conn.cursor()
self.cur.execute("""
CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY,
task TEXT,
priority INTEGER,
deadline TEXT
)
""")
self.conn.commit()
def add_task(self, task, priority, deadline):
self.cur.execute("INSERT INTO tasks (task, priority, deadline) VALUES (?, ?, ?)", (task, priority, deadline))
self.conn.commit()
def get_tasks(self):
self.cur.execute("SELECT * FROM tasks ORDER BY priority DESC")
return self.cur.fetchall()
def close(self):
self.conn.close()
✅ 이제 Database 클래스를 활용하여 데이터베이스 연산을 손쉽게 수행할 수 있습니다.
2. 성능 최적화
Tkinter GUI에서 성능을 향상시키려면 이벤트 루프 최적화, 위젯 수 감소, 메모리 관리 등의 기법을 적용해야 합니다.
1) 이벤트 루프 최적화
Tkinter는 after() 메서드를 사용하여 반복적으로 실행되는 작업을 효율적으로 처리할 수 있습니다.
def update_label():
label.config(text="업데이트됨!")
root.after(1000, update_label) # 불필요한 반복 호출 방지
root = tk.Tk()
label = tk.Label(root, text="대기 중...")
label.pack()
root.after(1000, update_label) # 1초마다 UI 업데이트
root.mainloop()
✅ 불필요한 UI 업데이트를 최소화하여 애플리케이션의 반응성을 개선합니다.
2) 위젯 수 감소 및 메모리 관리
Tkinter에서 위젯이 많아지면 성능이 저하될 수 있으므로 불필요한 위젯을 삭제하거나 숨기는 방식을 활용해야 합니다.
def toggle_label():
""" 필요할 때만 위젯을 표시/숨김 """
global label_visible
if label_visible:
label.pack_forget() # 위젯 숨기기
else:
label.pack() # 다시 표시
label_visible = not label_visible
root = tk.Tk()
label_visible = True
label = tk.Label(root, text="이 위젯을 숨길 수 있습니다.")
label.pack()
btn = tk.Button(root, text="토글", command=toggle_label)
btn.pack()
root.mainloop()
✅ 위젯을 삭제하지 않고 pack_forget()을 사용하면 메모리를 절약할 수 있습니다.
3. 멀티스레딩 (비동기 작업 처리)
Tkinter는 싱글 스레드 기반이므로 네트워크 요청, 데이터베이스 연산 등의 작업을 실행할 때 UI가 멈출 수 있습니다.
이를 방지하려면 백그라운드 스레드에서 작업을 실행하고, UI 업데이트는 메인 스레드에서 수행해야 합니다.
📌 안전한 멀티스레딩 예제
import threading
import time
import tkinter as tk
def long_running_task():
""" 시간이 오래 걸리는 작업을 백그라운드에서 실행 """
time.sleep(5)
root.after(0, lambda: label.config(text="작업 완료!")) # UI 업데이트는 after() 사용
def start_task():
thread = threading.Thread(target=long_running_task)
thread.start()
root = tk.Tk()
root.title("멀티스레딩 예제")
label = tk.Label(root, text="작업 대기 중...")
label.pack()
btn = tk.Button(root, text="작업 시작", command=start_task)
btn.pack()
root.mainloop()
✅ 이제 UI가 멈추지 않고 백그라운드에서 작업을 실행할 수 있습니다.
실습: 고급 TODO 리스트 애플리케이션
📌 주요 기능
- 카테고리, 우선순위, 마감일 관리
- SQLite 데이터베이스 연동 및 백업 기능
- 멀티스레딩 적용하여 UI 멈춤 방지
import threading
import sqlite3
import tkinter as tk
from tkinter import ttk
# 데이터베이스 연결
conn = sqlite3.connect("todo.db")
cur = conn.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY, task TEXT, priority INTEGER, deadline TEXT)")
conn.commit()
def add_task():
""" 새로운 작업을 추가하는 함수 (멀티스레딩 적용) """
task = entry.get()
priority = priority_var.get()
deadline = deadline_entry.get()
if task:
threading.Thread(target=lambda: add_task_db(task, priority, deadline)).start()
def add_task_db(task, priority, deadline):
""" 백그라운드에서 데이터베이스 업데이트 """
cur.execute("INSERT INTO tasks (task, priority, deadline) VALUES (?, ?, ?)", (task, priority, deadline))
conn.commit()
root.after(0, lambda: entry.delete(0, tk.END))
root.after(0, update_list)
def update_list():
""" 기존 목록을 초기화하지 않고 효율적으로 갱신 """
cur.execute("SELECT * FROM tasks ORDER BY priority DESC")
rows = cur.fetchall()
tree.delete(*tree.get_children()) # 기존 항목 삭제
for row in rows:
tree.insert("", tk.END, values=row)
root = tk.Tk()
root.title("TODO 리스트")
entry = tk.Entry(root, width=40)
entry.grid(row=0, column=0, padx=5, pady=5)
priority_var = tk.IntVar()
priority_dropdown = ttk.Combobox(root, textvariable=priority_var, values=[1, 2, 3])
priority_dropdown.grid(row=0, column=1, padx=5, pady=5)
priority_dropdown.current(0)
deadline_entry = tk.Entry(root, width=15)
deadline_entry.grid(row=0, column=2, padx=5, pady=5)
add_btn = tk.Button(root, text="추가", command=add_task)
add_btn.grid(row=0, column=3, padx=5, pady=5)
tree = ttk.Treeview(root, columns=("ID", "Task", "Priority", "Deadline"), show="headings")
tree.heading("ID", text="ID")
tree.heading("Task", text="할 일")
tree.heading("Priority", text="우선순위")
tree.heading("Deadline", text="마감일")
tree.grid(row=1, column=0, columnspan=4, padx=5, pady=5)
update_list()
root.mainloop()
conn.close()
✅ 멀티스레딩을 활용하여 UI가 멈추지 않고 데이터를 처리할 수 있습니다.
📌 최종 정리
- 대규모 애플리케이션 설계: 모듈화, 클래스 기반 설계 적용
- 성능 최적화: 이벤트 루프 최적화, 메모리 관리, 위젯 수 감소
- 멀티스레딩 적용: UI 멈춤 방지
- 실습: SQLite 연동 TODO 리스트 제작 및 성능 최적화
'프로그래밍 언어 > Python' 카테고리의 다른 글
Python Tkinter - 8. Tkinter 추천 프로젝트 (0) | 2025.02.28 |
---|---|
Python Tkinter - 7. Tkinter 심화 주제 (0) | 2025.02.28 |
Python Tkinter - 5. 그래픽과 애니메이션 (0) | 2025.02.28 |
Python Tkinter - 4. 메뉴, 다이얼로그, 스타일링 (0) | 2025.02.03 |
Python Tkinter - 3. 고급 위젯과 데이터 관리 (0) | 2025.02.03 |