11P by GN⁺ 2일전 | ★ favorite | 댓글 6개
  • 최근 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__ 같은 레거시 문법은 감춰지고, 더 직관적인 문법 제공

프로젝트 구조 (Monorepo 기반)

  • 백엔드와 프론트엔드를 통합하는 모노레포 구조를 선호함
    • 코드 관리 효율성, 검색 용이성, 단순화된 배포 및 테스트 파이프라인 등을 이유로 단일 저장소를 선택함
    • 과도하게 프로젝트를 여러 저장소로 분리하는 것은 오버 엔지니어링의 신호라고 판단함
  • 전형적인 프로젝트 구조 예시는 다음과 같음
    project/  
    ├── .github/ : GitHub Actions 등 CI/CD 워크플로우  
    ├── .vscode/ : VSCode 환경 설정  
    ├── docs/ : MkDocs 기반 정적 문서 및 사이트  
    ├── project-api/ : FastAPI 백엔드 및 데이터/노트북/툴/소스코드/테스트 포함  
    ├── project-ui/  : React/Next.js 프론트엔드  
    ├── docker-compose.yml (통합 실행)  
    └── Makefile 등 자동화 스크립트  
    
  • API 서버에서 처리된 데이터를 프론트엔드가 HTTP 요청으로 가져오는 방식으로 책임 분리
    • 프론트엔드는 무거운 데이터 처리를 금지하고 파이썬 기반 백엔드 API에 HTTP 요청을 위임함
  • 각 파이썬 모듈 디렉터리는 __init__.py로 명확히 지정함
  • project-api 내부에는 src/app, notebooks, tools, tests 폴더를 분리해 구성

주요 도구 및 설정

  • 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-apiproject-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, 데이터, 웹 개발 등 다양한 영역에 걸쳐 파이썬 생태계의 성장과 도구 발전으로부터 많은 이점을 경험 가능
  • 모노레포 구조, 자동화 도구, 린터 및 타입 검사기, 즉각적인 테스트 환경, 문서화, 인프라 오케스트레이션까지 하나의 통합된 개발 문화를 구현할 수 있음

파이썬은 라이브러리와 프레임웍이 풍부한 반면 패키지 버전관리가 잘 안되고 충돌이 잦은게 단점.
과거의 자바와 장단점의 경향이 비슷함

본문에도 나온 uv가 진짜 물건이에요. 빠른 것도 빠르고 버전이나 의존성 관리도 npm맹키로 잘 해줘서 uv 정착 중입니다.

그래도 요즘에는 uv, poetry를 통해서 버전관리와 충돌은 대부분 해소된것 같더라고요

React와 이런 부분들까지 생태계를 포괄하기에도 적절한가요?

React와 직접적으로 연동은 언어가 다르기에 어려운 부분도 있지만, 어떤것을 원하시는지에 따라 가능한 부분도 있을것 같아요.
개인적으로는 python을 통한 프론트엔드 개발은 크게 활성화되지 않은 부분이라 생각합니다.

