[ 데이터를 위한 Python : From Scratch to Master. ] 파이썬의 실행 구조 및 메모리 모델.

0
post-thumbnail

[ 데이터를 위한 Python : From Scratch to Master.] 파이썬의 실행 구조 및 메모리 모델.

∇ 파이썬의 실행 구조 및 메모리 모델.

# 파이썬의 실행 구조 및 메모리 모델 #

1. 📙 파이썬 인터프리터 구조
   1-1📒 CPython, PyPy, Jython 차이

   1-2📒 바이트코드와 인터프리터 동작

2. 📙 메모리 모델 및 객체 구조
   2-1📒 변수 참조, 객체 ID, 가비지 컬렉션

   2-2📒 참조 카운팅과 순환 참조 처리

1. 📙 파이썬 인터프리터 구조


파이썬 인터프리터 구조란??

파이썬은 '인터프리터' 언어.

  • 파이썬은 '인터프리터 언어'입니다.
  • 이는 코드를 '한 줄씩 해석해서 실행하는 방식'을 의미합니다.
  • 컴파일 언어(C, JAVA 등등)는 먼저 전체 코드를 기계어로 번역(컴파일)한 뒤 실행하지만,
    파이썬은 바로 실행할 수 있습니다.

파이썬 실행 흐름.

  • 파이썬 프로그램은 다음과 같은 과정을 거쳐서 실행됩니다.
.py 파일
↓ (컴파일)
바이트코드(.pyc)
↓ (인터프리터)
Python Virtual Machine(PVM)에서 실행
  • 파이썬은 먼저 코드를 '바이트 코드'로 변환합니다.

  • 이 바이트코드는 "PVM(Python Virtual Machine)"이 해석하여 실행합니다.

1-1📒 CPython, PyPy, Jython 차이

차이 분석.

  • 파이썬에는 여러 '구현체'가 있습니다.
  • 쉽게 말하면, 파이썬 언어를 구현한 프로그램 버전이 여러 개라는 뜻입니다.
구현체설명특징
CPython가장 널리 쓰이는 공식 구현체- C로 구현
- 바이트코드 → PVM에서 해석 실행
- 참조 카운팅 기반 메모리 관리
PyPy성능 최적화된 구현체- JIT 컴파일 사용
- 루프/함수 실행을 기계어로 변환해 캐싱
- 속도 ↑ (특히 반복 연산, 수치 계산)
JythonJava 기반 파이썬- JVM 위에서 실행
- Java 라이브러리 사용 가능
- Java와의 통합 용이
IronPython.NET 기반 파이썬- CLR(Common Language Runtime) 기반
- C# 라이브러리와 상호운용

초보자는 CPython만 알고 시작해도 충분합니다. 나중에 성능이 중요해지면 PyPy 등을 알아보세요.

🔍 실무에서의 선택 기준.

  • 일반적인 개발 → CPython

  • 고성능 연산 / 반복 작업 최적화 → PyPy

  • Java 기반 환경과 통합 필요 → Jython

  • .NET 환경 연동 → IronPython

1-2📒 바이트코드와 인터프리터 동작

바이트 코드란?

  • 바이트코드는 사람이 읽기 어려운 중간 코드입니다.

  • 파이썬 코드를 바이트 코드로 먼저 바꾼 후 실행됩니다.

  • .pyc 파일로, pycache 에 저장됨.

  • 인터프리터(PVM)가 이를 해석하여 실행.

🔧 예제: 바이트코드 확인.

파이썬 코드가 바이트코드로 어떻게 바뀌는지 보려면 'dis 모듈'을 사용합니다.

import dis

def add(x, y):
    return x + y

dis.dis(add)
  2           0 LOAD_FAST                0 (x)
              2 LOAD_FAST                1 (y)
              4 BINARY_ADD
              6 RETURN_VALUE
  • 'LOAD_FAST' , 'BINARY_ADD' 는 스택 기반 연산 명령어.

🔍 인터프리터란?

  • 바이트코드는 '인터프리터(PVM)'가 해석하여 실행합니다.

  • 파이썬의 인터프리터는 '스택 기반 가상 머신'입니다.

🔍 PVM(Python Virtual Machine)

  • '바이트 코드'를 "스택 기반 가상 머신 방식"으로 한 줄씩 해석.

  • 레지스터 기반이 아닌 스택 기반! -> 구현은 단순하나 속도는 느려짐. !

2. 📙 메모리 모델 및 객체 구조


2-1. 📒 변수는 이름표다.

a = [1, 2, 3]
b = a
  • 위 코드는 'a'라는 이름이 리스트를 가리키고,

  • 'b'도 같은 리스트를 가리킵니다.

객체 ID 확인.

  • 파이썬에서 'id()' 함수는 객체의 고유 번호를 알려줍니다.
  • CPython에서는 '메모리 주소'와 거의 같습니다.
print(id(a), id(b))  # 같은 숫자 출력

2-2. 📒 객체는 힙(Heap)에 저장된다.

  • 파이썬 객체(리시트, 클래스 등)는 '힙 영역'에 저장됩니다.

  • 변수는 객체를 직접 저장하지 않고, 참조(포인터)를 저장합니다.

2-3. 📒 객체 구조 ( CPython )

  • 파이썬의 모든 객체는 내부적으로 다음과 같은 구조를 가집니다.
struct PyObject {
    Py_ssize_t ob_refcnt;    // 참조 횟수
    PyTypeObject *ob_type;   // 타입 정보
};
  • 'ob_refcnt' : 이 객체를 몇 개의 변수나 자료구조가 참조하고 있는지 나타냅니다.

2-4. 📒 가비지 컬렉션과 참조 카운팅.

참조 카운팅.

  • 객체가 참조될 때마다 참조 횟수(refcount)가 증가합니다.
  • 참조가 없어지면 감소합니다.
  • refcount가 0이 되면, 객체는 자동으로 삭제됩니다.
import sys

a = []
print(sys.getrefcount(a))  # 참조 횟수 확인

순환 참조 문제.

class Node:
    def __init__(self):
        self.ref = self

n = Node()
  • 'n' 객체가 자기 자신을 참조하고 있음 -> 참조 횟수는 0이 되지 않음 -> 메모리 해제 불가.

가비지 컬렉터(GC).

  • 순환 참조를 해결하기 위해 CPython은 'gc' 모듈을 사용합니다.
  • 'gc'는 참조 그래프를 분석하여 순환 참조를 찾아냅니다.
import gc

gc.collect()  # 수동으로 GC 실행

세대별 수집.

  • 파이썬 GC는 객체를 0세대 -> 1세대 -> 2세대로 구분합니다.
  • 오래 살아남은 객체는 수집 빈도를 줄여서 성능을 최적화합니다.

요약.


0개의 댓글