MacBook M1을 사서 AI 프로젝트를 시작하려고 했는데, Python 설치부터 막혔다. 시스템 Python은 건드리면 안 된다고 하고, Homebrew로 설치한 Python은 버전 관리가 안 되고, conda는 왜 그렇게 느린지 모르겠고. PyTorch를 설치했더니 CPU 모드로만 돌아가서 M1 칩을 산 의미가 없어지고.
결국 한 주 정도 삽질한 끝에 pyenv + venv + Metal 가속이라는 조합에 정착했다. M1 32GB RAM 기준으로 LLM 파인튜닝부터 Stable Diffusion 로컬 실행까지, 이 세팅으로 대부분의 AI 작업을 문제없이 돌리고 있다. 이 글에서는 그 과정을 처음부터 끝까지 정리한다. 삽질 기록 포함.
📑 목차
왜 시스템 Python을 쓰면 안 되는가

macOS에는 기본으로 Python이 포함되어 있다. Sonoma 기준으로 /usr/bin/python3 경로에 Python 3.9가 깔려 있다. “이거 그냥 쓰면 안 되나?”라고 생각할 수 있는데, 결론부터 말하면 절대 쓰면 안 된다. 관련 내용은 Mac Ollama 로컬 LLM 가이드에서도 다루고 있다.
시스템 Python은 macOS 내부 도구들이 의존하는 것이라서, 여기에 패키지를 설치하거나 버전을 바꾸면 OS 기능이 망가질 수 있다. 실제로 pip install을 시도하면 이런 에러가 뜬다:
$ /usr/bin/python3 --version
Python 3.9.6
$ /usr/bin/pip3 install numpy
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try brew install
xyz, where xyz is the package you are trying to install.
If you wish to install a non-brew-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip.
note: If you believe this is a mistake, please contact your Python
installation or OS distribution provider.
Python 3.12부터 도입된 PEP 668(externally-managed-environment) 때문에, 시스템 Python에 직접 패키지를 설치하는 것이 원천 차단됐다. 이건 macOS만의 제한이 아니라 Python 생태계 전체의 방향이다. 이래저래 시스템 Python은 건드리지 않는 게 맞다.
Homebrew로 pyenv 설치

