포스트

데이터 파이프라인에서 자주 발생하는 Python 모듈 경로 에러 해결법

데이터 파이프라인에서 자주 발생하는 Python 모듈 경로 에러 해결법

데이터 파이프라인 구성 중,
from etl.load_to_postgres import foo 같은 코드를 작성했는데 아래와 같은 오류가 발생했다:

1
ModuleNotFoundError: No module named 'etl'

처음에는 etl 폴더가 분명히 있는데 왜 못 찾지? 싶었는데, 알고 보니 Python의 모듈 탐색 경로 문제였다.
이 글에서는 Python 프로젝트에서 자주 발생하는 모듈 import 문제를 어떻게 해결했는지 정리해본다.

📁 디렉토리 구조

1
2
3
4
5
6
7
project/
├── src/
│   ├── etl/
│   │   └── load_to_postgres.py   
│   ├── api/
│   │   └── fetch_places.py   
│   └── run_etl.py

나는 src/api/fetch_places.py 안에서 아래와 같이 import를 시도했는데,

1
from etl.load_to_postgres import foo

아래와 같은 에러가 발생했다:

1
ModuleNotFoundError: No module named 'etl'

🔍 원인

Python은 기본적으로 실행한 파일의 위치를 기준으로 모듈을 찾는다.

즉, 아래처럼 실행하면:

1
python src/api/fetch_places.py

현재 경로는 src/api가 되고, Python은 여기서 etl을 찾는다. 하지만 실제 etl은 src/etl에 있기 때문에 못 찾는 것이다.

📌 즉, 폴더 구조는 잘 만들어놨더라도, Python 입장에서 etl이 어디 있는지 모르면 import는 실패한다.

💡 해결 방법 1: sys.path.append() 사용

가장 빠른 해결 방법은 코드에서 직접 모듈 탐색 경로를 추가해주는 것이다.

1
2
3
4
5
6
7
import sys
import os

# 현재 파일 기준으로 프로젝트 루트(src 상단) 경로 추가
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from etl.load_to_postgres import foo

sys.path는 Python이 모듈을 찾기 위해 참고하는 경로들의 리스트인데, 여기에 src/ 경로를 직접 추가해준 것이다.

이렇게 하면 Python은 src/etl 안에 있는 load_to_postgres.py 파일을 찾아서 정상적으로 import할 수 있게 된다.

📌 이 방식은 지금 이 파일만 실행할 경우엔 효과적이지만, 여러 파일에 매번 써야 하므로 프로젝트가 커지면 관리가 번거로워진다.

💡 해결 방법 2: PYTHONPATH 환경변수 설정

여러 스크립트를 연속 실행하거나, 루트에서 실행할 때는 PYTHONPATH 환경변수를 설정하는 게 더 깔끔하다.

1
PYTHONPATH=./src python src/api/fetch_places.py

이렇게 하면 Python은 src/ 디렉토리를 모듈 탐색 경로로 인식한다. 즉, etl.load_to_postgres 같은 절대 경로 import가 가능해진다.

또는 여러 스크립트를 실행해야 하는 경우,

1
2
3
4
5
6
7
8
# run_etl.py
import subprocess
import os

env = os.environ.copy()
env["PYTHONPATH"] = "./src"

subprocess.run(["python", "src/api/fetch_places.py"], env=env)

이렇게 하면 run_etl.py가 각 하위 모듈을 실행할 때도 모듈 경로 문제가 발생하지 않는다.

마무리

처음에는 “폴더 구조도 잘 해놨는데 왜 import가 안되지?” 싶었는데,
알고 보니 Python은 파일 시스템 구조와는 별개로 실행 위치를 기준으로 모듈을 찾는다는 걸 몰랐던 게 원인이었다.

결론적으로, 프로젝트를 디렉토리별로 잘 나눴다면

  • 빠르게 테스트하거나 단독 실행할 때는 sys.path.append()
  • 전체 프로젝트 구조로 일관되게 실행하려면 PYTHONPATH 환경변수 설정

두 가지 방식 중 상황에 맞게 선택하면 된다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.