POSIX 스레드 (pthreads): 운영체제 스레드 표준 API

핵심 인사이트 (3줄 요약)

  1. 본질: POSIX 스레드 (pthreads)는 서로 다른 UNIX 계열 운영체제(Linux, macOS, Solaris 등)에서 개발자들이 스레드를 생성하고 동기화할 때, **OS마다 달랐던 난잡한 코드 방식을 하나로 통일시켜 준 C언어 기반의 범용 멀티스레딩 API 표준 규격(IEEE 1003.1c)**이다.
  2. 가치: "한 번 작성하면 어디서든 컴파일된다(Write once, compile anywhere)"는 이식성(Portability)을 멀티코어 프로그래밍에 부여하여, 아파치(Apache) 웹 서버나 MySQL 같은 거대 소프트웨어가 모든 유닉스 환경에서 동일하게 쌩쌩 돌아갈 수 있는 토대를 마련했다.
  3. 융합: pthreads는 그저 '명세서(약속)'일 뿐이며, 그 약속을 밑바탕에서 실제로 구현하는 기술은 OS마다 완전히 다르다. 리눅스는 이 표준을 지키기 위해 내부적으로 clone() 시스템 콜과 NPTL(Native POSIX Thread Library)이라는 1:1 스레드 매핑 아키텍처를 융합하여 세계에서 가장 빠른 pthreads 환경을 완성했다.

Ⅰ. 개요 및 필요성 (Context & Necessity)

  • 개념:

    • POSIX (Portable Operating System Interface): "서로 다른 운영체제라도 이 API 모양만큼은 똑같이 맞추자"라고 정한 IEEE의 유닉스 표준.
    • pthreads (POSIX Threads): 그 POSIX 표준 중에서 스레드의 생성(pthread_create), 종료(pthread_join), 동기화(pthread_mutex_lock)에 관한 규칙만을 모아놓은 서브 스펙이다.
  • 필요성(문제의식):

    • 1990년대, CPU 코어가 여러 개 달린 썬 마이크로시스템즈(Sun) 컴퓨터와 HP 컴퓨터, IBM 컴퓨터가 쏟아져 나왔다.
    • 개발자가 멀티스레드 코드를 짤 때 Sun OS에서는 thr_create()를, HP-UX에서는 cma_thread_create()를 썼다. OS가 바뀔 때마다 스레드 코드를 수천 줄씩 완전히 새로 짜야 하는 지옥(Vendor Lock-in)이 펼쳐졌다.
    • 해결책: "운영체제 회사들아, 니들 내부적으로 스레드를 어떻게 만들든 상관 안 할 테니까, 밖으로 보여주는 함수 이름이랑 매개변수 모양만 pthread_로 똑같이 통일해라!"
  • 💡 비유:

    • 표준화 이전: 한국 전기 콘센트는 220V 둥근 돼지코고, 미국은 110V 납작한 모양, 영국은 세 갈래 모양이라 여행 갈 때마다 어댑터를 수십 개씩 사야 했다.
    • pthreads (표준 API): 전 세계 모든 가전제품 회사가 "앞으로는 무조건 USB-C 타입(pthreads) 하나로만 꼽게 만들자!"라고 대동단결한 것. 개발자는 USB-C 케이블만 있으면 어느 나라(OS) 콘센트에 꼽아도 전기가 들어온다.
  • 등장 배경:

    • 1995년 IEEE에서 POSIX.1c 표준을 제정. 이후 리눅스 진영이 LinuxThreads라는 엉성한 초기 구현체를 거쳐 2003년 커널 2.6부터 IBM/Red Hat이 주도한 NPTL(Native POSIX Thread Library)을 도입하며 pthreads의 완벽한 르네상스가 시작되었다.
  ┌─────────────────────────────────────────────────────────────┐
  │                 pthreads API 추상화 계층(Abstraction Layer) 구조      │
  ├─────────────────────────────────────────────────────────────┤
  │                                                             │
  │   [ 1. 사용자 응용 프로그램 (C/C++ 개발자) ]                        │
  │     - `pthread_create(&thread_id, NULL, worker_func, NULL);`│
  │     (나는 OS가 뭔지 모름. 그냥 이 표준 함수만 부르면 스레드가 생기겠지!)       │
  │                                                             │
  │  ===============( POSIX pthreads API 장벽 )================== │
  │                                                             │
  │   [ 2. 운영체제별 표준 라이브러리 (libc / libpthread) ]             │
  │    ┌─────────────────┐ ┌──────────────────┐ ┌───────────────┐ │
  │    │ Linux (glibc)   │ │ macOS (libSystem)│ │ Solaris (libc)│ │
  │    │ NPTL 구현체 사용   │ │ XNU 커널 구현체 사용 │ │ LWP 구현체 사용  │ │
  │    └────────┬────────┘ └────────┬─────────┘ └───────┬───────┘ │
  │             │                   │                   │         │
  │  ===========│===================│===================│======== │
  │             ▼                   ▼                   ▼         │
  │   [ 3. 운영체제 커널의 실제 시스템 콜 (System Call) ]                 │
  │    Linux: `clone(...)`   macOS: `bsdthread_create(...)`       │
  │    (내부적으로는 완전히 다른 우주가 돌아가며 스레드를 만들어냄)                │
  └─────────────────────────────────────────────────────────────┘

