Process는 독립적인 memory 공간과 resource를 할당받는 실행 중인 program 인스턴스입니다. Thread는 process 안에서 실행되는 작업 흐름입니다. 같은 process의 thread들은 code, heap 같은 memory를 공유하지만 각자 stack과 register 상태를 가질 수 있습니다.
process끼리는 기본적으로 memory가 분리되어 안정성이 높고, thread는 memory를 공유하기 때문에 통신이 빠르지만 race condition 같은 동시성 문제가 생길 수 있습니다. 그래서 안정성과 비용, 공유의 편의성 사이에서 차이가 납니다.
꼬리질문
조금 더 깊게 물어본다면
답변 뒤에 이어질 수 있는 질문들을 하나씩 열어볼 수 있어요.
process와 thread는 memory를 어떻게 나눠 쓰나요?
process는 독립적인 address space를 가집니다. 다른 process의 memory에 직접 접근할 수 없습니다. 같은 process의 thread들은 heap 같은 memory 영역을 공유합니다.
하지만 thread마다 call stack은 따로 가져야 각자의 함수 호출 흐름을 유지할 수 있습니다.
thread가 빠른데 왜 process를 쓰나요?
격리와 안정성 때문입니다. process를 분리하면 한 process의 crash나 memory corruption이 다른 process에 직접 영향을 덜 줄 수 있습니다.
보안이나 안정성이 중요한 구조에서는 비용이 더 들더라도 process 격리를 선택할 수 있습니다.
race condition은 왜 thread에서 자주 문제 되나요?
여러 thread가 같은 공유 데이터를 동시에 읽고 쓰기 때문입니다. 실행 순서에 따라 결과가 달라질 수 있습니다.
이를 막기 위해 mutex, semaphore, lock-free 구조 같은 동기화 기법을 사용합니다.
thread가 메모리를 공유한다는 점은 어떤 버그로 이어질 수 있나요?
여러 thread가 같은 값을 동시에 읽고 쓰면 실행 순서에 따라 결과가 달라질 수 있습니다. 예를 들어 두 thread가 같은 counter를 증가시키는데 읽기와 쓰기가 엇갈리면 증가 횟수가 일부 사라질 수 있습니다.
그래서 공유 데이터를 다룰 때는 lock, atomic 연산, message passing처럼 접근 순서를 제어하는 방법이 필요합니다.
부가 설명
브라우저를 떠올리면 이해하기 쉽습니다. 탭이나 renderer process를 분리하면 한 페이지 문제가 전체 브라우저를 덜 흔들게 만들 수 있습니다. 반면 같은 process 안의 여러 thread는 rendering, network, background 작업처럼 역할을 나눠 동시에 진행할 수 있습니다.
단순히 “process는 program, thread는 function”처럼 말하면 부족합니다. 핵심은 resource 소유와 memory 공유 범위입니다.
process 간 통신은 IPC가 필요하고 비용이 상대적으로 큽니다. thread 간 통신은 같은 address space를 공유하므로 더 쉽지만, 동시에 같은 데이터를 바꾸면 문제가 생길 수 있습니다.
Context switching 비용도 차이가 납니다. process context switching은 address space 전환까지 포함될 수 있어 thread보다 무거운 경우가 많습니다.
한 줄 정리
process는 독립적인 memory를 가진 실행 단위이고, thread는 process 안에서 memory를 공유하며 실행되는 흐름입니다.