Blog
Anki
Python

Python 인터프리터 면접 질문

CPython과 PyPy의 차이점에 대해 설명해주세요

꼬리 질문
  • GIL(Global Interpreter Lock)이 무엇이고 왜 필요한가요?
  • PyPy가 CPython보다 빠른 이유는 무엇인가요?
  • Reference Counting과 Mark-and-Sweep GC의 차이점은 무엇인가요?

답변 보기

✅ CPython과 PyPy는 Python 언어의 서로 다른 구현체입니다.

  • CPython
    • Python Software Foundation에서 개발한 공식 표준 구현체
    • C 언어로 작성됨
    • Reference Counting + Mark-and-Sweep 방식의 메모리 관리
    • GIL(Global Interpreter Lock) 사용으로 한 번에 하나의 스레드만 Python 바이트코드 실행
    • C 확장 모듈과의 뛰어난 호환성 (NumPy, Pandas 등)
  • PyPy
    • RPython으로 작성된 JIT 컴파일 지원 구현체
    • incminimark GC (점진적 세대별 가비지 컬렉션) 사용
    • 순수 Python 코드에서 CPython보다 5-10배 빠른 성능
    • C 확장 모듈 호환성 제한적
  • 꼬리질문: GIL(Global Interpreter Lock)이 무엇이고 왜 필요한가요?
    • GIL은 한 번에 하나의 스레드만 Python 바이트코드를 실행할 수 있도록 하는 뮤텍스(mutex)입니다
    • CPython의 Reference Counting이 Thread-Safe하지 않기 때문에 필요
    • CPU 집약적 작업에서 멀티스레딩 성능 제한 ⚠️
    • I/O 집약적 작업에서는 영향 적음 (I/O 대기 시 GIL 해제)
  • 꼬리질문: PyPy가 CPython보다 빠른 이유는 무엇인가요?
    • JIT(Just-In-Time) 컴파일러 내장
    • 실행 중 Hot Spot(자주 실행되는 코드)을 감지하여 기계어로 컴파일
    • 최적화된 코드를 메모리에 캐싱하여 재사용
    • 긴 실행 시간의 애플리케이션에서 특히 효과적 🚀
  • 꼬리질문: Reference Counting과 Mark-and-Sweep GC의 차이점은 무엇인가요?
    • Reference Counting (CPython)
      • 각 객체가 참조 카운트를 유지
      • 카운트가 0이 되면 즉시 메모리 해제
      • 즉시 메모리 해제로 예측 가능한 메모리 관리 ✅
      • 순환 참조 문제 발생 가능 ❌
    • Mark-and-Sweep GC (PyPy)
      • 주기적으로 실행되는 가비지 컬렉션
      • 도달 가능한 객체를 마킹하고 나머지 제거
      • 순환 참조 문제 자동 해결 ✅
      • GC 실행 시점까지 메모리 유지 ❌

Python의 메모리 관리 방식에 대해 설명해주세요

꼬리 질문
  • 순환 참조 문제란 무엇이고 어떻게 해결하나요?
  • Python 3.13의 GIL 제거 실험에 대해 알고 있나요?

답변 보기

✅ Python의 메모리 관리는 구현체에 따라 다르며, CPython의 경우 Reference Counting이 기본입니다.

  • CPython의 메모리 관리
    • Reference Counting으로 즉시 메모리 해제
    • 객체 생성 시 참조 카운트 1로 시작
    • 참조 추가/제거 시 카운트 증감
    • 카운트가 0이 되면 즉시 메모리 해제 🗑️
    • 순환 참조 해결을 위한 별도의 Mark-and-Sweep GC 존재
  • 메모리 관리의 장단점
    • 장점: 즉시 메모리 해제, 예측 가능한 동작, Deterministic Destruction
    • 단점: 순환 참조 문제, Thread Safety 문제(GIL로 해결)
  • 꼬리질문: 순환 참조 문제란 무엇이고 어떻게 해결하나요?
    • 순환 참조는 두 개 이상의 객체가 서로를 참조하는 상황
    • Reference Counting만으로는 카운트가 0이 되지 않아 메모리 누수 발생
    • CPython은 별도의 Mark-and-Sweep GC를 주기적으로 실행하여 해결
    • gc 모듈로 수동 제어 가능
  • 꼬리질문: Python 3.13의 GIL 제거 실험에 대해 알고 있나요?
    • Python 3.13부터 실험적으로 GIL 없는 빌드 제공 (free-threading)
    • ./configure --disable-gil로 빌드 가능
    • Biased Reference Counting 도입
      • 객체를 주로 접근하는 스레드에 "편향"
      • 소유 스레드는 non-atomic 연산 사용
      • 다른 스레드는 atomic 연산 필요
    • 멀티코어 활용 개선 기대 🔓

