프로세스와 스레드의 차이점과 컨텍스트 스위칭

프로세스(Process)와 스레드(Thread) 개념

프로세스(Process)

프로세스는 실행 중인 프로그램의 인스턴스로, 운영체제로부터 시스템 자원을 할당받아 독립적으로 실행되는 작업 단위입니다.

주요 특징:

  • 독립된 메모리 공간 소유 (Code, Data, Heap, Stack)
  • 다른 프로세스와 완전히 격리됨
  • 프로세스 간 통신을 위해서는 IPC(Inter-Process Communication) 필요
  • 생성과 종료에 많은 오버헤드 발생

스레드(Thread)

스레드는 프로세스 내에서 실행되는 실행 흐름의 단위로, 프로세스의 자원을 공유하면서 독립적으로 실행됩니다.

주요 특징:

  • 같은 프로세스 내의 스레드들은 메모리 공간 공유 (Code, Data, Heap 영역)
  • 각 스레드는 독립적인 Stack과 PC(Program Counter) 보유
  • 스레드 간 데이터 공유가 쉬움
  • 생성과 전환에 상대적으로 적은 오버헤드

메모리 구조 비교

프로세스 메모리 구조

프로세스 A          프로세스 B
┌──────────┐       ┌──────────┐
│   Stack  │       │   Stack  │
├──────────┤       ├──────────┤
│   Heap   │       │   Heap   │
├──────────┤       ├──────────┤
│   Data   │       │   Data   │
├──────────┤       ├──────────┤
│   Code   │       │   Code   │
└──────────┘       └──────────┘
   독립적            독립적

스레드 메모리 구조

       하나의 프로세스
┌─────────────────────────────┐
│  Thread1   Thread2  Thread3 │
│  Stack     Stack    Stack   │
├─────────────────────────────┤
│        공유 Heap            │
├─────────────────────────────┤
│        공유 Data            │
├─────────────────────────────┤
│        공유 Code            │
└─────────────────────────────┘

컨텍스트 스위칭(Context Switching)

컨텍스트 스위칭은 CPU가 한 작업에서 다른 작업으로 전환할 때 발생하는 과정입니다.

프로세스 컨텍스트 스위칭

과정:

  1. 현재 실행 중인 프로세스의 상태를 PCB(Process Control Block)에 저장
  2. 새로 실행할 프로세스의 PCB에서 상태 정보를 로드
  3. 메모리 맵, 페이지 테이블 전환
  4. 캐시 플러시 (Cache Flush) 발생

저장되는 정보:

  • CPU 레지스터 값들
  • 프로그램 카운터(PC)
  • 스택 포인터
  • 메모리 관리 정보 (페이지 테이블 등)
  • 프로세스 상태 정보

오버헤드가 큰 이유:

  • 메모리 맵 전환으로 인한 TLB(Translation Lookaside Buffer) 플러시
  • CPU 캐시 무효화
  • 페이지 테이블 전환

스레드 컨텍스트 스위칭

과정:

  1. 현재 스레드의 레지스터 상태를 TCB(Thread Control Block)에 저장
  2. 새로운 스레드의 레지스터 상태를 로드
  3. 스택 포인터 전환

저장되는 정보:

  • CPU 레지스터 값들
  • 프로그램 카운터(PC)
  • 스택 포인터
  • 스레드별 로컬 데이터

오버헤드가 적은 이유:

  • 메모리 맵 전환 불필요 (같은 프로세스 내)
  • 캐시 플러시가 발생하지 않음
  • 페이지 테이블 공유

성능과 오버헤드 비교

생성/종료 비용

  • 프로세스: 높음 (메모리 할당, 페이지 테이블 생성 등)
  • 스레드: 낮음 (스택 영역만 추가 할당)

컨텍스트 스위칭 비용

  • 프로세스: 높음 (수십 마이크로초)
  • 스레드: 낮음 (수 마이크로초)

메모리 사용량

  • 프로세스: 높음 (독립적인 메모리 공간)
  • 스레드: 낮음 (메모리 공간 공유)

동기화와 통신

프로세스 간 통신 (IPC)

프로세스는 독립적인 메모리 공간으로 인해 특별한 통신 방법이 필요합니다.

IPC 방법들:

  • 파이프(Pipe): 부모-자식 프로세스 간 통신
  • 공유 메모리(Shared Memory): 메모리 영역을 공유하여 통신
  • 메시지 큐(Message Queue): 메시지 기반 통신
  • 소켓(Socket): 네트워크를 통한 통신

스레드 간 통신

스레드는 메모리를 공유하므로 통신이 간단하지만, 동기화 문제가 발생할 수 있습니다.

동기화 방법들:

  • 뮤텍스(Mutex): 상호 배제를 위한 락
  • 세마포어(Semaphore): 리소스 접근 제한
  • 조건 변수(Condition Variable): 특정 조건 대기
  • 스핀락(Spinlock): 바쁜 대기 방식의 락

언제 무엇을 사용할까?

프로세스를 사용하는 경우

  • 안정성이 중요한 경우: 한 프로세스 오류가 다른 프로세스에 영향을 주지 않음
  • 보안이 중요한 경우: 프로세스 간 완전한 격리
  • 독립적인 작업: 서로 다른 애플리케이션 실행
  • 예시: 웹 브라우저 탭, 멀티프로세싱 웹 서버

스레드를 사용하는 경우

  • 성능이 중요한 경우: 빠른 생성/전환, 적은 메모리 사용
  • 데이터 공유가 필요한 경우: 같은 데이터를 여러 작업에서 처리
  • 응답성이 중요한 경우: UI 프로그램에서 백그라운드 작업
  • 예시: 웹 서버의 요청 처리, 게임의 렌더링과 로직 분리

실제 시스템에서의 활용

웹 서버 아키텍처

  • Apache 전통 모델: 프로세스 기반 (안정성 우선)
  • Nginx: 이벤트 기반 + 적은 수의 워커 프로세스
  • Node.js: 단일 스레드 + 이벤트 루프

브라우저 아키텍처

  • Chrome: 프로세스 격리 (탭마다 별도 프로세스)
  • 렌더링: 메인 스레드 + 워커 스레드 조합

참고 자료

마무리

프로세스와 스레드는 각각 고유한 장단점을 가지고 있으며, 시스템의 요구사항에 따라 적절히 선택해야 합니다. 안정성과 격리가 중요하다면 프로세스를, 성능과 효율성이 중요하다면 스레드를 고려해보세요. 현대의 많은 시스템들은 두 방식을 적절히 조합하여 사용하고 있습니다.