파일이 직접 실행될 때만 돌아야 하는 코드와 import되어도 안전해야 하는 정의를 나누고 싶을 때 main guard를 씁니다.
핵심은 __name__ 값이 실행 맥락에 따라 달라진다는 점과, 실행 로직을 main()으로 묶어 두면 재사용과 테스트가 쉬워진다는 점입니다.
핵심 정리
def main() -> None:
print("run app")
if __name__ == "__main__":
main()문법
기본형은 실행 함수와 main guard 두 줄로 보면 됩니다.
def main() -> None:
...
if __name__ == "__main__":
main()실행 분리
main guard는 "직접 실행"과 "import 시 평가"를 구분한다
Python 모듈은 import될 때 top-level 문장이 한 번 평가됩니다. 그래서 실행용 코드를 그냥 아래에 두면, 다른 모듈이 import할 때도 원치 않게 동작할 수 있습니다. main guard는 이 문제를 막습니다.
def helper():
return 1
if __name__ == "__main__":
print(helper())이 패턴 덕분에 같은 파일을 스크립트로도, 라이브러리 모듈로도 쓸 수 있습니다.
실행 맥락
__name__ 값은 실행 맥락을 알려 준다
직접 실행된 파일은 __name__ == "__main__"이 되고, import된 모듈은 자신의 모듈 이름을 가집니다. python -m package.module처럼 모듈 실행 방식이어도 실행 진입점에서는 __main__으로 동작합니다.
print(__name__)이 규칙이 main guard가 동작하는 기반입니다.
실행 로직은 main() 함수 안으로 넣는 편이 테스트와 재사용에 좋다
guard 안에 바로 긴 코드를 쓰기보다 main() 함수로 감싸면 테스트와 재사용이 쉬워집니다.
def main() -> None:
...
if __name__ == "__main__":
main()입력 파싱, 리턴 코드 처리, 예외 처리도 이 구조 위에서 정리하기 좋습니다.
구조 선택
main guard를 언제 두는가
| 상황 | 적합한 선택 |
|---|---|
| 스크립트 직접 실행 코드 분리 | main guard |
| import 시 부작용 방지 | if __name__ == "__main__": |
| 실행 로직 정리 | main() 함수 |
| 재사용 가능한 유틸 제공 | top-level 정의 + guard 분리 |
주의할 점
top-level에 실행 코드를 바로 두면 import만 해도 동작해 버립니다.
# ❌ import 시에도 실행됨
print("start app")
# ✅ 직접 실행될 때만 수행
if __name__ == "__main__":
print("start app")참고 링크
2 sources