Python 프로젝트를 구조화하거나 규모가 커질수록 모듈, 패키지, 그리고 import에 대한 정확한 이해가 필수입니다. 이 글에서는 모듈과 패키지의 개념부터 __init__.py의 역할, import 에러가 발생하는 이유를 예제와 함께 정리합니다.
모듈, 패키지, import 개념 정리: __init__.py
목차
1. 모듈(Module)과 패키지(Package)란?
“모듈(Module)”과 “패키지(Package)” 개념은 Python 코드의 구조화와 재사용성 향상에 핵심적인 역할을 합니다
◆ 모듈(Module)
Python 코드가 들어 있는 .py 파일 하나가 곧 모듈입니다.
- 함수, 변수, 클래스 등을 정의하고 모아 놓은 코드 묶음 단위입니다.
- 다른 파일에서 import하여 재사용할 수 있습니다.
my_project/
├── main.py
└── utils.py ← 이것이 하나의 "모듈"
예제 코드 (utils.py)
def add(a, b):
return a + b
PI = 3.14
사용 방법(main.py)
import utils
print(utils.add(3, 4)) # 7
print(utils.PI) # 3.14
◆ 패키지(Package)
여러 모듈을 하나로 묶은 디렉토리(폴더)이며, 그 안에 __init__.py 파일이 있으면 Python이 이 디렉토리를 패키지로 인식합니다.
- 프로젝트 규모가 커질수록 모듈을 기능별로 나누고 폴더 단위로 정리해야 함
- Python 3.3 이상부터는:
- __init__.py 파일이 없어도 해당 디렉토리를 패키지처럼 import할 수 있습니다.
- 이를 "namespace package" 라고 부릅니다.
- 하지만 __init__.py가 있으면 명시적인 패키지 (regular package)로 간주됩니다
예시 구조:
my_project/
├── main.py
└── utils/ ← 이것이 "패키지"
├── __init__.py ← 패키지로 인식되도록 함
├── math_utils.py ← 모듈
└── string_utils.py ← 모듈
예제코드(utils/math_utils.py)
def add(a, b):
return a + b
사용방법(main.py)
from utils.math_utils import add
print(add(5, 6)) # 11
◆ 모듈(Module) vs 패키지(Package)
구분 | 모듈(Module) | 패키지(Package) |
형태 | .py 파일 하나 | 디렉토리 (폴더) |
예시 | math.py | utils/, services/ |
내부 구성 | 함수, 변수, 클래스 | 여러 개의 모듈 (.py) |
재사용 방법 | import 모듈명 | from 패키지.모듈 import 함수 |
확장성 | 작고 단일 기능 | 대규모 기능 분할 가능 |
2. __init__.py의 의미와 역할
__init__.py는 해당 디렉토리를 Python 패키지로 인식시키는 파일입니다.
Python 3.3 이상에서는 없어도 import가 가능하지만, 실무에서는 항상 넣는 것을 권장합니다.
◆ __init__.py의 주요 역할과 예시
역할 | 설명 | 코드 예시 |
① 패키지 선언 | 디렉토리를 패키지로 인식시킴 | 폴더에 __init__.py만 있으면 import 가능 |
② 내부 모듈 자동 로딩 | 패키지를 import할 때 특정 모듈/함수를 자동으로 포함 | from .logger import log |
③ 공용 export 지정 | from package import * 시 export할 이름 제어 | __all__ = ['log', 'add'] |
④ 초기화 코드 실행 | 패키지가 import될 때 실행할 코드 정의 가능 | print("패키지 초기화됨") |
my_project/
├── main.py
└── utils/
├── __init__.py
├── logger.py ← log()
└── math_utils.py ← add()
① 패키지 선언
- Python은 __init__.py가 있으면 utils 폴더를 하나의 패키지로 인식합니다.
- 이게 없으면 상대 import (from . import logger) 등에서 오류 발생 가능
# main.py에서
from utils import logger
② 내부 모듈 자동 로딩
- __init__.py에서 하위 모듈을 import하면, 외부에서는 직접 접근하지 않아도 사용할 수 있게 됩니다.
- 보통은 main.py에서 이 두 파일을 이렇게 각각 불러와야 합니다:
from utils.logger import log
from utils.math_utils import add
- utils/__init__.py 파일 안에 이렇게 적어두면:
from .logger import log
from .math_utils import add
#즉, "utils 폴더가 열릴 때 log와 add를 자동으로 같이 가져오도록 하겠다"는 의미입니다.
- 그리고 나서, main.py에서 아래와 같이 짧고 간다하게 쓸 수 있습니다.
from utils import log, add
③ 공용 export 제어 (__all__)
- from utils import *로 import할 수 있는 객체를 제한합니다.
- 지정하지 않으면 __init__.py에 명시되지 않은 항목은 import되지 않음
- utils/__init__.py:
from .logger import log
from .math_utils import add
__all__ = ['log', 'add']
- 사용예:
from utils import *
log("info")
print(add(10, 20))
④ 초기화 코드 실행
- 패키지가 import될 때 실행되어야 하는 코드가 있다면 여기에 작성합니다.
- 로깅, 환경 설정, 캐시 초기화 등에 사용
- utils/__init__.py:
print("✅ utils 패키지 로딩됨")
from .logger import log
3. import 대상 및 문법 정리
◆ 실질적으로 import 가능한 대상
대상 | 예시 | 설명 |
모듈 (.py) | import utils.helper | 파일 단위로 가져오기 |
함수 | from math import sqrt | 함수만 가져오기 |
클래스 | from datetime import datetime | 클래스만 가져오기 |
상수/변수 | from config import DEBUG | 상수, 설정값 등 |
패키지 | import numpy, import mediapipe.tasks | 폴더 전체 (내부에 __init__.py) |
__init__.py에서 정의한 것 | from utils import log | __init__.py에서 자동 노출시 가능 |
- 디렉토리는 __init__.py가 있어야 패키지로 import 가능
- 파일이나 폴더 이름이 숫자로 시작하면 안 됨
- 확장자는 .py 여야 함 (또는 .so, .pyd 등 C-extension)
#1. 모듈 import
import utils.helper # utils/helper.py
#2.모듈 내 함수 import
from utils.helper import some_function
#3.외부 패키지 import
import numpy as np
#4.서브 모듈 import
from mediapipe.tasks.python.vision import GestureRecognizer
◆ 다양한 import 문법 정리
문법 | 예시 | 설명 |
import module | import math | 전체 모듈을 불러와 math.sqrt()처럼 사용 |
import module as alias | import numpy as np | 짧은 이름으로 축약 가능 |
from module import item | from math import sqrt | 필요한 함수/클래스만 가져오기 |
from module import * | from math import * | 모든 항목 import (⛔ 가독성 저하) |
동적 import | importlib.import_module("pkg.mod") | 런타임에 모듈 로딩 (플러그인 방식) |
4. 디렉토리 import 구조 예시
예시구조:
my_project/
├── main.py
├── utils/
│ ├── __init__.py
│ └── helper.py # ← some_function 정의
└── services/
├── __init__.py
└── service_core.py # ← helper.py import
utils/helper.py
def some_function():
return "Hello from helper!"
services/service_core.py
from utils.helper import some_function
def run_service():
print(some_function())
main.py
from services.service_core import run_service
if __name__ == "__main__":
run_service()
◆ import 기준
import 경로의 기준은 '실행하는 .py 파일의 위치'가 아니라, 실행된 파일이 위치한 디렉토리 = sys.path[0]입니다.
예를 들어:
cd my_project
python main.py
sys.path[0] == "my_project/" → from utils.helper 정상 작동
◆ import 오류 예시
cd services
python service_core.py
이 경우 sys.path[0] == "services/" → 상위 폴더의 utils/를 찾을 수 없음
◆ 추천 import 패턴
항목 | 권장 방식 |
모듈 import | 항상 절대 경로 import 사용 (from utils.helper import ...) |
실행 위치 | 항상 루트에서 실행 (main.py) |
__init__.py | 모든 하위 디렉토리에 포함 |
테스트 시 | sys.path 또는 PYTHONPATH 설정 |
관련 글 링크
https://docs.python.org/ko/3.13/tutorial/modules.html
6. Modules
If you quit from the Python interpreter and enter it again, the definitions you have made (functions and variables) are lost. Therefore, if you want to write a somewhat longer program, you are bett...
docs.python.org
'3.개발언어&라이브러리 > Python' 카테고리의 다른 글
6. Python 병렬 처리 : GIL, threading, asyncio, multiprocessing (0) | 2025.05.22 |
---|---|
5. Python 예외(Exception) 처리 : try-except-finally, with (0) | 2025.05.22 |
4. Python 함수구조, 함수인자, 람다함수, 클로저, 고차함수, 데코레이터 (0) | 2025.05.22 |
3. Python 클래스 정리: 클래스, 상속, 메서드, 접근제어 (0) | 2025.05.21 |
2. Python 변수 정리: 지역변수, 전역변수, global, 클래스 변수 (0) | 2025.05.21 |