ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] GIL — 파이썬은 왜 멀티코어를 막아놓았을까
    IT 2026. 1. 23. 11:16

    파이썬으로 어느 정도 개발을 하다 보면, 언젠가 반드시 이 질문을 만나게 됩니다.

    “왜 파이썬은 멀티스레드를 써도 CPU를 하나만 쓰는 것 같지?”

    그리고 곧이어 등장하는 단어가 바로 GIL(Global Interpreter Lock) 입니다. 이 글에서는 GIL을 단순히 ‘파이썬의 한계’로 설명하지 않고, 왜 이런 선택이 나왔는지, 그리고 우리가 어떻게 받아들이고 활용해야 하는지를 중심으로 풀어보려 합니다.


    GIL이란 무엇인가

    GIL은 말 그대로 전역 인터프리터 락입니다.

    CPython 인터프리터는 내부적으로 한 시점에 하나의 스레드만이 바이트코드를 실행할 수 있도록 설계되어 있습니다. 이 제약을 강제하는 장치가 바로 GIL입니다.

    즉,

    • 멀티스레드를 만들 수는 있지만
    • 동시에 파이썬 코드를 실행할 수는 없다

    라는 구조입니다.


    그럼 멀티스레드는 왜 있나?

    이 지점에서 많은 사람들이 혼란을 느낍니다.

    “어차피 동시에 실행 못 하는데, 스레드는 왜 존재하지?”

    답은 I/O 작업에 있습니다.

    • 네트워크 요청
    • 파일 읽기
    • 데이터베이스 대기

    이런 작업들은 CPU를 쓰지 않고 대기 상태에 들어갑니다. 이때 GIL은 다른 스레드에게 넘어갈 수 있고, 결과적으로 멀티스레드는 I/O 중심 작업에서는 충분히 효과적입니다.


    왜 이런 구조를 선택했을까

    GIL은 우연히 생긴 것이 아닙니다. 매우 현실적인 선택의 결과입니다.

    1. 메모리 모델을 단순하게 유지하기 위해

    CPython의 객체는 참조 카운트(reference count) 방식으로 메모리를 관리합니다.

    obj.refcount += 1
    obj.refcount -= 1

    이 연산이 여러 스레드에서 동시에 일어나면 어떻게 될까요? 모든 객체 접근마다 락이 필요해집니다.

    GIL은 이 복잡함을 통째로 제거합니다.

    • 객체 접근은 안전해지고
    • 인터프리터 구현은 단순해지며
    • C 확장 모듈도 훨씬 작성하기 쉬워집니다

    2. 성능은 생각보다 나쁘지 않았다

    GIL은 직관적으로는 느릴 것 같지만, 실제로는 많은 경우 싱글 스레드 성능을 희생하지 않습니다.

    • 락 경쟁이 없다
    • 캐시 친화적이다
    • 단일 스레드 코드가 매우 빠르다

    이 때문에 “GIL을 없애면 무조건 빨라진다”는 생각은 사실과 거리가 있습니다.


    GIL과 CPU-bound 작업

    문제는 CPU 연산이 많은 작업입니다.

    def heavy():
        total = 0
        for i in range(10**7):
            total += i
        return total

    이런 작업을 멀티스레드로 나눠도, 실제로는 한 스레드씩 번갈아 실행될 뿐입니다. 결과적으로 속도 향상은 거의 없습니다.

    이 지점에서 파이썬 개발자들은 다른 선택지를 사용합니다.


    파이썬에서의 현실적인 대응 전략

    1. 멀티프로세싱

    프로세스는 GIL을 공유하지 않습니다.

    from multiprocessing import Process
    • 각 프로세스는 독립된 GIL을 가진다
    • 실제 멀티코어 사용 가능
    • 대신 IPC 비용이 발생

    2. C 확장 / NumPy

    많은 고성능 라이브러리는 GIL을 해제한 상태에서 C 코드로 연산을 수행합니다.

    • NumPy
    • Pandas 내부 연산
    • 머신러닝 라이브러리

    그래서 파이썬이 느리다는 인식과 달리, 실제 계산은 매우 빠른 경우가 많습니다.


    3. 비동기 프로그래밍

    앞서 이야기한 코루틴, 이벤트 루프는 GIL을 피하려는 시도라기보다, 대기 시간을 효율적으로 쓰기 위한 전략입니다.

    • CPU를 나누는 것이 아니라
    • 기다리는 시간을 숨긴다

    GIL은 파이썬의 결함일까

    이 질문에 대한 답은 간단하지 않습니다.

    GIL은 분명 제약입니다. 하지만 동시에:

    • 파이썬을 지금의 파이썬답게 만든 핵심 요소이기도 합니다
    • 방대한 C 확장 생태계를 가능하게 했고
    • 언어의 단순함과 안정성을 지켜왔습니다

    마무리하며

    GIL을 이해할 때 가장 중요한 관점은 이것입니다.

    “파이썬은 병렬 계산 언어가 아니라, 생산성 중심 언어다”

    그래서 파이썬은

    • CPU-bound → 멀티프로세스, C 확장
    • I/O-bound → 멀티스레드, 코루틴

    이라는 전략을 자연스럽게 선택하게 됩니다.

    GIL은 피해야 할 괴물이 아니라, 파이썬이라는 언어의 성격을 가장 잘 드러내는 장치라고 볼 수 있습니다.

     
Designed by Tistory.