4강에서 설명드린 스레드 사용시 발생되는 문제점을 해결하기위해 이번 강의에서는 싱글턴을 코딩해보도록 하겠습니다. 스레드 사용시 필수적으로 구현되어야 하므로 반드시 이해가 동반되어야 합니다.
[유튜브 강의, 링크]와 같이 보시면 많은 도움이 되실 겁니다.
아래 내용이 이해가지 않으시면 블로그 글 제일 아래에 코드와 요약이 있으니 확인 바랍니다.
1. 코드 분석
우선 새로운 스크립트를 파일/nwe/pythone file을 클릭 후 kiwoom.py 스크립트를 만드셔야 됩니다.

(1) 파이썬 함수 불러오기
7강에서 설명드린바와 같이 이번에도 파이썬 내장 함수를 가져옵니다. 문구는 from A improt B 입니다.

◈import PyQt5.QtWidgets import * : PyQt5.QtWidgets의 모든 함수를 가져옵니다.
- 위젯이란 여러분들이 사용하는 프로그램의 클릭 버튼/표/진행바 등을 제어 하는 요소들을 통합적으로 부르는 말입니다. 이것을 가져와야 여러분들이 원하는 그래픽적인 기능을 수행할 수 있습니다.
- 만약 함수가 존재하지 않을 경우 그림과 같이 하단의 terminal을 선택한 후 pip install pyqt5를 입력 후 엔터 치세요.

◈import PyQt5.QAxContainer import * : PyQt5.QAxContainer의 모든 함수를 가져옵니다.
- 키움증권의 클래스를 사용할 수 있게 합니다.
◈import PyQt5Singleton import Singleton : PyQt5Singleton의 Singleton 함수를 가져옵니다.
- 함수가 없을 경우 위의 그림의 terminal을 선택한 후 pip install singleton 또는 pip install PyQt5Singleton 입력 후 엔터 치세요.
(2) 싱글턴 클래스 생성하기 : 매타클래스 이용
싱글턴 기능을 하는 매타클래스를 만들게 되면, 이를 이용하여 만든 클래스는 인스턴스가 오직 하나만 존재합니다. 간략히 말씀드리면, 유일한 객체를 만들 수 있게 된다는 뜻입니다. (객체 : a, b, c....와 같은 것)
싱글턴을 생성하는 방법은 크게 5가지가 존재합니다. 저는 복잡한 방법을 설명하기 보다 내장 함수를 그대로 클래스에 상속시켜 사용하는 법을 택하였습니다.

◈ class Kiwoom(QWwidget, metaclass=Singleton) : Kiwoom 클래스는 metaclass=Singleton에 의해 생성된 객체입니다. 즉, Kiwoom 클래스는 매타클래스에 의해 이미 인스턴스화 되었다는 의미입니다. 그러므로 Kiwoom에서 생성되는 모든 객체는 유일한 것이 됩니다(이 부분이 가장 중요합니다). .
- 매타클래스 : 클래스를 관리하는 클래스, 클래스라는 객체를 만들기 위한 클래스(어렵죠? 차차 알아 봅시다)
- 객체 : a = b에서 a는 객체, b는 클래스
- 인스턴스 : a = b에서 a는 b의 인스턴스 (말 장난 같지만... 잘 이해하시 바랍니다.)
◈ def __init__(self, parent=None, **kwargs)
- __init__ : 아래에 사용할 self가 붙은 다양한 변수들을 초기화 하는 역할 입니다. 초기화를 해야 컴퓨터가 준비를 하겠죠?
- parent=None : 특별히 parent를 명시하지 않아도 된다는 의미 입니다. Kiwoom은 이미 Singleton의 인스턴스이기 때문입니다.
- **kwargs : 키워드파라메터 인자를 def에 보낼 때 사용합니다. 키워드 파라메터는 x = 1, b = 2, c = 3와 같은 형태이고 출력은 (x, 1), (y, 2), (c, 3)과 같습니다.
◈ super().__init__(parent, **kwargs) : super는 우리가 만든 class(Kiwoom), 즉 superior class의 부모 class를 찾는 과정이라 생각하시면 됩니다. 단순히 말하면 우리가 상속받은 QWidget, metaclass=Singleton를 사용하기 위해 적는 코드입니다. 그리고 키워드파라메터 인자를 넣고자 **kwargs를 정의하였습니다.
(3) 키움 로그인 객체 생성 : 유일한 객체
키움에 로그인하기 위해서는 QAxWidget('KHOPENAPI.KHOpenAPICtrl.1')의 인스턴스가 반드시 필요합니다. 앞으로 키움에서 제공하는 함수를 사용하기 위해서는 "반드시" self.kiwoom을 사용해야 합니다.

