내가 쓴 파이썬 코드 한 줄이 어떻게 컴퓨터를 움직일까. 사실 이걸 몰라도 코딩은 할 수 있다. 그래도 파이썬 동작 원리를 알아두면 에러를 만났을 때 당황이 줄고, 코드가 왜 그렇게 도는지 감이 잡힌다. 어렵지 않으니 한 번 훑어보자.

컴퓨터는 사람 말을 모른다
한국어나 영어처럼 우리가 쓰는 말을 자연어라 한다. 보통의 컴퓨터는 이 자연어를 알아듣지 못한다. 그래서 컴퓨터에 일을 시키려면 파이썬 같은 프로그래밍 언어가 필요하다. 그런데 사실 컴퓨터의 진짜 모국어는 0과 1로 된 기계어뿐이다. 우리가 파이썬으로 쓴 코드도, 결국 이 기계어로 번역돼야 CPU가 실행한다. 그 번역을 누가, 어떻게 하느냐가 동작 원리의 핵심이다.
파이썬 코드 자체는 사람이 읽기 좋게 생겼다. print("안녕") 같은 한 줄은 우리 눈엔 직관적이지만, CPU에는 외계어나 다름없다. 그 사이의 거리를 메우는 다리가 필요하고, 파이썬은 그 다리를 안에서 알아서 놓아준다. 우리가 다리 설계를 신경 쓰지 않아도 되는 것, 그게 파이썬이 편한 이유이자 동시에 안에서 무슨 일이 벌어지는지 한 번쯤 들여다볼 가치가 있는 이유다.
코드가 실행되는 흐름
파이썬 코드는 한 번에 기계어로 가지 않는다. 중간 단계를 하나 거친다. 흐름을 그리면 이렇다.
소스 코드(.py) → 파이썬 컴파일러 → 바이트코드(.pyc) → 파이썬 가상 머신(인터프리터) → 기계어 → CPU.
먼저 파이썬은 내가 쓴 소스 코드를 ‘바이트코드’라는 중간 코드로 컴파일한다. 이 바이트코드는 사람도, CPU도 아닌 그 중간 어디쯤의 명령어 모음이다. 그다음 파이썬 가상 머신(Python Virtual Machine, PVM)이 이 바이트코드를 한 줄씩 읽어 기계어로 바꿔 CPU에 넘긴다. 우리가 흔히 쓰는 표준 파이썬은 C 언어로 만들어진 ‘CPython’이라는 구현인데, python 파일.py를 칠 때마다 바로 이 CPython이 위 과정을 돌린다. GeeksforGeeks가 정리한 파이썬 내부 동작을 보면 이 흐름이 더 자세히 그려져 있다.
여기서 ‘컴파일’과 ‘인터프리터’라는 말이 헷갈릴 수 있다. 흔히 C나 자바는 컴파일 언어, 파이썬은 인터프리터 언어로 나누지만, 실제로 파이썬은 둘을 섞어 쓴다. 안에서 한 번 컴파일을 하고, 그 결과를 인터프리터가 실행하는 식이다. 그래서 ‘파이썬은 컴파일 안 한다’는 말은 정확히는 틀린 셈이다. 다만 그 컴파일이 자동으로, 보이지 않게 일어나기 때문에 우리가 신경 쓸 일이 없을 뿐이다.
두 번 변환하는 게 비효율 아닐까?
여기서 의문이 들 만하다. 컴파일도 하고 인터프리터도 거치니, 변환을 두 번 하는 셈이다. “그거 비효율 아니야?” 결론부터 말하면 정반대다. 이 중간 단계가 오히려 효율을 높인다. 이유는 두 가지다.
첫째, 바이트코드라는 중간 코드가 있어야 최소한의 최적화가 가능하다. 사람 말을 곧장 기계어로 직역하는 것보다, 한 번 정돈된 중간 형태를 거치는 편이 더 매끄럽다. 게다가 이 바이트코드는 운영체제에 상관없이 도는 크로스플랫폼 명령어라, 한 번 만들면 여러 환경에서 같은 방식으로 쓰인다.
둘째, 캐싱 덕분이다. 파이썬은 만든 바이트코드를 __pycache__ 폴더 안에 .pyc 파일로 저장해둔다. 다음에 같은 코드를 실행할 때, 소스가 바뀌지 않았다면 다시 컴파일하지 않고 저장해둔 .pyc를 바로 쓴다. 불필요한 번역을 건너뛰니 실행이 빨라진다. 두 번 변환하는 게 손해가 아니라, 두 번째부터 시간을 버는 구조인 셈이다.
비유하자면 이렇다. 외국어 문서를 매번 처음부터 통째로 번역하는 대신, 한 번 번역해 둔 사본을 책상 서랍에 넣어두는 것과 같다. 원문이 그대로면 서랍의 사본을 꺼내 쓰면 되고, 원문을 고쳤을 때만 다시 번역한다. 바이트코드라는 ‘중간 번역본’을 두는 이 방식이 바로 파이썬이 빠르면서도 유연할 수 있는 비결이다.
그래서 ‘인터프리터 언어’라고 부른다
이렇게 안에서는 컴파일을 거치지만, 우리 입장에선 파이썬이 그냥 ‘바로 실행되는 언어’처럼 느껴진다. 따로 컴파일·링크 버튼을 누를 필요가 없고, 에러가 나면 내가 쓴 .py 파일의 몇 번째 줄이 문제인지 바로 알려준다. 고치고 다시 돌리는 순환이 빠르다. 그래서 파이썬을 흔히 인터프리터 언어라 부른다. 입문자에게 친절한 이유가 여기에도 있다. 파이썬이 왜 첫 언어로 좋은지는 파이썬의 매력에서, 무엇을 만들 수 있는지는 파이썬으로 할 수 있는 것에서 더 다뤘다.
파이썬 동작 원리를 알면 무엇이 좋을까
솔직히 이 원리를 몰라도 코딩은 된다. 그래도 알아두면 분명히 도움이 된다. 예를 들어 프로젝트 폴더에 __pycache__라는 폴더가 생겨도 당황하지 않는다. 그게 파이썬이 만들어둔 캐시라는 걸 아니까. 에러 메시지가 어느 단계에서 나는지 감이 잡히고, “파이썬은 느리다”는 말이 어떤 맥락인지도 이해된다. AI가 짜 준 코드를 읽을 때도, 그 코드가 실제로 어떻게 도는지 떠올릴 수 있으면 검증이 한결 수월해진다. 코딩이 처음이라면 프로그래밍 배우기, 망설이는 그대에게부터 시작해도 좋다.
“파이썬은 느리다”는 말도 이 구조에서 나온다. 바이트코드를 가상 머신이 한 줄씩 해석하다 보니, 처음부터 기계어로 직접 컴파일되는 C 같은 언어보다 같은 작업을 느리게 처리할 때가 있다. 하지만 대부분의 일상적인 작업에서는 그 차이가 체감되지 않고, 정작 속도가 중요한 부분은 C로 짜인 라이브러리가 대신 처리한다. 데이터 분석이나 AI에서 파이썬이 빠르게 느껴지는 건 바로 이 덕분이다. 그러니 ‘느리다’는 한 문장만 보고 겁먹을 필요는 없다.
원리는 거들 뿐, 일단 만들어보자
파이썬 동작 원리를 한 번 이해해두면 코드를 보는 눈이 한 뼘 깊어진다. 다만 이걸 완벽히 외운 다음에야 코딩을 시작할 필요는 없다. 오히려 작은 코드를 직접 돌려보면서, “아 이게 그 바이트코드로 바뀌어 실행되는 거구나” 하고 몸으로 익히는 편이 빠르다.
정리하면, 파이썬은 내 코드를 바이트코드로 한 번 정리한 뒤 가상 머신이 실행하고, 그 결과를 .pyc로 저장해 다음 실행을 빠르게 만든다. 복잡해 보여도 결국 ‘읽기 쉬운 코드’와 ‘컴퓨터가 알아듣는 말’ 사이를 부드럽게 잇기 위한 장치다. 이 한 장면만 머릿속에 그려둬도, 파이썬을 다루는 내내 든든한 배경지식이 된다. 원리는 거들 뿐이다. 일단 한 줄 써서 실행해보면, 이 흐름이 비로소 손에 잡힌다.
참고 자료
- GeeksforGeeks, "Internal working of Python"
- Opensource.com, "An introduction to Python bytecode"