파이썬 패키지 설치와 import 의존¶
한 줄 요약: 한 저장소의 코드를 패키지로 묶어 두면, 다른 프로젝트가 그 패키지를 특정 버전으로 고정해 설치하고
import해서 쓴다. 이때 코드는 내 프로세스 안에서 돈다. 실행 중에 원본 서버에 물어보는 것과는 전혀 다른 연결이다.
📍 만난 상황¶
- 2026-10-27 — Gemma 실패 원인을 정리하던 중이었다. 직전에 "스키마는 실행 중에 매니저에 물어보는 게 아니라, 어시스턴트에 설치된 패키지에서 꺼낸다"는 설명을 들었다. 15:03에 "매니저가 패키지를 만든 거고, 어시스턴트가 그걸 import해서 쓰는 거냐"고 물었다. → 맞다.
pyproject.toml에 git 태그로 고정해 설치한다. 1번 물음 → 그날 일지 - 그 전에도
models.py가 두 군데(매니저 저장소, 어시스턴트.venv안)에 있어서 어느 쪽을 봐야 할지 헷갈렸다.
🧩 쉽게 말하면¶
교재 인쇄본을 떠올리자. 매니저 저장소는 저자의 원고다. 태그 20261025는 "2026년 10월 25일 판"이다. 어시스턴트는 그 판을 사서 자기 책장(site-packages)에 꽂아 둔 학생이다.
학생은 공부할 때 책장의 책을 펼친다. 저자에게 전화하지 않는다. 저자가 원고를 고쳐도 학생 책은 그대로다. 새 판을 사야(태그를 올려야) 바뀐다.
반대로 HTTP API 호출은 저자에게 직접 전화해서 묻는 것이다. 저자가 지금 무엇을 알고 있는지가 답이 된다.
📖 제대로 알기¶
용어¶
- 모듈(module): 파이썬 파일 하나. 예:
models.py. - 패키지(package): 모듈을 묶은 폴더. 예:
dhub2/cores/resourceplan/. - 배포 이름과 import 이름: 설치할 때 이름과 코드에서 부르는 이름은 다를 수 있다. 오늘은 저장소가
dhub2-manager이고, import 이름은dhub2다. - 의존성(dependency): 내 프로젝트가 돌려면 필요한 다른 패키지.
pyproject.toml: 프로젝트 정보와 의존성을 적는 표준 설정 파일.- 가상 환경(virtual environment,
.venv): 프로젝트마다 따로 둔 파이썬 실행 환경. 패키지가 섞이지 않는다. site-packages: 가상 환경 안에서 설치된 패키지가 복사되는 폴더.- 잠금 파일(lock file:
uv.lock등): 실제 설치된 정확한 버전을 기록한 파일.
의존성을 적는 방법¶
| 방식 | 예 | 특징 |
|---|---|---|
| 패키지 저장소 버전 | requests>=2.31 |
PyPI(공개 패키지 저장소)에서 받음 |
| git 주소 + 태그 | git = "...", tag = "20261025" |
그 시점 코드로 고정 |
| 로컬 경로(편집 모드) | path = "../dhub2-manager", editable = true |
원본을 고치면 바로 반영 |
연결 방식 두 가지¶
| 방식 | 어디서 실행되나 | 오늘 예 |
|---|---|---|
| 패키지 import | 내 프로세스 안 | 도구 스키마, 계획 검증 propose_resource_plan |
| HTTP API 호출 | 상대 서버 | 데이터셋 검색, 실제 리소스 생성(manager_api.py) |
⚙️ 어떻게 동작하나¶
- 매니저 저장소에 태그
20261025를 단다. 그 시점 코드를 가리키는 이름표다. - 어시스턴트
pyproject.toml에 "그 저장소의 그 태그를dhub2로 설치"라고 적는다. - 설치 도구(uv, pip 등)가 그 시점 코드를 받아
.venv/lib/python3.14/site-packages/dhub2/에 복사한다. - 어시스턴트가
from dhub2.cores.resourceplan import ...를 실행하면, 파이썬은site-packages의 복사본을 읽는다. - 그 코드는 어시스턴트 프로세스 안에서 돈다. 그래서 오늘 422의 검증 오류도 매니저 서버가 아니라 어시스턴트 안의 매니저 공용 코어가 냈다.
flowchart LR
R["매니저 저장소"] -->|"① 태그 20261025"| T["고정된 코드"]
T -->|"② 설치·복사"| SP["어시스턴트 .venv<br/>site-packages"]
SP -->|"③ import"| A["어시스턴트 프로세스"]
A -->|"HTTP 호출"| MS["매니저 서버"]
①~③은 설치 시점의 연결이고, 아래 HTTP 호출은 실행 시점의 연결이다. 스키마와 검증은 ③을 통해 들어왔다.
그래서 매니저를 고치면¶
매니저 PR → 새 태그 → 어시스턴트의 태그를 올리는 PR(bump) 순서가 필요하다. 최근 커밋 chore(deps): bump dhub2 to 20261025 (#144)가 그런 작업이다.
🧪 예시¶
-
예시 1 · 일상에 빗대어: 학생 3명이 같은 교재 10월 25일 판을 쓴다. 저자가 11월에 오타 2곳을 고친다. 학생 3명의 책은 여전히 오타가 있다. 담임이 "11월 판으로 바꾸자"고 공지해야(bump PR) 바뀐다. 대신 저자가 실수로 이상한 내용을 넣어도, 학생들은 판을 바꾸기 전까지 영향을 받지 않는다.
-
예시 2 · 실제로는: 오늘 본 연결 고리다.
# dhub2-assistant/pyproject.toml (51줄) dhub2 = { git = "https://github.com/dtonic/dhub2-manager.git", tag = "20261025" }①# dhub2-assistant/src/dhub2_assistant/tools.py (31~36줄) from dhub2.cores.resourceplan import ( ResourcePlanApplyArgs, # apply 도구 양식 ResourcePlanProposeArgs, # propose 도구 양식 (payload가 여기) apply_resource_plan, # 실제 생성 로직 propose_resource_plan, # 계획 검증 로직 )pyproject.toml의 줄은 uv나 Poetry 같은 도구가 읽는 git 의존성 표기다. ②import는 설치된 복사본을 읽는다. ③ 그래서 매니저models.py538줄의payload정의가 어시스턴트 안으로 들어와 Gemma에게 전달된다.
실제로 어느 파일을 읽는지는 이렇게 확인한다.
python -c "import dhub2, sys; print(dhub2.__file__)"
# .venv/lib/python3.14/site-packages/dhub2/__init__.py 같은 경로가 나온다
⚖️ 비교 · 흔한 오해¶
| 오해 | 실제 |
|---|---|
| 어시스턴트가 실행 중에 매니저에 타입을 물어본다 | 설치된 복사본에서 import한다 |
| 매니저 main을 고치면 어시스턴트도 바뀐다 | 태그를 올리기 전엔 안 바뀐다 |
매니저 저장소 models.py를 고치면 어시스턴트가 그걸 쓴다 |
어시스턴트는 .venv 안 복사본을 쓴다 |
| 422는 매니저 서버가 냈다 | 어시스턴트 안의 매니저 코어 검증이 원인이다 |
왜 그렇게 생각하기 쉬운가
- 매니저는 서버로도 돌고 있고, 어시스턴트가 그 서버에 HTTP 요청도 보낸다. 그래서 "매니저에서 가져온다"를 모두 실행 중 호출로 생각하기 쉽다.
- 같은 이름의 models.py가 두 곳에 있다. 내용이 같으면 하나처럼 느껴진다. 하지만 하나는 원본, 하나는 복사본이다.
🛠️ 실무에서는¶
- 다른 저장소의 코드를 쓸 땐 먼저 확인한다. import로 쓰나, API로 부르나? 고칠 곳과 배포 순서가 달라진다.
- 버전 고정(태그, 잠금 파일)은 재현성을 준다. 대신 원본 수정이 늦게 반영된다.
- 원본과 같이 고치며 시험할 땐 편집 모드 설치(
pip install -e, uv의editable = true)를 쓴다. 단 커밋에 섞이지 않게 조심한다. - 의존 패키지에서 가져온 것을 내 쪽에서 덧씌우는 방법도 있다. 오늘 "어시스턴트에서 import한 양식에 힌트를 덧붙이기"가 그 예다. 패키지를 건드리지 않아 bump가 필요 없다.
- 문제가 생기면 먼저 볼 것:
pyproject.toml의 버전·태그 → 잠금 파일 → 실제 import 경로(__file__).
❓ 자주 묻는 질문¶
- Q.
.venv안의 파일을 직접 고치면 안 되나? A. 시험용으로만 가능하다. 다시 설치하면 사라지고, 다른 사람 환경에는 반영되지 않는다. - Q. 태그 말고 브랜치를 걸면? A. 설치할 때마다 내용이 달라질 수 있다. 재현성이 떨어져서 보통 태그나 커밋을 건다.
- Q. 매니저 패키지를 안 고치고 어시스턴트만 고치면 손해는? A. 같은 패키지를 쓰는 다른 프로젝트(dhub2-agent 등)는 혜택을 못 받는다. 고칠 곳이 여러 군데로 퍼질 수 있다.
🔭 더 깊이 보기¶
- 잠금 파일이 정확히 무엇을 기록하나 — 같은
pyproject.toml로 다른 버전이 설치되는 일을 막는 원리라서. - 시맨틱 버전(1.2.3)과 날짜 태그의 차이 — bump할 때 위험도를 판단하는 기준이라서.
- 관련 주제: LLM 도구 호출(function calling) 흐름, pydantic 검증과 Field 설정
📚 참고 자료¶
- 가상 환경 및 패키지 (파이썬 공식 문서 한국어) —
.venv와 패키지 설치의 기본 · 링크 - 모듈 (파이썬 공식 문서 한국어) — 모듈·패키지와
import가 파일을 찾는 방식 · 링크 - VCS Support (pip 공식 문서, 영문) — git 주소와 태그로 설치하는 방법 · 링크
🗓️ 이력¶
- 2026-10-27: 매니저가 만든 패키지를 어시스턴트가 import하는지 1번 물었다 → 일지