나만의 Python 프로젝트 표준 만들기: Claude Skills로 자동화하기
· 약 5분
Python 프로젝트를 시작할 때마다 매번 같은 설정을 반복하고 있지 않나요? pyproject.toml 작성, 린터 설정, 디렉토리 구조 만들기... 이번 글에서는 2025년 기준 최신 Python 도구 스택을 정리하고, Claude Skills로 이 과정을 자동화하는 방법을 공유합니다.
왜 표준화가 필요한가?
프로젝트마다 설정이 다르면 이런 문제가 생깁니다:
- "이 프로젝트는 black 쓰고, 저 프로젝트는 ruff 쓰고..."
- "mypy 설정이 어디 있더라?"
- "테스트는 pytest? unittest?"
한 번 정해두면 모든 프로젝트에서 일관된 개발 경험을 얻을 수 있어요.
2025년 Python 도구 스택
최종 선택
| 역할 | 도구 | 이유 |
|---|---|---|
| 패키지 매니저 | uv | pip보다 10-100배 빠름, 가상환경 통합 관리 |
| Linter + Formatter | ruff | Black + isort + Flake8 통합, 압도적 속도 |
| Type Checker (CLI) | ty | Astral의 새 타입 체커, mypy 대비 10-100배 빠름 |
| Type Checker (IDE) | Pylance | VSCode에서 안정적인 LSP 경험 |
| 테스트 | pytest | 사실상 표준 |
ty에 대한 참고
ty는 Astral(ruff, uv 만든 회사)에서 2025년 12월에 공개한 새로운 타입 체커예요. 아직 Beta(v0.0.7)지만 속도가 압도적입니다:
mypy: 18초
ty: 0.5초
다만 아직 Beta라서 IDE는 Pylance를 유지하고, ty는 CLI/CI용으로만 사용하는 게 안전해요.
pyproject.toml 템플릿
모든 설정을 한 파일에 모아둡니다:
[project]
name = "my-project"
version = "0.1.0"
description = "프로젝트 설명"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
[dependency-groups]
dev = [
"ruff>=0.14",
"ty>=0.0.7",
"pytest>=8.0",
"pytest-cov>=6.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# ============================================
# Ruff 설정
# ============================================
[tool.ruff]
line-length = 88
target-version = "py311"
src = ["src", "tests"]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # Pyflakes
"B", # flake8-bugbear
"I", # isort
"UP", # pyupgrade
"SIM", # flake8-simplify
"ASYNC", # flake8-async
"RUF", # Ruff-specific
]
ignore = [
"E501", # line too long (formatter handles)
"B008", # function call in default argument
]
[tool.ruff.lint.isort]
known-first-party = ["my_project"]
[tool.ruff.format]
quote-style = "double"
docstring-code-format = true
# ============================================
# ty 설정 (타입 체커)
# ============================================
[tool.ty]
# requires-python을 자동 감지
# ============================================
# pytest 설정
# ============================================
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-v --tb=short"
프로젝트 구조
src 레이아웃을 사용합니다:
my-project/
├── pyproject.toml
├── README.md
├── src/
│ └── my_project/
│ ├── __init__.py
│ └── main.py
└── tests/
├── __init__.py
└── test_main.py
왜 src 레이아웃인가?
- 설치된 패키지와 로컬 코드 혼동 방지
- import 경로가 명확
- 패키징 시 실수 방지
코드 철학
프로젝트 세팅만큼 중요한 건 코드 작성 원칙이에요. 제가 따르는 5가지 원칙입니다:
1. Explicit over Clever
# ❌ 너무 clever
result = [x for x in data if x and hasattr(x, 'value') and x.value > 0]
# ✅ 명시적
def is_valid_item(item: Item | None) -> bool:
if item is None:
return False
return item.value > 0
result = [x for x in data if is_valid_item(x)]
2. Type Hints 필수
# ❌ 타입 없음
def process(data):
return data.transform()
# ✅ 타입 명시
def process(data: DataFrame) -> DataFrame:
return data.transform()
3. 함수 크기: 20-50줄 목표
- 100줄 넘으면 리팩토링
- 한 함수 = 한 가지 일
4. 네이밍 (PEP 8)
# 변수/함수: snake_case
user_count = 10
def calculate_total(): ...
# 클래스: PascalCase
class DataProcessor: ...
# 상수: SCREAMING_SNAKE_CASE
MAX_RETRIES = 3
# Boolean: is_, has_, can_ 접두사
is_active = True
has_permission = False