[다이어그램 해설] 이 그림은 아키텍처에서 '추상화(Abstraction)'가 왜 그토록 위대한지 보여주는 완벽한 예시다. 개발자(1번 계층)는 리눅스의 기괴한 clone() 플래그 조작법이나 macOS의 Mach 포트 개념을 단 1도 몰라도 된다. 단지 C언어 헤더 파일 <pthread.h>를 포함(include)하고 표준화된 API만 부르면 끝난다. 그 밑의 지저분하고 OS 종속적인 삽질(2번, 3번 계층)은 GNU C 라이브러리(glibc)를 만드는 커널/시스템 해커들이 수십 년에 걸쳐 알아서 다 번역해 두었다.

  • 📢 섹션 요약 비유: pthreads는 스타벅스의 '빅맥 세트' 같은 겁니다. 한국에서 주문하든 미국에서 주문하든, "빅맥 하나 주세요(pthread_create)"라고 말하면 똑같은 햄버거가 나옵니다. 주방 안에서 한국 소를 잡았는지 호주 소를 잡았는지(커널 차이) 손님은 알 필요가 없습니다.

Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)

pthreads 4대 핵심 기능 그룹

이 표준은 크게 4가지 카테고리로 묶여 있으며, 멀티스레딩의 생로병사를 완벽하게 통제한다.

카테고리핵심 함수 API역할과 특징
스레드 관리 (Management)pthread_create, pthread_join, pthread_detach, pthread_exit스레드를 낳고, 죽이고, 결과값을 받아오거나 아예 고아로 버려버리는(detach) 생명주기 관리.
뮤텍스 (Mutex)pthread_mutex_init, _lock, _unlock가장 기본이 되는 자물쇠. 특정 공유 변수에 동시 접근하는 걸 막아 경쟁 조건(Race Condition)을 차단.
조건 변수 (Condition Variable)pthread_cond_wait, _signal, _broadcast"데이터가 들어올 때까지 기다려!"라고 뮤텍스와 묶어서 수면(Sleep) 상태로 대기하다 알람을 받고 깨는 생산자-소비자 패턴의 뼈대.
스레드 로컬 스토리지 (TLS)pthread_key_create, pthread_setspecific모든 스레드가 전역 변수를 공유하지만, "이 변수만큼은 각 스레드마다 자기만의 복사본을 쓰게 해줘"라고 지정하는 특수 공간(TSD).

리눅스의 혁명적 아키텍처: NPTL (Native POSIX Thread Library)

