파이썬에서 가장 이상해 보이는 한 줄 — 풀어드립니다
아무 파이썬 파일이나 열어보면 맨 아래서 이걸 보게 될 거예요:
if __name__ == "__main__":
main()
마법 같은 상투적인 문구처럼 보이죠. 실은 무슨 일을 하는지만 알면 아주 실용적인 기능이에요 — 파이썬이 "스크립트"와 "라이브러리" 사이에 선을 긋지 않기 때문에 존재합니다.
배경: 파일을 쓰는 두 가지 방법
파이썬의 모든 .py 파일은 두 가지 방식으로 쓸 수 있어요:
- 스크립트로 —
python3 file.py로 직접 실행. - 모듈로 — 다른 파일이
import file로 임포트.
언어는 여러분이 둘 중 어느 걸 쓰고 있는지 미리 선언하게 하지 않아요. 어느 파일이든 둘 다가 될 수 있어요.
math_helpers.py라는 파일을 상상해 봅시다:
# math_helpers.py
def mean(values):
return sum(values) / len(values)
def median(values):
s = sorted(values)
mid = len(s) // 2
if len(s) % 2 == 0:
return (s[mid - 1] + s[mid]) / 2
return s[mid]
# 개발하면서 돌려보는 빠른 스모크 테스트
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print("mean:", mean(numbers))
print("median:", median(numbers))
이 파일을 직접 실행하면 테스트 출력이 찍혀요 — 좋아요. 그런데 다른 파일이 import math_helpers를 하면, 그 print 문들이 임포트되는 도중에 실행돼요. 이 모듈을 쓰는 모든 사용자가 개발용 낙서 출력을 보게 됩니다. 그건 별로죠.
__name__이 뭔가요
파이썬의 모든 모듈에는 __name__이라는 내장 변수가 있어요. 파이썬이 자동으로 설정해 줍니다:
- 파일이 임포트되면,
__name__은 그 모듈의 임포트 이름이 돼요 — 위 예제에서는"math_helpers". - 파일이 직접 실행되면, 파이썬이
__name__을 특별한 문자열"__main__"으로 설정해요.
덕분에 지금이 어느 모드인지 구분할 수 있게 돼요. "스크립트 전용" 코드를 이 검사로 감싸세요:
# math_helpers.py
def mean(values):
return sum(values) / len(values)
def median(values):
s = sorted(values)
mid = len(s) // 2
if len(s) % 2 == 0:
return (s[mid - 1] + s[mid]) / 2
return s[mid]
if __name__ == "__main__":
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print("mean:", mean(numbers))
print("median:", median(numbers))
이제 python3 math_helpers.py는 테스트 출력을 찍어요. 하지만 다른 파일에서 import math_helpers를 하면 그 블록은 통째로 건너뛰어져요 — 함수들은 쓸 수 있고, 원치 않는 건 실행되지 않아요.
자주 같이 쓰이는 짝: main() 함수
실제 스크립트는 대부분 전용 main() 함수를 만들고 가드 블록은 작게 유지해요:
# process_orders.py
import sys
def load_orders(path):
with open(path) as f:
return [line.strip() for line in f if line.strip()]
def process(orders):
for order in orders:
print(f"Processing {order}")
def main():
if len(sys.argv) < 2:
print("Usage: python3 process_orders.py <file>")
sys.exit(1)
orders = load_orders(sys.argv[1])
process(orders)
if __name__ == "__main__":
main()
왜 가드 아래에 바로 로직을 쓰지 않고 main()을 굳이 만드는가:
- 테스트 가능성. 모듈을 임포트해서 테스트에서
main()(이나 다른 헬퍼)을 호출할 수 있어요. - 지역 변수.
main()안에 정의된 건 모듈 수준 이름이 아니라 지역 변수가 돼요. 이름 충돌을 피할 수 있고 모듈의 공개 표면이 깔끔해져요. - 가독성. 가드 블록이 이제 두 줄이에요 — 뭉뚱그려진 로직이 아니라 명확한 "스크립트 진입점"이 됩니다.
빠른 시연
동작을 직접 볼 수 있어요:
이 스니펫을 파이썬으로 실행하면 __name__ is: __main__과 "being run as a script."가 찍혀요. 다른 파일이 이걸 임포트했다면 같은 검사가 다른 분기를 찍을 거고요.
가드가 필요 없는 경우
가드가 자라지 않는 파이썬 파일도 많아요. 누구도 임포트할 리 없는 짧은 스크립트라면 없어도 괜찮아요:
# one_off_rename.py
import os
for name in os.listdir("."):
if name.endswith(".txt"):
os.rename(name, name.lower())
완전히 좋아요. 라이브러리를 만드는 게 아니고, 아무도 이걸 임포트하지 않을 거예요. 하지만 파일 안에 재사용 가능한 로직이 생기는 순간 — 그리고 사이드 이펙트를 일으키는 코드를 그 옆에 두고 싶어지는 순간 — 가드를 꺼내세요.
설치된 패키지의 엔트리 포인트
여러분의 코드를 진짜 패키지로 배포하게 되면, 더 정식 메커니즘이 있어요: 패키지 메타데이터의 entry_points. 명령어를 함수에 매핑해 주죠. 여러분의 패키지를 설치한 사용자는 그 함수를 바로 호출하는 셸 명령을 얻게 돼요. 하지만 자기 컴퓨터의 폴더에서 스크립트를 돌리는 수준에서는 __main__ 가드가 표준 도구예요.
이번 챕터 마무리
이제 여러분이 가진 것들:
- 로직에 이름을 붙이는 함수.
- 유연한 호출을 위한
*args/**kwargs. - 일회용 함수를 위한 lambda.
- 함수를 감싸고 문서화하는 데코레이터와 타입 힌트.
- 코드를 파일과 프로젝트로 나누는 모듈, pip, 가상환경.
- 스크립트와 모듈이 공존하게 해주는
__main__가드.
다음: 클래스
지금까지는 대부분 함수와 평범한 데이터 — dict, list, tuple — 를 짝지어 다뤘어요. 다음 챕터는 클래스를 소개합니다. 파이썬이 데이터와 동작을 묶는 방식이고, self, __init__, 상속, 데이터클래스 같은 개념이 사는 곳이에요.
자주 묻는 질문
if __name__ == '__main__'은 뭘 하나요?
if __name__ == '__main__'은 뭘 하나요?파일이 직접 실행될 때(모듈로 임포트되었을 때가 아니라) 만 그 아래 블록을 실행해요. 덕분에 한 .py 파일이 스크립트로 돌아갈 수도, 다른 파일에서 임포트돼 함수와 클래스를 제공할 수도 있게 돼요 — 임포트할 때 스크립트 동작이 함께 일어나는 일 없이요.
파이썬에 main 함수가 꼭 필요한가요?
아니요. 파이썬 파일은 위에서 아래로 자동 실행돼요. 하지만 파일에 임포트돼서도 쓰일 로직이 생기는 순간부터 if __name__ == '__main__' 가드가 중요해져요 — 그리고 스크립트의 최상위 작업을 main() 함수 안에 넣는 게 흔히 짝지어지는 습관이에요.
__name__과 __main__은 뭐가 다른가요?
__name__과 __main__은 뭐가 다른가요?__name__은 파이썬이 모든 모듈에 설정하는 특별 변수예요. 파일이 임포트되면 __name__은 모듈 이름(예: 'util')이 되고, 직접 실행되면 파이썬이 __name__을 문자열 '__main__'으로 설정해요. if는 그 둘을 비교하는 거예요.