Hacker News 의견
  • 코드에서 환경변수 누락 시 “YOUTUBE_API_KEY 또는 YOUTUBE_CHANNEL_ID가 없습니다”라고 OR로 메시지를 띄우는 방식은 굳이 OR를 쓸 필요 없는 상황에서 사용자를 괴롭히는 것임. 각각의 값을 개별적으로 체크해 어떤 것이 빠졌는지 명확히 알려주는 것이 훨씬 좋은 사용자 경험임. 개발 시간 차이도 거의 없다는 점에서 이렇게 하는 걸 추천함

    • 작은 부분까지 집요하게 파고드는 이야기지만, 이런 케이스는 := 연산자(월러스 연산자)를 쓰기에 딱 알맞다고 생각함. 예시로, if not (API_KEY := os.getenv("API_KEY")): 처럼 바로 쓸 수 있음. 개인적으로 내부 도구에서는 os.environ["API_KEY"]에서 KeyError를 그냥 터뜨리게 둠. 이 역시 충분히 명확하다고 생각함

    • 더 나아가서, 조건을 하나씩 검사해 하나라도 빠진 게 있으면 전부 알려주는 편이 훨씬 낫다고 생각함. 한 변수 누락 때문에 프로그램을 돌리고, 그 다음에 또 다른 변수 에러를 보는 불편함을 줄일 수 있음. 상황에 따라 어쩔 수 없이 번거로울 때도 있지만, 가능한 한 한 번에 보여주는 게 좋음

    • 환경변수들을 전부 가져오고, 그 중 빠진 것들을 한 번에 리포트해 주는 방법이 가장 좋음

    • boolean 플래그를 활용해서 마지막에 한 번만 exit(1) 해버리는 방법도 있음. 이렇게 하면 누락된 환경변수를 한 번에 모두 보여줄 수 있음

    • exit("Missing ...")처럼 메시지를 바로 출력하면서 코드 1로 종료할 수도 있음

  • 프로젝트 구조를 자동으로 만들어주는 도구를 찾고 있다면 cookiecutter를 추천함. 내가 자주 쓰는 몇 가지 템플릿이 있는데, python-lib, click-app, datasette-plugin, llm-plugin 등이 있음. 다음처럼 사용하면 됨: uvx cookiecutter gh:simonw/python-lib

    • Ruby로 baker라는 걸 만들었음. baker는 템플릿 repo를 복사하지 않고, 해야 할 작업리스트(명령형 단계 목록)를 만들고, 수동 작업(API key를 받아와 설정하기)과 자동 작업('uv init' 등)을 섞을 수 있음. Markdown 문법에 루비 스트링 인터폴레이션, bash도 쓸 수 있음. yml 베이스 config에 아주 지쳤기 때문에 만들게 된 것임

    • 요즘 뜨는 건 Copier라는 도구임. 자세한 건 copier 문서 참고

    • 신규 프로젝트 세팅하는 걸 오히려 즐기는 편임. 이런 걸 굳이 자동화하고 싶지 않음

    • 이런 구조화 자동화 툴은 사실 요즘 에이전트 기반 LLM 개발 워크플로에도 딱 어울리는 영역이라고 생각함

  • "파이썬이 유닉스 대부분에 기본 탑재라서 더 인간 친화적"이라는 평가는 다소 낙관적인 해석임. "import json" 이상만 넘어가면 금방 virtualenv 지옥에 빠지게 됨. Python 3.13.x 환경에서 Ubuntu 22.04나 24.04, Rocky 9 등에서 돌리려면 결국 venv, 컨테이너, 버전매니저는 필수가 됨

    • “import json” 같은 기본 라이브러리조차, 포함되지 않은 언어라면 따로 설치해야 하지만, 파이썬은 표준라이브러리 덕분에 초반 생산성이 높음. 물론 대형 프로젝트에서 표준라이브러리만으론 부족하지만, 실제로 표준라이브러리로만 여러 실전 코드들을 배포했고 배포, 보안 관리 이슈가 생기지 않음. venv 관리도 예전만큼 어렵지 않으며, 패키지 매니저도 발전했음

    • 내 농담삼아 주장하는 이론 중 하나는, Docker/컨테이너가 이렇게 빨리 확산된 이유의 절반은 파이썬 의존성 지옥을 극복하게 해줬기 때문임. 내 첫 파이썬 경험은 2012년 서버에 파이썬 서비스 설치였는데, 의존성 지옥, venv 명령어, 다루기 힘든 환경 세팅, 정말 끔찍했음. pip, brew, macOS 환경에서도 삽질만 반복했고, 파이썬만 보면 바로 피했음. 하지만 최근 uv 덕분에 초보자 입장에서도 파이썬이 한결 나아졌다고 느낌. uv init, uv add, uv run 만으로도 충분함

    • virtualenv는 늘 써야 한다고 생각함. 결국 하나의 디렉토리일 뿐이고, 이제 pip로 시스템 전체에 설치하려 하면 경고도 뜨는 등, 예전만큼 어렵지 않음

    • virtualenv나 container를 꼭 쓰는 게 좋음. 다루기 어렵게 느껴져도, 업데이트나 라이브러리 버전 업 때문에 시스템 전체에 영향 주는 일을 피할 수 있음

    • 예전엔 시스템에 Python2만 기본 포함된 경우가 많았고, 시스템 자체가 이 Python2에 의존할 때도 있어서 오히려 위험했음

  • 파이썬이 동시에 장황하면서도 부족하다고 느껴짐. 뭔가 간단한 거 하려면 500개씩 의존성을 넣거나, 아니면 아주 사소한 일에도 수십부터 많게는 수백 줄까지 코드가 늘어나게 됨. 그래서 파이썬은 불필요한 삽질이 너무 많아 피하게 됨. Perl로 훨씬 빠르고 간결하게 마무리할 수 있어서 Perl을 선호함. 파이썬은 무언가 일 자체보단 프로그래밍을 위한 프로그래밍 같아짐

    • 난 의존성 없는 프로젝트도 많이 만듦. 표준라이브러리와 단일 파일로도 진짜 많은 걸 할 수 있음. Python만 깔려 있다면 curl로 바로 내려서 돌릴 수 있음. 예로 2000줄짜리 돈 관리 CLI 툴이 있는데, plutus는 12개 정도 표준 모듈만 씀. 코드 중 25% 가량이 argparse로 커맨드 파싱하는 부분임. 파라미터별로 라인 하나씩 두는 식으로, 명확하게 쓰는 걸 좋아함

    • Perl이 Python보다 빠르고 강력하다고 했는데, 구체적으로 어떤 예시가 있는지 궁금함

    • 파이썬은 데이터구조 중첩할 때 머리 안 쓰고 바로 쓸 수 있다는 점이 편함. 리스트 안 튜플, 딕셔너리 등 자유롭게 섞을 수 있고 통일된 문법으로 접근 가능함. Perl은 분명 더 똑똑하고 재미있긴 한데, 그래서 오히려 머릿속이 꼬이기 쉬워 내게는 별로임. Python은 심심하긴 한데 5년 뒤 봐도 이해할 수 있게끔 명확성이 상당히 큼

    • 파이썬은 표준라이브러리로도 충분히 쓸 만하다고 생각함

  • 나는 모노레포 구조 선호자지만, 예전에 다녔던 회사에서는 이 방식 때문에 초대형 비대한 구조가 되어 다른 팀 코드를 잘못 건드릴까봐 아무도 손대지 않게 된 경우가 있었음. 이슈의 핵심은 레포 자체가 아니라, requirements.txt를 레포 전체 하나로 관리하거나 빌드 스크립트가 꼬인 탓이 큼. 이론상 한 번만 의존성 업데이트하면 모든 코드가 최신 패치로 안전해져야 하는데, 현실에서 이를 누구도 건들지 못했음. 모노레포는 조직이 매우 NIH(Google처럼 직접 모든 걸 만드는 성향)일 때만 잘 굴러감. 이런 경험 덕에, 각 서비스가 조직의 팀 구조와 일치하는 마이크로서비스 구조를 오히려 높게 보기 시작함. Conway's law도 참조해볼 만함

  • 파이썬은 내가 쓴 의사코드에 가장 근접하게 동작하는 언어임. 머릿속에서 명확하다고 넘어가는 부분마다 실제로도 파이썬이 직관적인 추상화를 제공해줌. 수학 기반 백그라운드에서 왔기에 참 만족스럽게 다가왔음. 물론 지금은 다른 언어들도 좋아하지만 여전히 매력이 있음

    • 수학적 사고를 하는 사람 입장에서는 OOP 쪽이 오히려 사고를 어렵게 만듦. 등가적 추론, 더 좋은 람다, 부작용 회피, 데이터 불변 등이 중요함. OOP는 내가 접한 패러다임 중 수학과 가장 거리가 멀게 느껴짐
  • 거의 똑같은 패턴으로 프로젝트 구성을 만들고 있음. 너무 비슷해서 소름끼칠 정도임. Python 개발자 생태계가 점점 비슷한 스타일로 수렴하는 게 아닌가 생각함. 예전엔 내 선택이 독특한 줄 알았는데, 이렇게 다들 같은 방식이면 내 자유의지는 어디 갔나 싶음. 흔한 아기 이름 짓는 현상과 비슷하게, 독특하다고 생각한 선택이 사실은 인기 #2였던 느낌임

    • 이런 구조는 10년 전부터 파이썬에서 인기가 있었음. 결국 여러 합리적인 엔지니어가 고민 끝에 이 패턴에 자연스럽게 모이는 것 같음

    • 사람의 에고가 마치 파일럿파 양자파처럼 모든 스펙트럼에 깔려 있고, 거기서 존재로 변화한다는 느낌이 듦. becoming-being, 웃음이 절로 남

  • 다른 사람도 파이썬을 좋아하게 된 걸 보면 반갑게 느껴짐. 나는 원래 Ruby를 선호했지만 고객의 요구로 파이썬을 어쩔 수 없이 쓰게 됐음. 예전에는 Ruby가 많이 느렸으나, 억지로 파이썬을 익히면서 점점 익숙해졌고, 지금은 나름 즐기고 있음. Make 사용법에 대해선 다소 이견이 있는데, 의존성을 전혀 쓰지 않는다면, 케이스 문 들어간 스크립트랑 다를 게 없음... 농담 반 섞어서 말하지만, 요즘 세대는 Make에 익숙하지 않은 걸 보면 씁쓸함. 나 때는 말이야, 라는 심정임

    • Ruby는 문법이 훨씬 예쁨. 들여쓰기만으로 스코프를 구분하는 파이썬은 내 스타일이 아님

    • 처음엔 케이스 문으로 된 스크립트로 시작했다가, 결국 flat한 Makefile로 진화했음. Makefile이 더 표준적이고 무작위 스크립트보다 알아보기 쉬움

  • Dataclass와 Pydantic Basemodel 중 어떤 걸 써야 할지 궁금함. Pydantic을 이미 쓴다면 그냥 다 Pydantic으로 통일해도 되지 않을까 싶은데, 굳이 Dataclass를 쓸 이유가 있을지 고민임

    • attrs 프로젝트에서 매우 잘 정리해둔 비교글이 있음. attrs 공식 비교가 있는데, 물론 약간의 편향은 있겠지만 논리적 근거는 충분하다고 생각함. 또 이 블로그도 도움이 됨

    • Dataclass는 nested object 검증을 지원하지 않음. 그래서 단순하게 함수 인자 전달용 flat 구조에는 dataclass를 쓰는 게 나음. 너무 많은 인자를 리스트로 받는 것보다 명확함

    • 생성 시 데이터 검증 때문에 성능 저하 이슈가 있음. msgspec처럼 훨씬 가볍고 빠른 대안도 있음

    • 굳이 검증이나 직렬화가 필요 없으면 Pydantic은 오히려 쓸데없는 오버헤드임. 내 원칙은 직렬화가 필요하면 Pydantic, 아니면 dataclass

    • TypeAdapter(MyDataclass)처럼 기존 dataclass를 바로 쓸 수 있는데, 굳이 Pydantic 모델을 따로 만들 이유가 있나 싶음

  • 최근에는 오히려 Python이 아니라 다른 언어로 이주해서 더 만족하고 있음. 내 파이썬에 대한 생각은 이 글에 정리해놨음. 다음에 다시 파이썬 쓸 기회가 온다면 uv, ruff, ty 같은 걸 꼭 써 볼 생각임

    • 나 역시 백엔드에서 Python에서 JS로 갈아타고 한참 즐기고 있음. 파이썬 설치/패키지 관리가 망가진 건 동의함. 하지만 나에겐 async가 제일 큰 생산성 향상이었음. Python에는 asyncio가 있지만, 여러 경쟁 방식이 혼재되어 표준이 안 잡혀 있음. JS는 딱 하나에 모인 점이 좋아서 훨씬 편했음. 자잘한 항목도 다 합치면 큰 차이를 만들었고, 파이썬은 들여쓰기 스코핑, 임포트에서 상대경로 문제, JS 객체 문법 등 여러 부분이 더 쾌적함. 관련 설명 참고