pthreads는 '규칙'일 뿐이다. 과거 리눅스는 이 규칙을 지키기 위해 LinuxThreads라는 M:N (유저 스레드 여러 개를 커널 스레드 몇 개에 묶는) 방식을 썼다가, 시그널 처리가 꼬여서 성능이 박살 났다. 이를 갈아엎고 나온 21세기 아키텍처가 NPTL이다.

  ┌───────────────────────────────────────────────────────────────────┐
  │                 Linux NPTL 아키텍처 (1:1 매핑의 승리)                │
  ├───────────────────────────────────────────────────────────────────┤
  │                                                                   │
  │   [ 유저 공간 (User Space) ]                                        │
  │   App: `pthread_create()` 호출 1만 번!                              │
  │           │                                                       │
  │   [ NPTL 라이브러리 (glibc) ]                                       │
  │   "어, 스레드 1만 개 만들어달라고? 꼼수 안 부릴게! 1:1로 다 꽂아버려!"          │
  │           │ `clone(CLONE_VM | CLONE_THREAD ...)` 1만 번 무자비하게 발사!│
  │           ▼                                                       │
  │   [ 커널 공간 (Kernel Space) ]                                      │
  │   - 커널 스케줄러(CFS)의 RunQueue에 실제 '커널 태스크(LWP)' 1만 개 생성!     │
  │   - 커널: "이제 이 1만 개의 태스크는 내가 직접 CPU 코어 64개에 분산시킨다!"      │
  │                                                                   │
  │   ▶ NPTL의 기적: 10만 개의 스레드를 띄워도 커널이 2초 만에 다 만들어냄 (O(1)).│
  │                 다중 코어(SMP) 환경에서 극단적인 병렬 성능 폭발!           │
  └───────────────────────────────────────────────────────────────────┘

[다이어그램 해설] NPTL은 "스레드를 유저 스페이스에서 가짜로 묶지 말고, 그냥 무식하게 100% 커널에 1:1로 때려 박아라(1:1 Threading Model)"라는 철학이다. 커널 태스크가 너무 무거웠던 옛날엔 상상도 못 할 짓이었다. 하지만 리눅스는 clone()을 고도화하여 스레드 1개 생성 속도를 1마이크로초로 줄여버렸다(O(1) 스케줄러 도입). NPTL 덕분에 리눅스의 pthreads는 그 어떤 유닉스 운영체제보다 더 빠르고 무식하게 멀티코어를 100% 다 씹어먹는 최강의 괴물로 군림하게 되었다.

  • 📢 섹션 요약 비유: 예전엔 회사(OS)에서 직원 채용(스레드 생성) 절차가 너무 복잡해서, 외주 용역(가짜 유저 스레드)을 섞어 쓰다가 퀄리티가 박살 났습니다. 지금(NPTL)은 채용 절차(clone)를 1초로 간소화시켜버려서, 그냥 필요할 때마다 정규직 1만 명을 즉각 뽑아 64개 부서(코어)에 직접 던져버리는 압도적인 물량전이 가능해졌습니다.

Ⅲ. 융합 비교 및 다각도 분석

Pthreads vs 현대 언어의 스레드 (Java Thread, C++11 std::thread)

"요즘 누가 C언어로 귀찮게 pthread_create를 짜나요?" 맞다. 하지만 그 깊은 뿌리는 100% 이어져 있다.

층위 (Layer)추상화 도구내부 동작 (결국 도달하는 곳)차이점
High-levelJava Thread(), Python threadingJVM/Python 인터프리터가 OS의 네이티브 스레드 API 호출가비지 컬렉션(GC)이나 언어 런타임 제약(GIL)이 섞여 느림
Mid-levelC++11 std::thread, Rust std::threadpthreads API (리눅스 기준)를 100% 그대로 감싼(Wrapping) 껍데기!C++ 객체 지향 문법으로 예쁘게 포장했을 뿐, 속도와 작동 방식은 pthreads와 100% 동일함.
Low-levelPOSIX Pthreads (C언어)OS의 clone(), futex 시스템 콜 직접 호출가장 날것(Raw). 스택 크기, 스케줄링 친화성을 나노 단위로 제어 가능.

과목 융합 관점

  • 운영체제 동기화 (Futex의 융합): Pthreads의 pthread_mutex_lock은 과거엔 락을 쥘 때마다 커널 모드로 진입(시스템 콜)하는 지옥의 오버헤드가 있었다. 이를 혁신한 것이 리눅스의 **Futex (Fast Userspace Mutex)**다. 현재의 pthreads 뮤텍스는 커널에 안 들어가고 유저 스페이스(메모리 변수)에서 CAS 연산으로 락을 슬쩍 잡아본다. 누군가 이미 락을 쥐고 있어서 쟁탈전이 났을 때만 어쩔 수 없이 커널(Futex)로 들어가서 잠을 잔다(Sleep). 유저의 가벼움과 커널의 대기 큐를 융합한 세기의 걸작이다.

  • 실시간 시스템 (SCHED_FIFO 연동): Pthreads 표준에는 "이 스레드는 무조건 빨리 끝내라"고 강제하는 실시간 스케줄링 옵션이 포함되어 있다. 개발자는 pthread_attr_setschedpolicy API를 통해 스레드를 만들 때 일반적인 공평 스케줄러(SCHED_OTHER)를 버리고, 한 번 잡으면 안 놓는 강제 실시간 스케줄러(SCHED_FIFO)의 권한을 스레드에 박아 넣을 수 있다. (단, 이 기능은 OS 커널이 실시간(RT)을 지원해야만 먹힌다).

  • 📢 섹션 요약 비유: Pthreads는 자동차의 '엔진(커널)'과 운전자(앱)를 연결하는 '기어 스틱과 핸들'입니다. C++이나 Java는 그 기어 스틱 위에 부드러운 가죽 커버를 씌우고 열선을 깐 것일 뿐, 결국 바퀴를 굴리려면 반드시 Pthreads라는 쇳덩어리 기어를 거쳐야만 합니다.


