PyQt로 GUI앱을 만들었다

기존 Python + Selenium으로 만들었던 툴을 GUI 앱으로 만들어보기로 했다. 로그인 정보를 user.py라는 파일에 하드코딩하는 것도 좀 그렇고, 이슈 개수마다 template을 따로 복사해서 특정 폴더에 계속 가지고 있어야 하는 것도 솔직히 조금 귀찮았기 때문에, GUI로 만들면 실행 파일 하나로만 모든 걸 실행할 수 있지 않을까 싶었다.

Python의 GUI 라이브러리는 뭐가 있을까 싶어 찾아보다가, Kivy가 눈에 띄었다. 라이브러리 자체에 크게 고민은 하지 않았는데, 앱 자체가 단순히 입력 필드 몇 개와 submit 버튼만 있으면 되는 간단한 구조이기 때문이다.

그렇게 Kivy를 사용해서 GUI를 만들고 있었는데 pyinstaller를 사용해서 exe로 빌드 후 실행하려고 하면 실행이 안됐다. 딱히 오류는 없어보였는데, 실행하면 아래처럼 터미널에 로그 같은 것들이 출력이 되더니 그냥 종료됐다.

Purge log fired. Processing... 
Purge finished! 
195 symbols loaded 
Providers: img_tex, img_dds, img_sdl2, img_pil (img_ffpyplayer ignored)
Provider: sdl2

디버깅을 계속하다가 도저히 모르겠어서 PyQt로 갈아탔다. 팀원 중에서도 Python으로 GUI를 만들어서 공유했던 분이 있는데, PyQt를 사용했다고 들은 기억이 있고 실제로 exe 빌드 시 실행이 잘 되었다 (나중에 내가 만든 앱을 공유할때 다시 물어봤는데 PyQt가 아니고 Tkinter를 사용했다고 한다 😅).

기존 코드에 PyQt를 추가해서 연동시키는 작업은 순조로웠고, 대략 1.5일 정도 걸려서 완성했다.

기존에는 exe파일과 로그인 정보를 담는 파일 , 그리고 이슈를 저장할 폴더가 따로 있었다. 이슈를 생성할 때마다 해당 폴더에 있는 template.py 파일을 복사해서 issue1.py, issue2.py와 같이 만든 후 프로그램을 실행하는 구조였다.

하지만 지금은 .exe 실행파일 딱 하나만 존재한다.

앱을 실행 시키면 앱 내에 로그인 정보와 이슈 내용을 바로 입력할 수 있다. 기존에 issue1.py, issue2.py, …를 추가하던 구조와 비슷하게 앱 내에 tab이 따로 존재한다. 각 탭이 하나의 이슈를 의미하며 탭을 추가해서 필요한 만큼 이슈를 생성할 수 있다.

일단 팀원들한테 공유를 하기는 했는데 잘 쓸지는 모르겠다 😅


  • 2025/05/25 - 1:45

앱 실행 후 매번 로그인 정보를 따로 입력했어야 했는데, 입력한 정보를 기억할 수 있도록 Save credential 기능을 추가했다.

로그인 정보 입력 후 Save credential checkbox를 선택하면, 해당 프로그램이 실행됐던 폴더 내에 user.dat파일이 생성된다. 해당 파일에 ID와 Passwod가 기록된다. 프로그램 실행할 때, 해당 파일이 있는지 확인하고 존재하면 로그인 정보를 불러온다.

처음에는 입력한 정보 그대로 plain text로 파일에 저장했었는데, 아무래도 비밀번호를 그대로 저장하는 건 좀 위험하다 싶어서 암호화 하기로 했다. 처음에는 단순히 bcrypt를 사용해서 저장했는데 one-way hashing이였다. One-way hashing인 경우 입력한 비밀번호를 파일에 암호화하여 저장할 수 있지만, 암호화된 비밀번호를 다시 plain text로 바꿀수가 없어서 해당 동작과는 맞지 않았다.

그러다가 cryptography.fernet 라이브러리를 알게되었고 해당 라이브러리를 사용해서 비밀번호의 암호화(encryption)과 복호화(decryption)을 구현할 수 있었다.

from cryptography.fernet import Fernet

key = Fernet.generate_key()
f = Fernet(key)

token = f.encrypt(b"hello world")
print(token) 

d = f.decrypt(token)
print(d)

비밀번호만 암호화했고, 아이디는 평문 그대로 파일에 쓰고있는데, 아이디도 암호화하는 것이 좋을까??


  • 2025/05/28 - 12:50

프로그램을 공유받고 사용하던 팀원 한 명이 아래와 같은 질문을 했다.

“디폴트 값들은 못바꾸죠?”

아무래도 내가 쓰려고 만든 앱이다 보니, 기본 값들은 내가 사용하는 것들로 적용이 되어있다. 그러다보니 생각도 못했었는데, 위 한 마디로 프로그램을 크게 수정했다.

  1. Save default -> 디폴트 값 변경하여 저장
  2. Load default -> 디폴트로 저장한 값 불러오기
  3. Reset -> 기본값으로 리셋

위 기능을 구현하면서 전체적인 구조가 살짝 변경되었고, 하는 김에 shortcut도 추가했다.

  • Ctrl + S -> Save Default
  • Ctrl + L -> Load Default
  • Ctrl + R -> Reset
  • Ctrl + D -> Delete current tab
  • Ctrl + N -> New tab
  • Ctrl + Tab -> 다음 탭으로 이동
  • Ctrl + Shift + Tab -> 이전 탭으로 이동

Save에서 각각 다른 이름의 파일로 저장해서, Load할 때 마치 템플렛을 불러오듯이 구현할까 생각했지만, 일단은 간단하게 현재 폼의 내용을 저장하고 불러오는 방식으로 구현했다. 만약 template이 유용하다 싶으면 그 때 업데이트 할 예정이다.

Backlinks: