반응형
반응형

 

이미지 읽어서 스케치 형식으로 변환

# img_to_sketch_001.py
# 이미지 읽어서 스케치 형식으로 변환


# 파이썬 컴파일 경로가 달라서 현재 폴더의 이미지를 호출하지 못할때 작업디렉토리를 변경한다. 
import os
from pathlib import Path
# src 상위 폴더를 실행폴더로 지정하려고 한다.
###real_path = Path(__file__).parent.parent
real_path = Path(__file__).parent
print(real_path)
#작업 디렉토리 변경
os.chdir(real_path) 


import cv2
import numpy as np
import os

def convert_to_sketch(image_path, output_path="sketch_output.jpg"):
    """
    사진을 읽어들여 스케치 형식으로 변환하고 저장합니다.
    """
    try:
        # 1. 이미지 로드
        img = cv2.imread(image_path)
        if img is None:
            print(f"오류: 이미지를 로드할 수 없습니다. 경로를 확인하세요: {image_path}")
            return

        # 2. 이미지를 회색조로 변환
        gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        
        # 3. 이미지 반전 (어두운 부분은 밝게, 밝은 부분은 어둡게)
        # 펜으로 그린 선처럼 보이게 합니다.
        inverted_img = 255 - gray_img
        
        # 4. 가우시안 블러 적용
        # 이미지를 부드럽게 만들고, 반전된 이미지와 블렌딩할 때 경계를 부드럽게 합니다.
        # (21, 21)은 커널 크기, 0은 시그마 값 (자동 계산)
        blurred_img = cv2.GaussianBlur(inverted_img, (21, 21), 0)
        
        # 5. 컬러 닷지 블렌드 모드 적용 (스케치 효과의 핵심)
        # 원본 회색조 이미지와 블러 처리된 반전 이미지를 혼합합니다.
        # "닷지(Dodge)" 모드는 밝은 영역을 더 밝게 만들고, 어두운 영역의 디테일을 유지합니다.
        # OpenCV에서는 직접적인 닷지 블렌드 모드 함수를 제공하지 않으므로, 수학적 연산을 사용합니다.
        # result = (gray_img * 256) / (255 - blurred_img + epsilon)
        # 여기서 255 - blurred_img가 0이 되는 것을 방지하기 위해 작은 값(epsilon)을 더합니다.
        epsilon = 10 # 0으로 나누는 것을 방지하기 위한 작은 상수
        sketch_img = cv2.divide(gray_img, 255 - blurred_img + epsilon, scale=256)
        
        # 6. 결과 이미지 저장
        cv2.imwrite(output_path, sketch_img)
        print(f"스케치 이미지가 '{output_path}'로 성공적으로 저장되었습니다.")

    except Exception as e:
        print(f"스케치 변환 중 오류 발생: {e}")

# --- 사용 예시 ---
# 1. 'input_image.jpg' 라는 이름의 사진 파일을 이 파이썬 스크립트와 같은 폴더에 놓으세요.
# 2. 또는 정확한 이미지 파일 경로를 지정하세요.
input_image_path = "person_01.jpg"

# 파일명과 확장자 분리 및 새 파일명 생성
file_name_without_extension, file_extension = os.path.splitext(input_image_path)
output_sketch_path = f"{file_name_without_extension}_sketch{file_extension}"
 
print(f"원본 파일명: {input_image_path}")
print(f"확장자 없는 파일명: {file_name_without_extension}")
print(f"확장자: {file_extension}")

#output_caricature_path = file_name_without_extension + "_caricature_result." + file_extension
# F-string을 사용하여 문자열 내부에 변수를 직접 삽입합니다.
output_sketch_path = f"{file_name_without_extension}_caricature_result{file_extension}"



convert_to_sketch(input_image_path, output_sketch_path)

# 결과 이미지 확인 (선택 사항)
# try:
#     # OpenCV로 이미지 표시 (OpenCV 창을 사용)
#     result_img = cv2.imread(output_sketch_path)
#     if result_img is not None:
#         cv2.imshow("Sketch Image", result_img)
#         cv2.waitKey(0)  # 아무 키나 누를 때까지 대기
#         cv2.destroyAllWindows() # 모든 OpenCV 창 닫기
#     else:
#         print("결과 이미지를 읽을 수 없습니다.")
# except FileNotFoundError:
#     print("결과 이미지를 찾을 수 없어 미리보기를 실행할 수 없습니다.")
# except Exception as e:
#     print(f"결과 이미지 미리보기 중 오류 발생: {e}")

반응형
반응형

[python] 대상 주식을 시계와 함께 실행하는 .exe 파일 만들기

 

 

.EXE로 배포하기. 

pyinstaller --onefile --windowed miniClockApp_finance_003.py

 

 

miniClockApp_finance_003.py

# pyinstaller --onefile --windowed miniClockApp_finance_003.py
# 시간과 슬라이드 바 사이에 공백이 없이 100% fill 로 처리하는데 시계는 center에 위치하고 아래의 버튼과도 100% fill.
# 공백을 완전히 없애고 100% 채움(fill) 처리하며, 시계는 중앙에 위치하도록 수정
"""
초미니 시계가 나타나고, 상단에는 주식의 이름, 현재가, 목표가, 그리고 차이가 함께 표시되며 주기적으로 순환합니다.
'Full Screen' 버튼을 눌러 전체 화면으로 전환하면 전체 배경이 불투명 검은색으로 변하고, 주식 및 시계 정보가 더 크게 표시됩니다. 
바탕화면을 클릭하면 다시 원래 크기로 돌아옵니다.
"""

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QSizePolicy
from PyQt5.QtCore import QTimer, QTime, Qt, QPoint, QEvent
from PyQt5.QtGui import QFont, QColor
import yfinance as yf # 주식 데이터 가져오기 위한 라이브러리

class MiniClockApp(QWidget):
    def __init__(self):
        super().__init__()
        self.is_fullscreen = False  # 전체 화면 상태 추적 변수
        self.old_pos = None         # 창 이동을 위한 이전 마우스 위치 저장
        
        # 모니터링할 주식 목록과 목표 가격 설정
        self.stocks_to_monitor = {
            '007310.KS': ('오뚜기', 396167),
            '215200.KQ': ('메가스터디교육', 36900),
            '005930.KS': ('삼성전자', 49900),
            '005387.KS': ('현대차2우B', 133300),
            '138910.KS': ('KODEX 구리 선물 ETF', 7190),
            'META': ('메타', 450.80),
            'AMZN': ('아마존', 151.61)
        }
        self.formatted_stock_data = [] # 주식 전체 정보를 저장할 리스트
        self.current_stock_index = 0 # 현재 표시 중인 주식 정보 인덱스

        self.initUI()
        
        # 창 플래그 설정: 프레임 없이, 항상 위에, 배경 투명 (초미니 시계에 적합)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) 
        self.setAttribute(Qt.WA_TranslucentBackground) 

        # 전체화면 시 바탕화면 클릭 감지를 위한 이벤트 필터 설치
        QApplication.instance().installEventFilter(self)

        # 1초마다 시간 업데이트 타이머
        self.time_timer = QTimer(self)
        self.time_timer.timeout.connect(self.update_time) 
        self.time_timer.start(1000) 

        # 30초마다 주식 가격 데이터 가져오기 타이머
        self.stock_fetch_timer = QTimer(self)
        self.stock_fetch_timer.timeout.connect(self.fetch_and_process_stock_prices)
        self.stock_fetch_timer.start(30000) # 30초마다 업데이트

        # 3초마다 주식 정보 순환 표시 타이머
        self.stock_display_timer = QTimer(self)
        self.stock_display_timer.timeout.connect(self.display_next_stock_info)
        self.stock_display_timer.start(3000) # 3초마다 순환

        # 초기 업데이트
        self.update_time()
        self.fetch_and_process_stock_prices() # 앱 시작 시 바로 주식 데이터 가져오기

    def initUI(self):
        # 윈도우 설정
        self.setWindowTitle('초미니 시계 & 주식 모니터')
        self.setGeometry(100, 100, 400, 400) # 초기 위치 및 크기
        self.setMinimumSize(400, 400) # 최소 크기 400x400으로 고정

        # 메인 레이아웃 (세로 방향)
        main_layout = QVBoxLayout()
        self.setLayout(main_layout)
        # 전체 레이아웃의 안쪽 여백과 위젯 간 간격을 모두 0으로 설정하여 꽉 차게 만듦
        main_layout.setContentsMargins(0, 0, 0, 0) 
        main_layout.setSpacing(0) 

        # 주식 정보 표시 레이블
        self.stock_info_label = QLabel(self)
        self.stock_info_label.setAlignment(Qt.AlignCenter) # 중앙 정렬
        self.stock_info_label.setFont(QFont('Arial', 12)) # 폰트 크기 12px
        self.stock_info_label.setStyleSheet("color: #FFFFFF; background-color: rgba(0,0,0,180); padding: 0px;") 
        # 수직 방향으로 확장 가능하도록 설정 (Vertical, Expanding)
        self.stock_info_label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        main_layout.addWidget(self.stock_info_label)

        # 시간 표시 레이블
        self.time_label = QLabel(self)
        self.time_label.setAlignment(Qt.AlignCenter) # 중앙 정렬
        self.time_label.setFont(QFont('Arial', 40)) # 폰트 및 크기 설정
        self.time_label.setStyleSheet("color: white; background-color: rgba(0,0,0,150); padding: 0px;") 
        # 수직 방향으로 확장 가능하도록 설정 (Vertical, Expanding)
        self.time_label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        main_layout.addWidget(self.time_label)

        # 버튼들을 위한 수평 레이아웃
        button_layout = QHBoxLayout()
        # 버튼 레이아웃은 수직으로 고정 (Fixed) 또는 선호(Preferred)로 설정하여
        # 남은 공간을 주식 정보와 시계가 나눠 갖도록 함
        button_layout.setSizeConstraint(QHBoxLayout.SetFixedSize) # 버튼 레이아웃이 자체 크기를 유지하도록 설정
        main_layout.addLayout(button_layout) 

        # 풀스크린 버튼
        self.fullscreen_button = QPushButton('Full Screen', self)
        self.fullscreen_button.clicked.connect(self.toggle_fullscreen) 
        self.fullscreen_button.setStyleSheet("""
            QPushButton {
                background-color: #4CAF50;
                color: white;
                border-radius: 0px; 
                padding: 10px; 
                height: 50px; /* 버튼 높이 고정 */
            }
            QPushButton:hover {
                background-color: #45a049;
            }
        """)
        button_layout.addWidget(self.fullscreen_button)

        # 종료 버튼 추가
        self.exit_button = QPushButton('Exit', self)
        self.exit_button.clicked.connect(QApplication.instance().quit) 
        self.exit_button.setStyleSheet("""
            QPushButton {
                background-color: #f44336;
                color: white;
                border-radius: 0px; 
                padding: 10px; 
                height: 50px; /* 버튼 높이 고정 */
            }
            QPushButton:hover {
                background-color: #da190b;
            }
        """)
        button_layout.addWidget(self.exit_button)

    def update_time(self):
        current_time = QTime.currentTime()
        display_text = current_time.toString('hh:mm:ss') 
        self.time_label.setText(display_text)

    def fetch_and_process_stock_prices(self):
        temp_stock_data = []
        for ticker, (name, target_price) in self.stocks_to_monitor.items():
            try:
                stock_info = yf.Ticker(ticker).history(period='1d')
                if not stock_info.empty:
                    current_price = stock_info['Close'].iloc[-1]
                    price_diff = current_price - target_price

                    diff_color_code = "#AAAAAA" 
                    if price_diff > 0:
                        diff_text = f'+{price_diff:,.2f}'
                        diff_color_code = "#FF0000" 
                    elif price_diff < 0:
                        diff_text = f'{price_diff:,.2f}' 
                        diff_color_code = "#0000FF" 
                    else:
                        diff_text = f'0.00'
                    
                    formatted_text = (
                        f'<span style="font-size:14px; font-weight:bold;">{name}</span><br>'
                        f'<span style="font-size:12px;">현재가: {current_price:,.2f} | '
                        f'목표가: {target_price:,.2f} | '
                        f'<span style="color:{diff_color_code};">차이: {diff_text}</span></span>'
                    )
                    temp_stock_data.append((formatted_text))

                else:
                    temp_stock_data.append(f'{name}: 데이터 없음')
            except Exception as e:
                temp_stock_data.append(f'{name}: 오류 발생')
                print(f"Error fetching {ticker}: {e}")
        
        self.formatted_stock_data = temp_stock_data
        self.current_stock_index = 0
        self.display_next_stock_info() 

    def display_next_stock_info(self):
        if not self.formatted_stock_data:
            self.stock_info_label.setText("주식 정보 없음")
            self.stock_info_label.setStyleSheet("color: #AAAAAA; background-color: rgba(0,0,0,180); padding: 0px;")
            return

        text = self.formatted_stock_data[self.current_stock_index]
        self.stock_info_label.setText(text)
        
        self.current_stock_index = (self.current_stock_index + 1) % len(self.formatted_stock_data)

    def toggle_fullscreen(self):
        if not self.is_fullscreen:
            self.showFullScreen()
            # 전체 화면 시 폰트 크기 및 배경 불투명도 조절
            self.time_label.setFont(QFont('Arial', 200)) 
            self.time_label.setStyleSheet("color: white; background-color: rgba(0,0,0,220); padding: 0px;")
            
            # 전체 화면 시 주식 정보 폰트 크기 키우기 및 배경 색상 변경
            self.stock_info_label.setFont(QFont('Arial', 40)) 
            self.stock_info_label.setStyleSheet("color: #FFFFFF; background-color: rgba(0,0,0,220); padding: 0px;")
            
            # 전체 앱의 배경을 불투명 검은색으로 변경
            QApplication.instance().setStyleSheet("QWidget { background-color: rgba(0,0,0,220); }")

            self.fullscreen_button.setText('Exit Full Screen')
            self.exit_button.setVisible(False) 
            self.is_fullscreen = True
        else:
            self.showNormal()
            self.setGeometry(100, 100, 400, 400) 
            
            # 원래 폰트 크기 및 배경 불투명도 복원
            self.time_label.setFont(QFont('Arial', 40))
            self.time_label.setStyleSheet("color: white; background-color: rgba(0,0,0,150); padding: 0px;")
            
            # 주식 정보 폰트 크기 원래대로 및 배경색 복원
            self.stock_info_label.setFont(QFont('Arial', 12)) 
            self.stock_info_label.setStyleSheet("color: #FFFFFF; background-color: rgba(0,0,0,180); padding: 0px;")
            
            # 전체 앱의 배경을 원래대로 복원 (투명)
            QApplication.instance().setStyleSheet("QWidget { background-color: transparent; }")

            self.fullscreen_button.setText('Full Screen')
            self.exit_button.setVisible(True) 
            self.is_fullscreen = False
            
    # --- 마우스 드래그로 창 이동 기능 ---
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton and not self.is_fullscreen:
            self.old_pos = event.globalPos() - self.frameGeometry().topLeft()
            event.accept()

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton and not self.is_fullscreen:
            if self.old_pos is not None:
                self.move(event.globalPos() - self.old_pos)
                event.accept()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.old_pos = None
            event.accept()

    # --- 이벤트 필터: 전체화면일 때 외부 클릭 감지 ---
    def eventFilter(self, obj, event):
        if self.is_fullscreen and event.type() == QEvent.MouseButtonPress:
            if not self.rect().contains(self.mapFromGlobal(event.globalPos())):
                self.toggle_fullscreen() 
                return True 
        return super().eventFilter(obj, event) 

# 애플리케이션 실행
if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    # 애플리케이션 전체 기본 스타일 시트 (창 배경은 기본 투명)
    app.setStyleSheet("""
        QWidget {
            background-color: transparent; /* 기본 창 배경 투명 */
            color: #EEEEEE; /* 기본 글자색 밝게 */
            font-family: Arial;
        }
        QPushButton {
            font-size: 14px;
        }
    """)
    
    clock_app = MiniClockApp()
    clock_app.show()
    sys.exit(app.exec_())
반응형
반응형

[pytho] FFmpeg 설치하기 

 

 

1. Windows에 FFmpeg 설치하기 (권장 방법)

Windows에서는 패키지 관리자를 사용하거나, 수동으로 바이너리 파일을 다운로드하여 설치할 수 있습니다. 수동 설치 후 **환경 변수(PATH)**를 설정하는 것이 중요합니다.

1-1. 수동 설치 (일반적이고 권장되는 방법)

  1. FFmpeg 다운로드:
    • FFmpeg 공식 다운로드 페이지로 이동합니다.
    • "Windows builds" 섹션 아래에서 권장되는 빌드 중 하나를 선택합니다. (예: gyan.dev 또는 BtbN)
    • gyan.dev로 접속했다면, "release builds" 섹션에서 ffmpeg-release-full.7z (전체 기능 포함) 또는 ffmpeg-release-essentials.7z (필수 기능만 포함) 중 하나를 다운로드합니다. 보통 full 버전을 권장합니다.
  2. 압축 해제: 다운로드한 .7z 파일의 압축을 해제합니다. (7-Zip 같은 압축 해제 프로그램이 필요할 수 있습니다.) 압축을 해제한 폴더를 C:\ 또는 D:\와 같이 이동하거나 삭제하지 않을 안정적인 위치에 놓습니다. (예: C:\ffmpeg)
  3. 환경 변수(PATH) 설정: FFmpeg 실행 파일이 있는 bin 폴더의 경로를 시스템 PATH 환경 변수에 추가해야 합니다. 그래야 명령 프롬프트의 어느 위치에서든 ffmpeg 명령어를 사용할 수 있습니다.
    • "시작" 메뉴 검색창에 "환경 변수"를 입력하고 **"시스템 환경 변수 편집"**을 엽니다.
    • "고급" 탭에서 "환경 변수(N)..." 버튼을 클릭합니다.
    • "사용자 변수" 또는 "시스템 변수" 섹션에서 Path를 찾아 선택하고 "편집(I)..." 버튼을 클릭합니다.
    • **"새로 만들기(N)"**를 클릭하고, 압축을 해제한 FFmpeg 폴더 안의 bin 폴더 경로를 붙여넣습니다. (예: C:\ffmpeg\bin 또는 C:\Users\사용자명\Downloads\ffmpeg-xxxxx-full_build\bin)
    • 모든 창에서 **"확인"**을 클릭하여 변경 사항을 저장합니다.
  4. 설치 확인:
    • 새로운 명령 프롬프트(CMD) 또는 PowerShell 창을 엽니다. (환경 변수 변경 사항을 적용하려면 기존 창은 닫고 새로 열어야 합니다.)
    • ffmpeg -version을 입력하여 FFmpeg 버전 정보가 올바르게 출력되는지 확인합니다.

 

 

반응형
반응형

 

파일 실행에 필요한 모듈 리스트 추출 방법

 

pip install pipreqs

pipreqs . --encoding=utf-8 --force


       .: 현재 디렉토리를 스캔하라는 의미입니다.
       
       --encoding=utf-8: 파일 인코딩을 지정합니다. (한글 주석 등이 있을 경우 필요)
       
       --force: 이미 requirements.txt 파일이 존재하더라도 덮어쓰도록 합니다. (주의해서 사용)


pip install -r requirements.txt
반응형
반응형

[python] I'm Switching to Python and Actually Liking It  파이썬으로 전향중이고, 생각보다 꽤 마음에 들어요  

 

https://www.cesarsotovalero.net/blog/i-am-switching-to-python-and-actually-liking-it.html

 

I’m Switching to Python and Actually Liking It

I’ve started writing more Python code lately (because of… AI, you know). In this post, I share the tools, libraries, configs, and other integrations I use for building production-grade Python applications following a frontend-backend architecture.

www.cesarsotovalero.net

 

 

  • 최근 AI 개발의 트렌드로 인해 본격적으로 파이썬 학습 및 사용을 시작했고, 이제는 그 생태계에 큰 만족을 느끼고 있음
  • Python은 과거보다 훨씬 빠르고 현대적인 언어로 발전했고, Cython을 통한 성능 향상 등 급격한 발전을 체감함
  • uv, ruff, pytest, Pydantic 등 최신 개발 도구와 라이브러리를 본인의 워크플로우에 적극 도입하여 개발 생산성을 높이고 있음
  • 프로덕션 환경과 Jupyter 노트북/스크립트 기반 개발 간의 차이를 줄이기 위한 프로젝트 구조 및 자동화 방안도 적용
  • GitHub Actions, Docker 등을 활용해 CI/CD, 테스트, 인프라 관리를 효율적으로 구축함.

 

I’m Switching to Python and Actually Liking It 요약

왜 파이썬으로 전향했는가

  • AI 중심의 개발 환경에서는 Python이 사실상의 표준 언어로 자리잡고 있음
  • 과거에는 단순한 스크립트 작성에만 사용했지만, 최근에는 RAG, 에이전트, 생성형 AI 등의 “실전용 앱”을 만들기 위해 진지하게 사용하게 되었음
  • 그 과정에서 Python 생태계가 과거에 비해 매우 진화했다는 사실을 체감하게 되었음

Python의 강점 3가지

  1. 풍부한 라이브러리와 도구 생태계: 데이터 처리, 분석, 웹, AI에 특화
  2. Cython 등으로 인한 성능 개선: 컴파일 기반 최적화 가능
  3. 개선된 문법 가독성: __init__, __new__ 같은 레거시 문법은 감춰지고, 더 직관적인 문법 제공

주요 도구 및 설정

  • uv
    • Astral에서 제공하는 최신 파이썬 패키지 매니저 및 빌드 도구
    • 의존성 관리, 가상환경 생성, 프로젝트 초기화 등 대부분의 작업을 빠르게 처리함
    • pyproject.toml이 핵심 설정 파일로, 모든 메타데이터 및 의존성 정보가 통합됨
    • uv init, uv add, uv sync 명령어로 빠르게 프로젝트 환경 구성 가능
  • ruff
    • 초고속 파이썬 린터 및 코드 포매터
    • isort, flake8, autoflake 등을 통합한 도구
    • ruff check, ruff format 으로 린팅 및 자동 수정
    • PEP 8 코딩 스타일 가이드 기본 지원
  • ty
    • Astral이 만든 Python용 정적 타입 검사기
    • typing과 조합해 정적 분석, 초기 버그 방지에 효과적
    • 초기 개발 단계임에도 안정적으로 사용할 만한 수준임
  • pytest
    • 단위테스트 및 확장 가능한 테스트 환경을 제공하는 대표적인 파이썬 테스트 프레임워크
    • 간단한 파일 네이밍 규칙과 명령어 한 줄로 바로 통합 테스트 가능함
      • test_*.py로 테스트 구성 후 uv run pytest로 실행
    • 간결한 문법, 풍부한 플러그인 생태계
  • Pydantic
    • 데이터 검증 및 환경 설정 관리 라이브러리
    • .env 환경변수 기반 설정 로딩 및 타입 검증
    • BaseSettings 클래스를 통해 API 키나 DB URL 등을 안전하게 관리
  • MkDocs
    • 파이썬 프로젝트의 정적 웹사이트 및 문서 생성을 간편하게 지원
    • 오픈소스 프로젝트 스타일의 미려한 디자인 빠른 적용 가능
    • GitHub Pages 연동도 용이
  • FastAPI
    • 빠른 RESTful API 구축 프레임워크
    • 자동 검증 및 문서화, 빠른 성능, 쉬운 Pydantic 통합 장점
    • Starlette 및 Pydantic 기반으로 높은 타입 안정성과 성능 제공
  • Dataclasses
    • 파이썬 표준 기능으로 데이터 중심 클래스를 간편하게 정의할 수 있음
    • 특별 메소드 자동 생성으로 보일러플레이트 코드 대폭 감소

버전 관리 및 자동화

  • GitHub Actions
    • project-api와 project-ui 각각에 대해 별도 CI 파이프라인 구성
    • 다양한 OS에서 CI 파이프라인 구축에 최적화된 워크플로우 제공
    • 도커 기반 테스트 환경으로 프로덕션과 동일한 환경에서 테스트 시행 가능
  • Dependabot
    • 자동 의존성 최신화 및 보안 패치 관리를 자동화함
  • Gitleaks
    • 민감 정보(비밀번호, API 키 등) 유출 방지 도구로 git 커밋 전에 보안 검사를 수행함
  • Pre-commit Hooks
    • 커밋 전 자동 린팅, 포매팅, 보안 검사를 위한 도구임
    • ruff, gitleaks 등과 함께 사용해 코드 일관성과 품질 유지

인프라 자동화

  • Make
    • make test, make infrastructure-up 등의 명령어로 일관된 개발 워크플로우 지원
    • 프로젝트 루트와 project-api에 각각 Makefile 존재
  • Docker & Docker Compose
    • project-api, project-ui 각각을 컨테이너로 분리 실행
    • docker compose up --build -d 한 줄로 전체 앱 실행 가능
    • Dockerfile에는 uv 설치, FastAPI 앱 실행 명령어 포함

마무리

  • 위와 같이 최신 파이썬 개발 환경에서는 효율적이고 견고한 프로덕션 워크플로우를 구성할 수 있음
  • AI, 데이터, 웹 개발 등 다양한 영역에 걸쳐 파이썬 생태계의 성장과 도구 발전으로부터 많은 이점을 경험 가능
  • 모노레포 구조, 자동화 도구, 린터 및 타입 검사기, 즉각적인 테스트 환경, 문서화, 인프라 오케스트레이션까지 하나의 통합된 개발 문화를 구현할 수 있음

https://news.hada.io/topic?id=22028&utm_source=weekly&utm_medium=email&utm_campaign=202529

 

