가상환경을 구축하는 방법으로 Virtual Box, VMWare 등을 사용할 수 있습니다.

Vagrant 를 사용하면 스크립트로 원하는  VM 을 쉽게 구축할 수 있습니다.

또 여러개의  VM 도 쉽게 만들 수 있습니다.

코딩을 하다보면 Oracle, Mysql 등의 Database 를 설치하거나 redis 등의 서버를 설치하는 경우가 있습니다.

docker 를 사용할 수도 있지만 ssh 로 직접 설정을 바꿔보고 싶은 경우 VM 이 좀더 나은 선택일 수도 있습니다.

1) Virtual Box 설치

VirtualBox는 오라클에서 개발한 가상화 소프트웨어입니다.

설치 방법은 아래 URL  에서 자신의 OS 에 맞게 다운로드하면 됩니다.

https://www.virtualbox.org/wiki/Downloads

 

Downloads – Oracle VirtualBox

This VirtualBox Extension Pack Personal Use and Educational License governs your access to and use of the VirtualBox Extension Pack. It does not apply to the VirtualBox base package and/or its source code, which are licensed under version 3 of the GNU Gene

www.virtualbox.org

저는 Windows 에 설치해보겠습니다.

 

 

기본설치로 진행해보겠습니다.

Next 를 계속 눌러서 설치를 진행하면 됩니다.

 

설치는 시간이 걸립니다. 느긋하게 기다리면 됩니다.

 

확장 패키지를 다운로드합니다.

이제 확장 패키지를 설치합니다.

도구 > 확장 패키지 관리자를 선택합니다.

 

설치를 클릭합니다.

 

다운받은 확장 패키지를 선택 후 설치합니다.

 

설치가 완료되면 확장 패키지가 활성화 됩니다.

 

2) Vagrant 설치

아래 URL 에서 OS 맞게 선택 후 설치합니다.

https://developer.hashicorp.com/vagrant/install

 

Install | Vagrant | HashiCorp Developer

Explore Vagrant product documentation, tutorials, and examples.

developer.hashicorp.com

 

 Windows 64 비트의경우 AMD64 를 선택하면 됩니다.

 

License 동의 후에 Install 을 클릭합니다.

 

설치에 시간이 걸리므로 잠시 기다려주면 됩니다.

 

 

3) NAT 네크워크 설정

Vagrant 로 VM 생성 시 NAT 네크워크 설정이 필요합니다.

 

호스트 전용 네트워크를 클릭합니다.

 

NAT 네트워크는 DHCP 를 사용하거나 직접 IP 를 설정할 수  있습니다.

DHCP 설정의 경우 Client 에서 IP 설정을 할 필요가 없지만 할당된 IP가 변경이 될 수 있으므로 DHCP 를 사용하지 않겠습니다.

DHCP 를 사용해도 됩니다. 본인이 선택을 하면 됩니다.

우선 DHCP 비활성화로 예를 들어 설명하겠습니다.

아래와 같이 DHCP 서버 활성화를 체크해제하여 비활성화 시킵니다.

 

어댑터 탭을 보면 수동으로 어댑터 설정이 되어 있습니다.

IPv4 주소는 192.168.56.1 이고 서브넷 마스크는 255.255.255.0  입니다.

Client IP 는 192.168.56.xx 로 설정이 가능합니다.

만약 다른 IPv4 주소를 사용하고 싶으면 다른 주소를 선택하면 됩니다.

'유틸리티 > Vagrant' 카테고리의 다른 글

Vagrant 1.3편-Rocky Linux 에 MariaDB 설치  (1) 2025.04.05
Vagrant 1.2편-Rocky Linux 에 Oracle 설치  (2) 2025.03.31
Posted by 제이브레인
,

python 으로 Database 라이브러리는 다양한 종류가 존재합니다.

다양한 Python 데이터베이스 검색 라이브러리를 비교한 표를 정리하면 다음과 같습니다.

라이브러리 지원 데이터베이스 주요 특징 장점 단점
SQLAlchemy MySQL, PostgreSQL, SQLite, Oracle, MSSQL 등 강력한 ORM(Object Relational Mapping) 기능 제공 객체 지향적인 방식으로 SQL 조작 가능, 다양한 DB 지원 학습 곡선이 가파를 수 있음
Peewee MySQL, PostgreSQL, SQLite 등 경량 ORM, 간결한 코드 사용법이 간단하고 빠름 대규모 프로젝트에는 부족할 수 있음
Django ORM PostgreSQL, MySQL, SQLite, Oracle Django 프레임워크와 통합된 ORM Django 사용 시 강력한 기능 제공 Django 프로젝트 외 사용이 번거로울 수 있음
PonyORM MySQL, PostgreSQL, SQLite 등 Pythonic한 쿼리 지원 직관적인 SQL 문법, 자동화된 관계 관리 대규모 시스템에서는 성능 문제 가능성 있음
Tortoise-ORM PostgreSQL, MySQL, SQLite 등 비동기 ORM 지원 asyncio 기반, 빠른 비동기 쿼리 처리 비동기 환경이 아닌 경우 사용이 어렵거나 필요 없음
TinyDB JSON 기반의 파일 DB NoSQL 방식, 경량 데이터베이스 설정이 간단하고 파일 기반 저장 가능 대용량 데이터 처리에 적합하지 않음
Whoosh 자체 인덱싱 엔진 사용 풀텍스트 검색 엔진 Python 내에서 검색 엔진 구축 가능 대규모 검색 시스템에는 부족할 수 있음
Elasticsearch-py Elasticsearch 강력한 검색 엔진과 연동 대량 데이터 검색 최적화 설정 및 유지보수가 어려울 수 있음
PyMongo MongoDB NoSQL 데이터베이스 연결 라이브러리 JSON 기반 문서 저장, 유연한 데이터 구조 관계형 데이터베이스 지원 부족
Qdrant Client Qdrant (벡터 데이터베이스) 벡터 기반 검색 지원 AI 및 유사 이미지 검색 등에 최적화 전통적인 SQL 검색이 아닌 경우 부적합