Python 인터프리터를 선택할 때 고려해야 할 점은 무엇인가요?

꼬리 질문
  • CPU 집약적 작업과 I/O 집약적 작업에서 어떤 차이가 있나요?
  • C 확장 모듈을 사용해야 한다면 어떤 인터프리터를 선택해야 하나요?

답변 보기

✅ Python 인터프리터 선택은 프로젝트의 요구사항과 제약조건을 고려해야 합니다.

  • CPython을 선택해야 하는 경우
    • C 확장 모듈 사용이 필수적인 경우 (NumPy, Pandas, TensorFlow 등) 📊
    • 메모리 사용량이 중요한 환경
    • 짧은 실행 시간의 스크립트
    • 안정성과 호환성이 최우선
    • 대부분의 Python 라이브러리 생태계 활용 필요
  • PyPy를 선택해야 하는 경우
    • 순수 Python 코드 위주의 CPU 집약적 작업
    • 긴 실행 시간의 애플리케이션 (JIT 최적화 효과)
    • 성능이 최우선이고 생태계 제약 감수 가능
    • 웹 서버나 장시간 실행되는 서비스
  • 꼬리질문: CPU 집약적 작업과 I/O 집약적 작업에서 어떤 차이가 있나요?
    • CPU 집약적 작업
      • PyPy가 JIT 컴파일로 5-10배 성능 향상 가능 🚀
      • CPython은 GIL로 인해 멀티스레딩 효과 제한
      • 순수 Python 연산이 많은 경우 PyPy 유리
    • I/O 집약적 작업
      • GIL이 I/O 대기 시 해제되어 CPython도 효과적
      • 성능 차이가 크지 않음
      • C 확장 모듈 활용 가능한 CPython이 유리할 수 있음
  • 꼬리질문: C 확장 모듈을 사용해야 한다면 어떤 인터프리터를 선택해야 하나요?
    • CPython 선택이 필수적 ✅
    • PyPy는 C 확장 모듈 호환성이 제한적
    • NumPy, Pandas, scikit-learn 등 데이터 과학 라이브러리는 CPython 권장
    • PyPy는 cffi를 통한 제한적 C 인터페이스만 지원

JIT 컴파일이란 무엇이고 Python에서 어떻게 동작하나요?

꼬리 질문
  • Hot Spot이란 무엇인가요?
  • JIT 컴파일의 장단점은 무엇인가요?

답변 보기

✅ JIT(Just-In-Time) 컴파일은 실행 시점에 코드를 기계어로 변환하는 최적화 기법입니다.

  • JIT 컴파일 동작 과정 (PyPy)
    • 인터프리터 모드로 프로그램 시작
    • 코드 실행 빈도 모니터링
    • Hot Spot(자주 실행되는 코드) 감지
    • 해당 부분을 기계어로 컴파일하여 캐싱
    • 이후 실행 시 컴파일된 코드 사용 ⚡
  • Python에서의 JIT 구현
    • PyPy: 내장 JIT 컴파일러 (가장 성숙한 구현)
    • Numba: NumPy 연산 JIT 컴파일
    • JAX: XLA를 통한 JIT 컴파일
  • 꼬리질문: Hot Spot이란 무엇인가요?
    • 프로그램에서 자주 실행되는 코드 부분
    • 일반적으로 전체 실행 시간의 80%는 코드의 20%에서 소비 (파레토 법칙)
    • 루프, 재귀 함수, 자주 호출되는 함수가 대표적
    • JIT 컴파일러는 이런 부분을 우선적으로 최적화 🎯
  • 꼬리질문: JIT 컴파일의 장단점은 무엇인가요?
    • 장점
      • 실행 중 최적화로 높은 성능
      • 플랫폼별 최적화 가능
      • 인터프리터의 유연성 유지
    • 단점
      • 초기 실행 속도 느림 (워밍업 필요)
      • 메모리 사용량 증가 (컴파일된 코드 캐싱)
      • 짧은 스크립트에서는 오버헤드
      • 디버깅 복잡도 증가