Ⅳ. 실무 적용 및 기술사적 판단

실무 시나리오 및 운영 안티패턴

  1. 시나리오 — pthreads 생성 후 좀비 스레드(메모리 릭) 폭발 사태: 주니어 C 개발자가 수천 개의 네트워크 소켓을 받기 위해 while 루프 안에서 pthread_create로 스레드를 무한히 만들었다. 스레드 안에서 자기 일을 다 끝내고 return으로 정상 종료했는데도, 서버의 램(RAM)이 1분 만에 꽉 차서 OOM(Out of Memory)으로 서버가 뻗었다.

    • 원인 분석: 스레드도 프로세스와 똑같이 종료 후 좀비(Zombie) 상태가 된다! 부모 스레드가 pthread_join()을 호출해 자식의 종료 결과값을 읽어주지 않으면, 자식이 쓰던 수 메가바이트의 스택(Stack) 메모리 찌꺼기가 커널에 영원히 남아있는다.
    • 아키텍트 판단 (Detach 옵션 강제): 만약 자식이 끝나는 걸 기다려줄(join) 필요가 없는 독립적인 워커(Worker) 스레드라면, 생성할 때부터 "너는 죽으면 나한테 보고하지 말고 니 몸뚱이는 알아서 소각해라"라고 pthread_detach() 함수를 호출하거나, 아예 속성에 PTHREAD_CREATE_DETACHED를 걸고 스폰(Spawn)시켜야 좀비 메모리 릭(Leak)을 완벽히 차단할 수 있다.
  2. 시나리오 — 우선순위 역전 (Priority Inversion) 방지를 위한 Mutex 튜닝: 라즈베리파이(리눅스)로 드론 제어 코드를 pthreads로 짰다. 카메라 영상 처리(Low 순위)가 쥐고 있는 뮤텍스 락을, 자세 제어 모터 스레드(High 순위)가 기다리다가 드론이 뒤집혀 추락했다.

    • 원인 분석: 기본 pthread_mutex_t는 우선순위 역전을 방어하지 못하는 깡통 자물쇠다.
    • 아키텍트 판단 (PI Mutex 속성 셋팅): 이기종 워크로드가 섞인 실시간 시스템에서는 뮤텍스 하나도 허투루 만들면 안 된다. 초기화(init) 직전에 뮤텍스 속성 객체에 **pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)**를 반드시 걸어주어야 한다. 이 마법의 한 줄이 들어가야만, 하위 스레드가 락을 쥔 상태에서 상위 스레드가 대기할 때 즉각 권력을 상속받아(Priority Inheritance) 드론 추락을 막는 구조적 안전망이 발동된다.
  ┌───────────────────────────────────────────────────────────────────┐
  │                 안전한 Pthreads 멀티스레딩 아키텍처 결정 트리             │
  ├───────────────────────────────────────────────────────────────────┤
  │                                                                   │
  │   [ 대량의 트래픽을 처리하는 동시성 엔진을 설계한다 ]                       │
  │                │                                                  │
  │                ▼                                                  │
  │      사용자 요청이 들어올 때마다 `pthread_create`로 스레드를 새로 낳을 건가?  │
  │          ├─ 예 ─────▶ 🚨 [ 치명적 안티패턴! (Thread Per Request) ]     │
  │          │             (스폰 오버헤드와 C10K 메모리 폭발로 서버 100% 뻗음)  │
  │          └─ 아니오                                                │
  │                │                                                  │
  │                ▼ [ 아키텍트의 정답지 ]                                 │
  │      [ Thread Pool (스레드 풀) 패턴 적용 ]                             │
  │      1. 서버 시작 시, 물리 코어 개수(ex: 16개)만큼만 미리 스레드를 생성.      │
  │      2. 들어오는 요청은 락프리 큐(Queue)에 잔뜩 밀어 넣음.                  │
  │      3. 16개의 스레드가 무한 루프를 돌며 큐에서 하나씩 빼서(Pop) 처리함.      │
  │      ▶ 결과: 스레드 생성/파괴 오버헤드 0초! 메모리 OOM 원천 방어!          │
  └───────────────────────────────────────────────────────────────────┘