어떤 데이터베이스를 사용하려는지에 따라 적절한 라이브러리를 선택하면 됩니다! 😊

SQLAlchemy 를 사용해서 Database 를 검색하는 기능을 추가해보겠습니다.

간단한 Member 라는 테이블을 만들어서 Name 으로 검색하고 결과를 출력하는 기능을 추가하겠습니다.

1) 코드 생성

Database 는 간단하게 파일로 생성할 수 있는 SQLite 를 사용하였습니다.

ChatGPT 에 사용한 프롬프트입니다.

pyqt5 로 실행 시 window 에 다음을 추가해주세요.
첫째 라인 : Meber Name 라는 GroupBox 로 둘러싸인 LineEdit, Search 버튼
둘째 라인 : Name, Age 이라는 Column 을 가지는 Grid

초기 실행 시 SQLite members.db 를 존재하지 않으면 생성하고 Member 테이블을 생성한 후에 테스트 데이터를 추가합니다.
테스트 데이터에는 Name 이 값은 Member 도 여러명 존재하고 Name 이 고유한 데이터도 존재해야 합니다.

SQLine 에 String Name, Intger Age 라는 Member 테이블을 만듭니다.
Seach 버튼을 클릭하면 SqlAlchemy 로 Member 테이블을 검색하여 Member Name LineEdit 에 입력된 값으로 검색하여 Name 이 일치하는 
레코드를 찾습니다.
일치하는 데이터를 찾으면 Grid 에 Name, Age 를 추가합니다.

 

생성된 코드는 다음과 같습니다.

위 코드는 아래 git 에서도 다운받을 수 있습니다.

git clone git@github.com:jbpark/jbDeskExample.git
cd jbDeskExample/jbDesk/ch2.1

 

search_database.py

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QGroupBox, QLineEdit, QPushButton, QTableWidget, \
    QTableWidgetItem, QHBoxLayout
from sqlalchemy import create_engine, Column, Integer, String, select
from sqlalchemy.orm import declarative_base, sessionmaker
import os

# 데이터베이스 설정
DATABASE_URL = "sqlite:///members.db"
engine = create_engine(DATABASE_URL, echo=True)
Base = declarative_base()
Session = sessionmaker(bind=engine)
session = Session()


# Member 테이블 정의
class Member(Base):
    __tablename__ = "members"
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    age = Column(Integer, nullable=False)


# 데이터베이스 및 테이블 생성 (존재하지 않으면 생성)
if not os.path.exists("members.db"):
    Base.metadata.create_all(engine)


    # 테스트 데이터 추가
    def add_test_data():
        test_members = [
            Member(name="Alice", age=30),
            Member(name="Alice", age=28),
            Member(name="Bob", age=25),
            Member(name="Charlie", age=35),
            Member(name="David", age=40)
        ]
        session.add_all(test_members)
        session.commit()


    add_test_data()


class MemberSearchApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        main_layout = QVBoxLayout()

        # 첫째 라인: Member Name GroupBox + Search 버튼
        name_layout = QHBoxLayout()
        self.name_group = QGroupBox("Member Name")
        self.name_input = QLineEdit()
        group_layout = QVBoxLayout()
        group_layout.addWidget(self.name_input)
        self.name_group.setLayout(group_layout)

        self.search_button = QPushButton("Search")
        self.search_button.clicked.connect(self.search_member)

        name_layout.addWidget(self.name_group)
        name_layout.addWidget(self.search_button)
        main_layout.addLayout(name_layout)

        # 둘째 라인: Grid Table (Name, Age)
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(["Name", "Age"])
        main_layout.addWidget(self.table)

        self.setLayout(main_layout)

        self.setWindowTitle("Member Search")
        self.setGeometry(100, 100, 400, 300)

    def search_member(self):
        name = self.name_input.text().strip()
        if not name:
            return

        # SQLAlchemy 검색
        stmt = select(Member).where(Member.name == name)
        results = session.execute(stmt).scalars().all()

        self.table.setRowCount(len(results))
        for index, member in enumerate(results):
            self.table.setItem(index, 0, QTableWidgetItem(member.name))
            self.table.setItem(index, 1, QTableWidgetItem(str(member.age)))