파이썬으로 전향중이고, 생각보다 꽤 마음에 들어요 | GeekNews

최근 AI 개발의 트렌드로 인해 본격적으로 파이썬 학습 및 사용을 시작했고, 이제는 그 생태계에 큰 만족을 느끼고 있음Python은 과거보다 훨씬 빠르고 현대적인 언어로 발전했고, Cython을 통한 성

news.hada.io

 

반응형
반응형

[AI] Visual Studio Code(VS Code)에서 사용할 수 있는 코드 어시스턴트인 Copilot과 Gemini를 비교

 

 

 

Visual Studio Code(VS Code)에서 사용할 수 있는 코드 어시스턴트인 Copilot과 Gemini를 비교해 드리겠습니다. 두 도구 모두 AI 기반 코드 생성 및 지원 도구이지만, 지향점과 강점에 차이가 있습니다.


VS Code용 코드 어시스턴트 비교: Copilot vs Gemini

구분 GitHub Copilot Gemini (주로 Google Cloud Code for VS Code 통합)
개발 주체 GitHub / Microsoft Google
기반 AI 모델 OpenAI Codex (GPT-3 계열) Google Gemini (멀티모달 대규모 언어 모델)
주요 기능 - 실시간 코드 완성 및 제안: 함수, 코드 블록, 테스트 코드 등
- 주석을 코드로 변환: 자연어를 코드로 자동 생성
- 반복적인 코드 작성 효율화
- 코드 생성, 완성, 수정, 디버깅 지원: 프롬프트를 통한 코드 생성 및 개선
- 코드 설명 및 해석: 코드의 작동 방식 설명
- 오류 분석 및 해결 제안: 에러 메시지에 대한 디버깅 도움
- 대화형 지원: 자연어 질의응답을 통한 문제 해결 및 학습
VS Code 통합 GitHub Copilot 확장 프로그램 (매우 긴밀하게 통합) Google Cloud Code 확장 프로그램을 통한 통합 (주로 Duet AI/Gemini 기반)
강점 - 압도적인 코드 완성 능력: 방대한 코드 데이터 학습을 통한 높은 정확도
- 직관적인 사용성: 코드 작성 중 자동 제안
- 다양한 프로그래밍 언어 지원: 폭넓은 언어 커버리지
- 상용화 및 안정성: 오랜 기간 서비스되어 안정적
- 종합적인 개발 지원: 코드 작성 외 설명, 분석, 디버깅 등 폭넓은 기능
- 대화형 인터페이스: 복잡한 질문이나 개념 설명에 강점
- Google Cloud 서비스 연동: GCP 사용자에게 유리
- 멀티모달 능력 (향후 확장 가능성): 코드 외 다양한 데이터(이미지 등)와 연동 가능성
주요 사용 대상 - 코드 작성 속도를 높이고 싶은 개발자
- 반복적인 코드, 상용구(boilerplate) 작성을 최소화하고 싶은 경우
- 다양한 언어를 다루는 개발자
- 코드 이해 및 디버깅에 도움이 필요한 개발자
- 새로운 기술 학습 및 개념 이해가 필요한 경우
- Google Cloud 환경에서 개발하는 개발자
- 대화형으로 문제 해결을 선호하는 개발자
비용 유료 (개인 월별 또는 연간 구독), 학생/오픈소스 기여자 무료 유료 (Google Cloud Duet AI/Gemini for Developers 구독 모델, 또는 특정 클라우드 서비스 사용 시 포함)
Sheets로 내보내기

어떤 것을 선택해야 할까요?

  • 코드 자동 완성 및 작성 생산성이 최우선이라면 GitHub Copilot이 현재까지는 가장 강력하고 직관적인 도구로 평가받습니다. 코드를 쓰는 '속도'를 비약적으로 높여줍니다.
  • 코드 작성뿐만 아니라 코드 이해, 디버깅, 질문/답변, 학습 등 좀 더 종합적이고 대화형의 개발 지원을 원한다면 **Gemini (Duet AI)**가 더 적합할 수 있습니다. 특히 Google Cloud 환경에서 작업한다면 시너지가 큽니다.

두 도구 모두 각각의 장점이 명확하므로, 개인의 개발 스타일과 주력하는 작업에 따라 선택하거나, 상황에 따라 필요하다면 함께 활용하는 것도 고려해 볼 수 있습니다.

 

반응형

+ Recent posts