[다이어그램 해설] pthreads를 배웠다고 신나서 곳곳에 create를 남발하는 건 총을 난사하는 짓이다. 리눅스 스레드 생성(NPTL)이 아무리 빠르다 한들(1µs), 초당 10만 건이 들어오는 백엔드에서 10만 번을 만들고 부수면 CPU는 문맥 교환의 지옥에 빠진다. 고성능 아키텍처의 철칙은 "스레드는 서버 부팅 시점에 CPU 코어 수에 맞춰 딱 한 번만 낳아두고(Thread Pool), 평생 죽이지 말고 재활용하며 일감(Task Queue)만 던져주어라"다. 이것이 Nginx, Redis, 게임 서버의 공통된 바이블이다.

안티패턴

  • 스레드 취소(pthread_cancel)의 폭력적 사용: 어떤 스레드가 무한 루프에 빠진 것 같다고 밖에서 메인 스레드가 pthread_cancel(thread_id)를 날려 강제로 죽여버리는 짓. 그 스레드가 만약 malloc으로 메모리를 잡았거나 mutex_lock을 꽉 쥐고 있는 상태에서 모가지가 잘리면? 락은 영원히 풀리지 않아 서버 전체가 데드락(Deadlock)에 빠진다. 스레드 종료는 절대 타살(Cancel)하면 안 되며, 전역 플래그(is_running = false)를 세팅하여 스레드 본인이 확인하고 락을 다 푼 뒤 "자살(Return)"하게 만들어야 하는 우아한 종료(Graceful Shutdown)가 필수다.

  • 📢 섹션 요약 비유: 방 안에서 일하는 직원(스레드)이 맘에 안 든다고 밖에서 수류탄(Cancel)을 까서 던지면, 직원이 들고 있던 회사의 중요 금고 열쇠(Mutex)까지 박살 나서 회사 전체가 멈춥니다. 반드시 인터폰(Flag)으로 "이제 퇴근하세요"라고 알려줘서, 직원이 열쇠를 책상에 예쁘게 내려놓고 자기 발로 걸어 나오게(Graceful Exit) 해야 합니다.


Ⅴ. 기대효과 및 결론

정량/정성 기대효과

구분OS별 파편화된 스레드 API 사용 (과거)POSIX Pthreads 표준 적용 시개선 효과
정량 (코드 이식 비용)OS 바뀔 때마다 동기화 로직 100% 재작성소스 코드 1비트 수정 없이 100% 재컴파일만 수행크로스 플랫폼(Linux, Mac) 소프트웨어 개발 공수 극단적 삭감
정성 (아키텍처 통합)커널 스레드와 유저 스레드의 혼돈 관리clone 기반 NPTL의 1:1 완벽 매핑 정착멀티코어(SMP) 하드웨어의 병렬 연산 성능 100% 견인
정성 (생태계 확장)벤더 종속적 락(Lock) 설계로 버그 남발Mutex, CV 등 증명된 표준 동기화 모델 확립C/C++ 기반의 지구상 모든 고성능 서버 프레임워크의 탄생 토대

미래 전망

  • 스레드를 넘어 코루틴(Coroutine)의 시대로: Pthreads가 20년을 지배했지만, "스레드 1개당 스택 메모리 8MB"라는 육중한 덩치는 컨테이너 시대의 C10M(동접 1천만) 문제를 견디지 못했다. 현재는 C++20, Go, Rust 언어 차원에서 커널(Pthreads)을 아예 거치지 않고 사용자 공간(User Space)에서 수백 바이트의 스택만으로 문맥을 교환하는 초경량 코루틴(Goroutine, Async/Await) 아키텍처가 pthreads의 자리를 맹렬히 밀어내고 있다.
  • 분산 Pthreads (가상화 통합): 로컬 장비를 넘어, 클러스터로 묶인 여러 대의 머신 위에서 동작하는 '분산 공유 메모리(DSM)' 시스템을 위해, Pthreads API를 똑같이 호출하지만 실제로는 네트워크(RDMA)를 타고 다른 서버의 락(Lock)을 잡는 거대한 분산 스레드 아키텍처 연구가 HPC(슈퍼컴퓨터) 분야의 최전선이다.