if __name__ == "__main__":
    app = QApplication([])
    window = MemberSearchApp()
    window.show()
    app.exec_()

이제 UI가 다음과 같이 변경되었습니다:

  1. 첫째 라인
    • "Member Name"을 포함하는 QGroupBox 내에 QLineEdit
    • Search 버튼
  2. 둘째 라인
    • QTableWidget을 사용해 "Name", "Age" 컬럼을 포함하는 그리드
  3. 기능 추가
    • SQLite 데이터베이스 members.db를 생성하고 Member 테이블을 설정
    • 테스트 데이터 추가 (동일한 Name을 가진 여러 레코드 포함)
    • Search 버튼 클릭 시 Name으로 검색하여 그리드에 일치하는 레코드 표시

2) 코드 실행

SQLAlchemy 를 사용하므로 패키지를 실행전에 패키지를 설치해야 합니다.

pip install sqlalchemy

생성된 테스트 데이터를 보면 Alice 로 Name 이 동일한 Member 가 여러명 있는 것을 확인할 수 있습니다.

검색 시 아래와 같이 모든 Member 가 Grid 에 표시됨을 확인 할 수 있습니다.

코딩이 정말 쉽지 않나요?

아라비안 나이트에 알라딘의 요술램프가 있다면 요즘은 ChatGPT 같은 인공 지능 요술램프가 있는 것 같습니다.

 

3) JbDesk 코드 통합

JbDesk 에 통합 후 실행한 이미지입니다.

통합된 코드는 다음과 같이 git 에서 다운로드 할 수 있습니다.

git clone git@github.com:jbpark/jbDeskExample.git
cat jbDeskExample/jbDesk/ch2.1/jbdesk.py

 

코드 실행은 다음과 같이 run.bat 파일로 실행이 가능합니다.

run.bat 에는 패키지 설치도 포함되어 있습니다.

@echo off
set CONDA_ENV_NAME=jbdesk38_64

:: Conda 활성화
call conda activate base

:: Conda 환경 목록 확인 후 존재하지 않으면 생성
conda info --envs | findstr /C:"%CONDA_ENV_NAME%" >nul
if %errorlevel% neq 0 (
    echo Creating conda environment: %CONDA_ENV_NAME%
    conda create -y -n %CONDA_ENV_NAME% python=3.8
)

:: Conda 환경 활성화
call conda activate %CONDA_ENV_NAME%

:: PyQt5 설치
pip show PyQt5 >nul 2>nul
if %errorlevel% neq 0 (
    echo Installing PyQt5...
    pip install PyQt5
)

:: pytz 설치
pip show pytz >nul 2>nul
if %errorlevel% neq 0 (
    echo Installing pytz...
    pip install pytz
)

:: sqlalchemy 설치
pip show sqlalchemy >nul 2>nul
if %errorlevel% neq 0 (
    echo Installing sqlalchemy...
    pip install sqlalchemy
)

:: jbdesk.py 실행
python jbdesk.py

Posted by 제이브레인
,

Python에서는 메서드, 함수, 변수, 파일 이름은 snake_case, 클래스 이름은 CamelCase ,
**상수는 ALL_CAPS**로 작성하는 것이 표준입니다. 🚀

정리 요약

항목 표기법 표기법
클래스(Class) CamelCase class StockManager:
메서드(Method) snake_case def process_order(self):
함수(Function) snake_case def calculate_profit():
변수(Variable) snake_case stock_price = 1000
상수(Constant) ALL_CAPS MAX_RETRIES = 3
파일(File) snake_case.py order_processor.py
모듈(Module) snake_case trading_utils.py
패키지(Package) snake_case (소문자, 밑줄 없이) finance

 

1) 코드 정리

py 파일에서 많이 사용하는 표기법으로 jbdesk.py 파일을 정리하고 method 의 경우 string_util, log_util 로 분리하였습니다.

PyCharm 에서는 리팩토링 기능을 제공합니다.

그래서 다른 파일로 이동하거나 method 로 분리할 때 쉽게 할 수 있습니다.

string 관련 유틸리티 method 를 string_util.py 로 분리해보겠습니다.

우선 lib/string_util.py 를 생성합니다.

그리고 jbdesk.py 에서 다음과 같이  to_pascal_case_line 과 같은 string 관련 유틸리티 method 를 마우스로 선택 후에 

리팩터링 > 이동을 선택합니다.

 

대상 위치를 string_util.py 를 선택 후 [리팩토링] 버튼을 클릭합니다.

 

그러면 해당 method 들이 string_util 로 이동이 됩니다.

특정 라인을 method 로 추출하기 위해서는 아래와 같이 특정 라인을 선택 후 리팩터링 > 메서드 추출을 선택합니다.

 

2) 리팩터링 코드

리팩터링한 코드는 아래 위치에서 확인이 가능합니다.

git clone git@github.com:jbpark/jbDeskExample.git
cd jbDeskExample/jbDesk/ch1.6
Posted by 제이브레인
,