키움증권에서 제공하는 클래스는 각각 고유의 CLSID 또는 ProgID를 가지고 있습니다. 해당 값을 QAxWidget클래스로 전달하면 인스턴스가 생성되는데 이때 인스턴스는 self.kiwoom이라 정의 하였습니다.
키움증권 개발 가이드를 참조하면 ProgID는 'KHOPENAPI.KHOpenAPICtrl.1'임을 알 수 있고 이를 QAxWidget로 전달합니다. 이렇게 하면 우리는 키움증권 클래스를 사용할 수 있게 됩니다.
앞으로 각각의 스레드에서 키움 주문과 검색을 할텐데 모든 스레드에서는 QAxWidget('KHOPENAPI.KHOpenAPICtrl.1')을 입력해야 합니다. 하지만 우리는 Kiwoom이라는 클래스의 self.kiwoom에 객체화 했기 때문에 유일한 값이 되어 각각의 스레드에서는 Kiwoom 클래스에 접속하는 순간 키움의 모든 클래스를 사용할 수 있게 됩니다.
쉽게 말씀드리면, Kiwoom 클래스에 명시된 값들은 유일한 값을 가지고 절대적이라 스레드가 여기에 접속만 한다면 키움 증권의 어떤 클래스든 사용할 수 있다는 뜻입니다.(마법은 언어 입니다.)
2. 요약
모든 클래스와 스레드들이 각자 놀지 않고 서로서로 통신을 하기 위해서는 절대적인 교두보가 필요합니다. 이역할을 하는 것이 싱글턴이며, 매타클래스를 활용하여 만들어집니다. 우리는 Kiwoom이라는 클래스를 싱글턴으로 만들었고 Kiwoom 클래스 내에 정의된 모든 변수와 객체는 다른 모든 클래스와 스레드들이 공유할 수 있습니다. 예로 스레드에서 키움 클래스를 사용하기 위해서는 스레드마다 QAxWidget('KHOPENAPI.KHOpenAPICtrl.1')를 할당해야 되나, 우리는 Kiwoom이라는 클래스를 싱글턴에 QAxWidget('KHOPENAPI.KHOpenAPICtrl.1')을 할당하여 키움증권 클래스를 사용하고 싶은 클래스 또는 스레드가 접속만 하면 모든 기능이 수행되게끔 만들었습니다. 너~무 어려운 내용입니다. 중급이나 고급 정도 되셔야 이해가 되는 내용이지만 ALBA 프로그램이 이를 바탕으로 제작되었기 때문에 설명 드리고 넘어 갑니다. 혹시 이해가 되지 않으시면 코드만 입력하시면 되겠습니다. 앞으로도 계속 설명드릴 것입니다.
9강 바로가기 : 지금까지 했던 모든 코드들을 모아 두었습니다. 확인!

from PyQt5.QtWidgets import * # GUI의 그래픽적 요소를 제어 하단의 terminal 선택, activate py37_32, pip install pyqt5, 전부다 y
from PyQt5.QAxContainer import * # 키움증권의 클레스를 사용할 수 있게 한다.(QAxWidget)
from PyQt5Singleton import Singleton
class Kiwoom(QWidget, metaclass=Singleton): # QMainWindow : PyQt5에서 윈도우 생성시 필요한 함수
def __init__(self, parent=None, **kwargs): # Main class의 self를 초기화 한다.
print("로그인 프로그램을 실행합니다.")
super().__init__(parent, **kwargs)
################ 로그인 관련 정보
self.kiwoom = QAxWidget('KHOPENAPI.KHOpenAPICtrl.1') # CLSID
'주식 자동매매 강의 > 기초반(모든 코딩의 뿌리)' 카테고리의 다른 글
주식자동매매 10강. 키움 증권 로그인 전 기본기 쌓기 (0) | 2022.04.27 |
---|---|
주식자동매매 9강. 1~8강 복습 및 정리(초심자 용, 최종 코드) (4) | 2022.04.26 |
주식자동매매 7강. 파이썬을 이용해 GUI 화면 띄우기[코드 제공] (11) | 2022.04.25 |
주식자동매매 6강. 로그인을 위한 코드 기본 구조 셋팅(파이썬/GUI) (3) | 2022.04.25 |
주식자동매매 5강. 자동매매 구축 시 GUI의 필요성과 기능 설명 (2) | 2022.04.24 |