참고 표준

  • IEEE Std 1003.1c-1995 (POSIX.1c): 우리가 흔히 말하는 pthreads의 모든 함수와 동작 조건, 반환 에러 코드를 전 세계 공통으로 규정한 인류 스레드 역사의 헌법.
  • C11 / C++11 <thread>: pthreads의 C언어 포인터 남발과 메모리 안전성 문제를 해결하기 위해, 최신 C++ 컴파일러가 pthreads를 객체 지향 템플릿(RAII)으로 안전하게 감싸서 제정한 현대적 언어 표준.

POSIX 스레드 (pthreads) API는 "소프트웨어가 특정 하드웨어나 벤더(운영체제)의 노예가 되지 않겠다"는 해커들의 가장 찬란한 독립선언서다. pthreads라는 만국 공통의 언어가 있었기에, 전 세계의 수많은 오픈소스 개발자들이 운영체제의 파편화된 벽을 넘어 '동시성(Concurrency)'이라는 하나의 거대한 우주탑을 쌓아 올릴 수 있었다. 비록 지금은 더 가볍고 화려한 코루틴(Coroutine)과 이벤트 루프에 왕좌를 내어주고 있지만, 여전히 그 모든 첨단 기술들의 맨 밑바닥 쇳덩어리 기어 박스 속에서는 pthreads의 심장(NPTL)이 거칠게 뛰고 있다.

  • 📢 섹션 요약 비유: Pthreads는 전 세계의 모든 철로(OS) 간격을 똑같은 너비로 통일시킨 '표준 궤도' 규격과 같습니다. 이 규격 덕분에 한국에서 만든 기차(소프트웨어)가 유럽과 시베리아(서로 다른 OS)를 부품 교체 하나 없이 멈추지 않고 미친 듯이 질주할 수 있는 인프라 대통합의 기적을 이뤘습니다.

📌 관련 개념 맵 (Knowledge Graph)

개념 명칭관계 및 시너지 설명
clone() 시스템 콜리눅스가 Pthreads의 pthread_create()라는 표준을 만족시키기 위해, 밑단에서 메모리 공유 플래그를 떡칠해서 호출하는 진짜 창조자다.
NPTL (Native POSIX Thread Lib)옛날 리눅스의 엉성한 스레드 구조를 박살 내고, 1:1 커널 태스크 맵핑을 구현하여 리눅스 pthreads를 세계 최고 속도로 만든 전설의 아키텍처다.
Mutex / 조건 변수(Cond)스레드들이 자원을 두고 피 터지게 싸울 때, 질서를 맞추고 "다 되면 깨워줘"라는 핑퐁을 가능하게 하는 Pthreads의 양대 동기화 무기다.
좀비 프로세스 (메모리 릭)스레드도 죽고 나서 누군가 join으로 치워주지 않으면 스택 메모리가 썩어버리는 좀비가 되므로, 고아로 만들려면 detach를 꼭 쳐야 한다.
Thread Pool (스레드 풀)pthreads 생성이 아무리 빨라도 10만 번 부르면 서버가 터지므로, 스레드 10개만 만들어놓고 일감을 돌려쓰는 고성능 백엔드의 기본 패턴이다.

👶 어린이를 위한 3줄 비유 설명

  1. 옛날에는 레고(A운영체제)에서 만든 장난감 바퀴는 옥스포드(B운영체제) 장난감에 끼울 수가 없어서 장난감을 매번 새로 사야 했어요.
  2. 그래서 장난감 회사들이 모여서 "우리 바퀴 꼽는 구멍 크기(pthreads API)는 전 세계 무조건 똑같이 통일하자!"라고 약속(표준)을 했어요.
  3. 덕분에 개발자 아저씨들은 똑같은 바퀴(코드) 하나만 잘 만들어두면, 지구상 어떤 컴퓨터 장난감에 꽂아도 완벽하게 굴러가는 마법 같은 세상을 만들었답니다!