건물을 짓기 전에는 설계를 먼저 해야 합니다.
프로그램도 마찬가지입니다. 프로그램을 제작하기 전 설계를 해야 합니다. 그건 규모와 상관 없이 중요한 일입니다. 무슨 일을 하기 전에 계획을 세우는 건 당연한건데, 저는 PyWallpaper를 제작하면서 설계 과정을 따로 거치지 않았습니다. 그랬던 것에 대한 반성 겸 이 글을 보고 프로그램을 만드는 누군가가 저와 같은 실수를 하지 않길 바라며 프로그램 구조 설계를 앞부분에 배치해서 글을 씁니다.
프로그램 구조 설계하기 - 요구사항 작성하기
백지에서 뭔가를 시작한다는 건 쉬운 일이 아닙니다. 저도 마찬가지였습니다. 저는 전문 프로그래머도 아니고 프로그래밍을 제대로 배워본 적도 없습니다. 그럼에도 이렇게 백지에서 시작하는 것은, 윈도우의 배경화면을 더 아름답게 쓸 수 있는데 실제로는 그렇지 못하다는 점에서 불편함을 느꼈고, 이를 해결하기 위함입니다. 프로그램 구조를 설계할 때 어떤 방법론이 있는지는 잘 모르겠습니다. 일단 프로그램을 제작하기 전에 만들어낼 기능들을 미리 정해둡니다. 저는 제가 만들 프로그램이 다음의 기능을 수행하기를 바랍니다.
1. 시간에 따라서 배경화면 변경(일출 / 일몰 시간 반영은 추후에 할 일)
2. 윈도우 작업표시줄 트레이에 상주(중간에 꺼지거나 하지 않도록)
3. 설정창
4. 윈도우 시작시 자동 시작5. 배경화면 다운로드하기
사실 이것도 제 애초 계획과는 좀 다르게 많이 빠진 상태이긴 한데 일단 최소 기능 구현 목표(MVP) 제작에 초점을 맞추겠습니다. 파이썬에서 다음의 기능을 수행하는 프로그램을 만들 수 있을까? 하는 생각이 들었지만 딥러닝도 잘 굴리는 파이썬이 뭘 못할까 싶었습니다. 그래서 수 일간에 걸친 이런 저런 삽질 끝에 어떻게 만들면 되는지에 대한 길을 찾았습니다. 제가 이렇게 삽질을 할 때마다 '내가 컴퓨터공학과에, 어느정도 경력이 있는 프로그래머라면 달랐을까, 좀 삽질을 덜 했을까' 하는 자괴감이 많이 들지만 일단은 빡세게...삽질을 해봤습니다.
요구사항을 충족하는 기술적인 방법 찾기
이름은 거창하지만 사실 별거 없습니다. 저는 파이썬을 쓰기로 했기 때문에 필요한 기능을 찾고, 어떤 기능이 필요한지만 일단 나열해보겠습니다.
시간에 따라서 배경화면 변경 | 시간을 불러오는 모듈 time과 이미지 처리를 담당하는 OpenCV(cv2)를 사용합니다. 배경화면을 바꾸기 위해서는 유저 프로필이 담긴 윈도우 DLL 을 건드려야 합니다. 앞선 포스팅에서 언듭했듯 ctypes를 사용합니다.
윈도우 작업표시줄 트레이에 상주 | GUI를 제작하는 것이니 PyQt5를 사용합니다.
설정창 | 윈도우 파일 관련 담당하는 os와 shutil, 설정파일(.ini)를 읽고 쓸 수 있는 configparser를 사용합니다.
윈도우 시작시 자동 시작 | 윈도우 파일 관련 담당하는 os와 shutil을 사용합니다.
배경화면 다운로드하기 | 웹을 담당하는 urlib를 사용합니다.
막상 나열하고 보니 모듈이 은근히 많은데 이 모든 모듈을 활용해서 하나의 프로그램을 제작합니다. 보통을 이런 모듈이 필요할 것이라 예상하지는 않고 그냥 코드를 짜다 어? 이게 필요하겠는데? 하면 그냥 모듈 불러와서 씁니다.
프로그램이 전반적으로 돌아가는 Blueprint 제작하기
PyWallpaper를 제작하면서 느낀 점 중 하나는, 이렇게 작은 규모의 프로그램이라도 분명 동시작업을 할 일이 생깁니다. 따라서 어떤 클래스나 함수를 만들 때 이걸 어디에 어떻게 써야 하고, 어떤 걸 받아서 어떤 걸 출력할지에 대한 명확한 인지 하에 만들어야 여러 작업을 하는 와중에 혼선 없이 기능을 잘 추가해나갈 수 있습니다. 초기에 저는 프로그램 짜는 과정 전체를 크레이프 케이크 만들듯이 그냥 기능 하나 만들어보고 되면 메인 프로그램에 얹고 또 기능 만들어보고 되면 얹는 식으로 접근했습니다. 그 결과는? 중간에 한 번 갈아엎었습니다. 그렇기에 처음에 클래스들을 만들 때 클래스의 역할을 확실히 지정해 줘야 합니다. 여기에서는 각자 기능을 수행하는 클래스를 몇 개 정의해보겠습니다.
#프론트엔드
class InitDownloadGui # pyqt gui, 초기 실행시 배경화면 다운로드를 담당합니다.
class DownloadProgressGui # pyqt gui, 배경화면 다운로드 과정을 담당합니다.
class MainGui # pyqt gui, 설정을 담당합니다.
# 관리자
class MainQLogic # 프론트엔드와 백엔드를 모두 관리하는... 플랫폼같은 역할입니다.
#백엔드
class ImgDownloadThread # InitDownloadGui 에서 배경화면 리스트를 받아 배경화면을 다운로드하는 스레드입니다.
class MainThread # 실시간으로 시간 값을 받아와 배경화면 변경의 Trigger가 되는 스레드입니다.
class ConfigManager # configparser 모듈이 있지만 매번 불러올 수도 없고 번거로우니 설정을 관리하는 클래스를 만듭니다.
class Main # 시간에 따라 배경화면을 바꾸는 로직이 들어갑니다.