pyenv는 여러 Python 버전을 프로젝트별로 독립 관리할 수 있게 해주는 도구다. Node.js 진영의 nvm과 동일한 역할이다. Homebrew가 이미 설치되어 있다는 전제 하에 진행한다.
# Homebrew 업데이트 먼저
$ brew update
# pyenv 설치
$ brew install pyenv
# 설치 확인
$ pyenv --version
pyenv 2.4.22
# 쉘 설정 (zsh 기준 — Mac 기본 쉘)
# ~/.zshrc에 아래 내용 추가
$ cat >> ~/.zshrc << 'EOF'
# pyenv 설정
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
EOF
# 설정 반영
$ source ~/.zshrc
# pyenv가 정상적으로 쉘에 연결됐는지 확인
$ pyenv versions
* system (set by /Users/dev/.pyenv/version)
# 빌드 의존성도 함께 설치 (Python 소스 컴파일에 필요)
$ brew install openssl readline sqlite3 xz zlib tcl-tk
# Xcode Command Line Tools도 필요
$ xcode-select --install
# 이미 설치되어 있으면 "already installed" 메시지가 뜸
주의할 점: eval "$(pyenv init -)"는 반드시 ~/.zshrc에 넣어야 한다. ~/.zprofile에 넣으면 새 터미널 탭을 열 때 pyenv가 작동하지 않는다. 나도 이것 때문에 30분 삽질했다. 터미널을 완전히 닫았다 열면 되는데 탭만 추가하면 안 되는, 그런 짜증나는 상황이 발생한다.
pyenv로 Python 3.12 설치 (ARM 네이티브 확인)
2026년 4월 기준으로, AI 개발에 가장 안정적인 버전은 Python 3.12다. 3.13도 나와 있지만 일부 AI 라이브러리(특히 PyTorch 관련)의 호환성이 아직 완벽하지 않는다. 3.11은 잘 돌아가지만 성능 최적화 측면에서 3.12가 우위다.
# 설치 가능한 Python 3.12 버전 확인
$ pyenv install --list | grep "3.12"
3.12.0
3.12.1
3.12.2
3.12.3
3.12.4
3.12.5
3.12.6
3.12.7
3.12.8
3.12.9
# 최신 안정 버전 설치 (2026년 4월 기준)
$ pyenv install 3.12.9
Downloading Python-3.12.9.tar.xz...
-> https://www.python.org/ftp/python/3.12.9/Python-3.12.9.tar.xz
Installing Python-3.12.9...
Installed Python-3.12.9 to /Users/dev/.pyenv/versions/3.12.9
# 글로벌 기본 버전으로 설정
$ pyenv global 3.12.9
# 설정 확인
$ python --version
Python 3.12.9
# 경로 확인 — ARM 네이티브로 설치됐는지 반드시 확인
$ which python
/Users/dev/.pyenv/shims/python
$ python -c "import platform; print(platform.machine())"
arm64
# ⚠️ 만약 여기서 x86_64가 출력되면 Rosetta로 설치된 것
# 이 경우 터미널이 Rosetta로 실행되고 있는지 확인해야 함
$ file $(pyenv which python)
/Users/dev/.pyenv/versions/3.12.9/bin/python3.12: Mach-O 64-bit executable arm64
# arm64가 표시되면 정상. x86_64가 표시되면 아래 해결법 참고
ARM 네이티브 확인이 중요한 이유는, Rosetta 2로 빌드된 Python은 M1의 Neural Engine이나 Metal 가속을 제대로 활용하지 못하기 때문이다. 나중에 PyTorch MPS 백엔드를 쓸 때 문제가 된다.
Rosetta로 설치되는 경우 해결법
터미널 앱 자체가 Rosetta로 실행되고 있으면, pyenv도 x86_64 바이너리를 빌드한다. 이걸 확인하고 수정하는 방법:
# 현재 터미널의 아키텍처 확인
$ arch
arm64 # 이게 나와야 정상
# 만약 i386 또는 x86_64가 나오면:
# 1. 터미널(또는 iTerm2) 앱의 "정보 가져오기"에서
# "Rosetta를 사용하여 열기" 체크를 해제
# 2. 터미널 완전히 종료 후 재실행
# 3. 이미 설치된 Python을 삭제하고 재설치
$ pyenv uninstall 3.12.9
$ pyenv install 3.12.9
# 재확인
$ python -c "import platform; print(platform.machine())"
arm64
venv 가상환경 생성 및 관리
pyenv로 Python 버전 관리를 해결했으면, 프로젝트별 패키지 격리는 venv로 처리한다. Python 3.3부터 표준 라이브러리에 포함된 모듈이라 별도 설치가 필요 없다.
# 프로젝트 디렉터리 생성
$ mkdir ~/projects/my-ai-project && cd ~/projects/my-ai-project
# 이 프로젝트에서 사용할 Python 버전 지정 (pyenv local)
$ pyenv local 3.12.9
# .python-version 파일이 생성됨
$ cat .python-version
3.12.9
# 가상환경 생성
$ python -m venv .venv
# 가상환경 활성화
$ source .venv/bin/activate
# 활성화 확인 — 프롬프트 앞에 (.venv)가 붙음
(.venv) $ which python
/Users/dev/projects/my-ai-project/.venv/bin/python
(.venv) $ python --version
Python 3.12.9
# pip 업그레이드 (가상환경 안에서)
(.venv) $ pip install --upgrade pip
Successfully installed pip-24.3.1
# 가상환경 비활성화
(.venv) $ deactivate
$
venv의 핵심은 프로젝트마다 완전히 독립된 Python 환경을 만든다는 것이다. A 프로젝트에서 PyTorch 2.5를 쓰고 B 프로젝트에서 PyTorch 2.2를 써도 서로 충돌하지 않는다.
실전 관리 팁
가상환경 디렉터리 이름을 .venv로 통일하는 걸 추천한다. VSCode가 자동으로 인식하고, .gitignore에 한 줄만 추가하면 되니까 관리가 편하다.
# .gitignore에 추가
$ echo ".venv/" >> .gitignore
# VSCode에서 자동 인식시키려면 settings.json에 추가
# (보통 자동으로 감지하지만 안 될 때)
{
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python"
}
# 터미널을 열 때마다 activate하기 귀찮다면
# ~/.zshrc에 자동 활성화 함수를 추가할 수도 있다
auto_activate_venv() {
if [[ -f ".venv/bin/activate" ]]; then
source .venv/bin/activate
fi
}
# 단, 이건 취향 차이가 크다. 나는 명시적으로 activate하는 편을 선호한다.
pip install 시 M1 호환 이슈
M1이 나온 지 5년이 지났지만, 아직도 일부 패키지에서 ARM 호환 이슈가 발생한다. 특히 C 확장 모듈을 포함한 과학 계산 라이브러리들이 문제다.
numpy, scipy 설치 문제
2026년 기준으로 numpy와 scipy는 ARM64 wheel을 공식 제공하고 있어서 대부분 문제없이 설치된다. 하지만 특정 이전 버전을 지정 설치할 때 문제가 생긴다.
# 최신 버전은 문제없이 설치됨
(.venv) $ pip install numpy scipy
Successfully installed numpy-2.2.2 scipy-1.15.1
# 하지만 이전 버전을 지정하면 에러가 발생할 수 있음
(.venv) $ pip install numpy==1.23.0
ERROR: Could not find a version that satisfies the requirement numpy==1.23.0
ERROR: No matching distribution found for numpy==1.23.0
# numpy 1.23은 ARM64 wheel이 제공되지 않는 오래된 버전
# 이 경우 소스에서 빌드를 시도하면:
(.venv) $ pip install numpy==1.23.0 --no-binary :all:
# ... 한참 컴파일 후 ...
RuntimeError: Cannot compile 'Python.h'. Perhaps you need to install python-dev|python-devel.
# 해결법: openblas를 Homebrew로 설치한 뒤 환경변수 지정
$ brew install openblas
(.venv) $ OPENBLAS="$(brew --prefix openblas)" pip install numpy==1.23.0 --no-binary :all:
자주 문제가 되는 패키지 목록
| 패키지 | 상태 | 해결법 |
|---|---|---|
| numpy (최신) | 문제없음 | pip install numpy |
| scipy (최신) | 문제없음 | pip install scipy |
| h5py | HDF5 필요 | brew install hdf5 후 설치 |
| grpcio | 간헐적 빌드 실패 | GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1 설정 |
| tokenizers | Rust 빌드 필요 | brew install rust 후 설치 |
| llama-cpp-python | Metal 플래그 필요 | CMAKE_ARGS="-DGGML_METAL=on" pip install |
원칙은 간단하다. 최신 버전을 쓰면 대부분 ARM64 wheel이 제공된다. 문제가 생기는 건 거의 레거시 버전을 지정 설치하거나, C/Rust 네이티브 코드를 포함한 패키지를 소스에서 빌드할 때다.
PyTorch MPS (Metal Performance Shaders) 가속 설정
M1 Mac에서 AI 개발을 하는 가장 큰 이유 중 하나가 MPS(Metal Performance Shaders) 가속이다. NVIDIA GPU가 없어도, M1의 GPU를 활용해서 딥러닝 학습과 추론을 가속할 수 있다. PyTorch 1.12부터 MPS 백엔드를 공식 지원하고 있고, 2.x 버전에서 상당히 안정화됐다.
# PyTorch 설치 (MPS 지원 포함)
# 공식 사이트: https://pytorch.org/get-started/locally/
(.venv) $ pip install torch torchvision torchaudio
# 2026년 4월 기준 최신 안정 버전
# torch-2.5.1 torchvision-0.20.1 torchaudio-2.5.1
# MPS 가속 확인 — 이게 핵심
(.venv) $ python -c "
import torch
print(f'PyTorch version: {torch.__version__}')
print(f'MPS available: {torch.backends.mps.is_available()}')
print(f'MPS built: {torch.backends.mps.is_built()}')
if torch.backends.mps.is_available():
device = torch.device('mps')
x = torch.randn(3, 3, device=device)
print(f'Tensor on MPS: {x.device}')
print('MPS 가속 정상 작동!')
else:
print('MPS를 사용할 수 없습니다.')
"
# 정상 출력 예시:
PyTorch version: 2.5.1
MPS available: True
MPS built: True
Tensor on MPS: mps:0
MPS 가속 정상 작동!
만약 MPS available: False가 나온다면, 다음을 확인해야 한다:
- macOS 12.3 이상이어야 한다 (MPS는 Monterey 12.3부터 지원)
- Python이 ARM64 네이티브인지 확인 (위에서 다룬 Rosetta 이슈)
- PyTorch가 올바른 버전인지 확인 (1.12 미만이면 MPS 미지원)
MPS 실전 사용법 — CPU vs MPS 성능 비교
실제로 모델을 MPS에서 돌려보면 CPU 대비 확실한 차이를 체감할 수 있다. 간단한 벤치마크:
import torch
import time
def benchmark(device_name, size=4096, iterations=100):
device = torch.device(device_name)
a = torch.randn(size, size, device=device)
b = torch.randn(size, size, device=device)
# Warm-up
for _ in range(10):
c = torch.mm(a, b)
if device_name == 'mps':
torch.mps.synchronize()
start = time.time()
for _ in range(iterations):
c = torch.mm(a, b)
if device_name == 'mps':
torch.mps.synchronize()
elapsed = time.time() - start
print(f'{device_name}: {elapsed:.3f}s ({iterations} iterations)')
return elapsed
print('=== 행렬 곱셈 벤치마크 (4096x4096) ===')
cpu_time = benchmark('cpu')
mps_time = benchmark('mps')
print(f'\nMPS 속도 향상: {cpu_time / mps_time:.1f}x')
# MacBook M1 32GB 기준 실측 결과:
# cpu: 12.847s (100 iterations)
# mps: 2.031s (100 iterations)
# MPS 속도 향상: 6.3x
4096x4096 행렬 곱셈 기준으로 약 6배 정도 빨라진다. 모델 학습에서는 배치 크기, 모델 구조에 따라 2~8배 정도 차이가 나는데, CPU 학습이 밤새 걸리던 게 MPS로 몇 시간 만에 끝나는 수준이다.
MPS 사용 시 주의사항
MPS가 만능은 아니다. 알아두면 좋은 제한사항들:
- 일부 PyTorch 연산이 MPS에서 아직 구현되지 않았다. 이 경우
NotImplementedError가 발생한다. 대부분의 기본 연산은 지원하지만, 특수한 커스텀 연산은 CPU fallback이 필요할 수 있다. torch.mps.synchronize()를 호출하지 않으면 벤치마크 결과가 부정확하다. MPS는 비동기 실행이라 명시적 동기화가 필요하다.- Hugging Face Transformers를 사용할 때는
model.to("mps")만 하면 되지만, 일부 모델에서 NaN이 발생하는 경우가 있다. 이때는torch.float32를 명시적으로 사용하면 해결된다.
# Hugging Face 모델에서 MPS 사용 예시
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "skt/ko-gpt-trinity-1.2B-v0.5"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float32 # MPS에서 float16이 불안정할 때
)
model.to("mps")
# 추론
inputs = tokenizer("오늘 날씨가", return_tensors="pt").to("mps")
outputs = model.generate(**inputs, max_new_tokens=50)
print(tokenizer.decode(outputs[0]))
tensorflow-metal 설치 (선택)
PyTorch를 주력으로 쓴다면 이 섹션은 건너뛰어도 된다. 하지만 TensorFlow 기반 프로젝트를 다룰 일이 있다면, tensorflow-metal 플러그인으로 M1 GPU 가속을 활성화할 수 있다.
# TensorFlow와 Metal 플러그인 설치
(.venv) $ pip install tensorflow
(.venv) $ pip install tensorflow-metal
# GPU 인식 확인
(.venv) $ python -c "
import tensorflow as tf
print(f'TensorFlow version: {tf.__version__}')
gpus = tf.config.list_physical_devices('GPU')
print(f'GPU devices: {gpus}')
if gpus:
print('Metal GPU 가속 활성화!')
else:
print('GPU를 찾을 수 없습니다.')
"
# 정상 출력:
# TensorFlow version: 2.18.0
# GPU devices: [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
# Metal GPU 가속 활성화!
한 가지 알아둘 것은, tensorflow-metal의 업데이트 주기가 TensorFlow 본체보다 느리다는 점이다. TensorFlow 최신 버전과 tensorflow-metal 간 버전 호환이 안 맞아서 에러가 나는 경우가 종종 있다. 이때는 TensorFlow 버전을 한 단계 낮추면 해결되는 경우가 많다.
Jupyter Notebook/Lab 설정
AI 개발에서 Jupyter는 사실상 필수다. 데이터 탐색, 모델 프로토타이핑, 결과 시각화 등을 한 곳에서 할 수 있다.
# JupyterLab 설치 (Notebook보다 Lab을 추천)
(.venv) $ pip install jupyterlab ipykernel
# 가상환경을 Jupyter 커널로 등록
(.venv) $ python -m ipykernel install --user --name my-ai-project --display-name "My AI Project (3.12)"
Installed kernelspec my-ai-project in /Users/dev/Library/Jupyter/kernels/my-ai-project
# JupyterLab 실행
(.venv) $ jupyter lab
[I 2026-04-05 14:30:22.847 ServerApp] Jupyter Server is running at:
[I 2026-04-05 14:30:22.847 ServerApp] http://localhost:8888/lab?token=abc123...
# 등록된 커널 목록 확인
(.venv) $ jupyter kernelspec list
Available kernels:
my-ai-project /Users/dev/Library/Jupyter/kernels/my-ai-project
python3 /Users/dev/projects/my-ai-project/.venv/share/jupyter/kernels/python3
# 더 이상 쓰지 않는 커널 삭제
$ jupyter kernelspec uninstall my-ai-project
프로젝트별로 커널을 등록해두면, JupyterLab 안에서 커널을 전환하면서 다른 프로젝트의 환경을 바로 사용할 수 있다. venv와 함께 쓰면 패키지 충돌 걱정 없이 여러 프로젝트를 병행할 수 있다.
VSCode를 사용한다면 내장 Jupyter 확장으로도 충분하다. .ipynb 파일을 열면 커널 선택 UI가 나오고, .venv가 자동 감지된다.
requirements.txt와 pip freeze 관리
팀 프로젝트든 개인 프로젝트든, 패키지 버전을 고정해두지 않으면 나중에 반드시 재현 불가 문제가 생긴다. "내 컴퓨터에서는 됐는데"를 방지하려면 requirements.txt 관리가 필수다.
# 현재 설치된 모든 패키지를 requirements.txt로 저장
(.venv) $ pip freeze > requirements.txt
# requirements.txt 내용 확인
(.venv) $ cat requirements.txt
certifi==2024.12.14
charset-normalizer==3.4.1
filelock==3.16.1
fsspec==2024.12.0
Jinja2==3.1.5
jupyter_client==8.6.3
jupyterlab==4.3.4
MarkupSafe==3.0.2
mpmath==1.3.0
networkx==3.4.2
numpy==2.2.2
pillow==11.1.0
scipy==1.15.1
sympy==1.13.3
torch==2.5.1
torchaudio==2.5.1
torchvision==0.20.1
...
# 다른 환경에서 동일하게 설치
(.venv) $ pip install -r requirements.txt
# 더 나은 방법: 직접 설치한 패키지만 수동으로 관리
# requirements.txt (수동 관리 버전)
torch>=2.5.0
torchvision>=0.20.0
torchaudio>=2.5.0
numpy>=2.2.0
scipy>=1.15.0
jupyterlab>=4.3.0
transformers>=4.47.0
datasets>=3.2.0
accelerate>=1.2.0
# 개발 의존성은 별도 파일로 분리
# requirements-dev.txt
pytest>=8.0.0
black>=24.0.0
ruff>=0.8.0
ipykernel>=6.29.0
pip freeze의 출력을 그대로 쓰면 의존성의 의존성까지 모두 포함되어 버전이 과도하게 고정된다. 나는 직접 설치한 핵심 패키지만 requirements.txt에 적고, 전체 스냅샷은 requirements-lock.txt로 별도 관리하는 방식을 쓰고 있다. pip-tools나 uv 같은 도구를 쓰면 이 과정을 자동화할 수 있다.
# pip-tools를 사용한 의존성 관리 (선택)
(.venv) $ pip install pip-tools
# requirements.in (직접 설치할 패키지만)
# requirements.in:
torch>=2.5.0
transformers>=4.47.0
jupyterlab>=4.3.0
# 의존성 해결 및 lock 파일 생성
(.venv) $ pip-compile requirements.in -o requirements-lock.txt
# lock 파일 기준으로 설치
(.venv) $ pip-sync requirements-lock.txt
M1에서 자주 발생하는 에러와 해결법
지난 몇 달간 M1에서 AI 개발하면서 만난 에러들을 정리했다. 대부분 구글링해도 바로 나오지 않는 것들이라 메모해뒀다.
에러 1: "No module named '_lzma'"
# pyenv로 Python 설치 후 발생
$ python -c "import lzma"
ModuleNotFoundError: No module named '_lzma'
# 원인: xz 라이브러리가 없는 상태에서 Python이 빌드됨
# 해결:
$ brew install xz
$ pyenv uninstall 3.12.9
$ pyenv install 3.12.9
에러 2: "ERROR: Failed building wheel for grpcio"
# TensorFlow나 Google Cloud 관련 패키지 설치 시
(.venv) $ pip install grpcio
ERROR: Failed building wheel for grpcio
# 해결:
(.venv) $ GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1 \
GRPC_PYTHON_BUILD_SYSTEM_ZLIB=1 \
pip install grpcio
에러 3: "RuntimeError: Placeholder storage has not been allocated on MPS device!"
# PyTorch에서 MPS 텐서 연산 중 발생
# 원인: 모델의 일부가 CPU에, 일부가 MPS에 있을 때
# 해결: 모든 텐서와 모델이 같은 디바이스에 있는지 확인
# 잘못된 코드:
model.to("mps")
input_tensor = torch.randn(1, 3, 224, 224) # CPU에 있음
output = model(input_tensor) # 에러!
# 올바른 코드:
model.to("mps")
input_tensor = torch.randn(1, 3, 224, 224).to("mps")
output = model(input_tensor) # 정상
에러 4: "arch: posix_spawnp: ..." Rosetta 관련 에러
# 터미널에서 arch 명령어 관련 에러
$ arch -arm64 brew install python
arch: posix_spawnp: brew: Bad CPU type in executable
# 원인: Homebrew 자체가 Rosetta로 설치됨
# 해결: Homebrew를 ARM 네이티브로 재설치
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# ARM Homebrew 경로 확인
$ which brew
/opt/homebrew/bin/brew # ARM 네이티브 (정상)
# /usr/local/bin/brew # Intel (Rosetta) — 이러면 재설치 필요
에러 5: "MPS backend out of memory"
# 큰 모델을 MPS에 올릴 때 메모리 부족
# RuntimeError: MPS backend out of memory
# M1 32GB 기준으로 7B 모델이 한계선
# 해결법 1: 모델을 float16으로 로드
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16
).to("mps")
# 해결법 2: 환경변수로 MPS 메모리 제한 설정
import os
os.environ["PYTORCH_MPS_HIGH_WATERMARK_RATIO"] = "0.0"
# 0.0으로 설정하면 시스템 메모리를 최대한 활용 (스왑 발생 가능)
경험적으로, M1 32GB에서 MPS를 사용해 안정적으로 돌릴 수 있는 모델 크기는 7B 파라미터 정도다. 13B 이상은 양자화(4-bit) 없이는 메모리가 부족하다. llama.cpp의 Metal 가속을 활용하면 양자화된 모델을 효율적으로 돌릴 수 있다.
conda vs pyenv+venv 비교
이 글 전체에서 pyenv + venv 조합을 다뤘지만, "그냥 conda 쓰면 안 되나?"라는 질문을 많이 받는다. 결론부터 말하면 상황에 따라 다르다.
| 항목 | pyenv + venv | conda (Miniforge) |
|---|---|---|
| Python 버전 관리 | pyenv (소스 빌드) | conda install python=3.12 |
| 패키지 관리자 | pip (PyPI) | conda + pip 혼용 |
| 설치 속도 | 빠름 (wheel) | 느림 (의존성 해결) |
| 디스크 사용 | 가벼움 | 무거움 (환경당 1~5GB) |
| 비Python 패키지 | Homebrew 별도 관리 | conda로 통합 관리 |
| M1 ARM 지원 | 네이티브 빌드 | Miniforge 권장 |
| 학습 곡선 | 낮음 | 중간 |
| 추천 대상 | 웹/API/일반 AI 개발 | 과학 계산, R/Julia 혼용 |
나의 선택 기준은 이렇다:
- pyenv + venv를 쓸 때: 순수 Python 프로젝트, 웹 서버, API 개발, PyTorch 기반 AI 프로젝트. 대부분의 경우 이쪽이 가볍고 빠르다.
- conda를 쓸 때: CUDA 버전 관리가 필요하거나(M1에서는 해당 없음), R이나 Julia를 같은 환경에서 써야 하거나, 특정 과학 패키지가 conda-forge에만 있는 경우.
M1 Mac에서 conda를 쓸 거라면 반드시 Miniforge를 사용해야 한다. 일반 Anaconda나 Miniconda는 ARM64를 제대로 지원하지 않는 채널을 기본으로 사용하기 때문에 문제가 생긴다.
# Miniforge 설치 (conda를 쓰기로 했다면)
$ brew install miniforge
# conda init
$ conda init zsh
$ source ~/.zshrc
# ARM64 확인
$ conda info | grep platform
platform : osx-arm64
# 환경 생성
$ conda create -n ml python=3.12
$ conda activate ml
# PyTorch 설치 (conda-forge 채널)
$ conda install pytorch torchvision torchaudio -c pytorch
개인적으로는 pyenv + venv 조합이 더 가볍고 직관적이라 이쪽을 주력으로 쓰고 있다. conda의 "solving environment" 단계에서 5분씩 걸리는 걸 기다리는 게 체질에 안 맞기도 하고. 다만 이건 순전히 취향이고, conda 생태계가 이미 익숙하다면 굳이 바꿀 이유는 없다.
지금까지 M1 Mac에서 Python AI 개발환경을 세팅하는 전 과정을 다뤘다. 정리하면:
- pyenv로 Python 버전을 관리하고 (ARM 네이티브 필수 확인)
- venv로 프로젝트별 패키지를 격리하고
- PyTorch MPS로 Metal GPU 가속을 활용한다
이 세 가지만 제대로 세팅하면, M1 Mac에서 AI 개발하는 데 불편함이 거의 없다. NVIDIA GPU가 없어도 로컬에서 모델 학습과 추론을 돌릴 수 있다는 게 M1의 최대 장점이고, 그 장점을 살리려면 MPS 설정을 빠뜨리면 안 된다. 자세한 내용은 pyenv GitHub를 참고하자.