비슷하지만 전혀 다른… 병행성(동시성)과 병렬성

컴퓨터 과학을 공부하다 보면, 겉으로는 매우 비슷해 보이지만 실제로는 근본적으로 다른 개념이 있다. 그 대표적인 예가 바로 ‘병행성(Concurrency)’과 ‘병렬성(Parallelism)’이다. 많은 사람들이 이 둘을 혼동하거나 심지어 같은 의미로 사용하기도 하지만, 둘은 엄연히 구분되는 용어이며, 아마도 컴퓨터 과학에서 가장 헷갈리는 개념 중 하나일 것이다.

영어로 ‘Concurrency’와 ‘Parallel’은 모두 ‘동시에’라는 일상적인 단어로 번역되지만, 컴퓨터 과학에서는 그 의미가 훨씬 엄밀하다. 두 개념은 모두 여러 작업을 동시에 처리한다는 점에서 공통점을 가지지만, ‘동시에’를 실현하는 방식이 완전히 다르다. 핵심 차이점은 바로 프로세서(또는 코어)의 개수에 있다.

병행성(Concurrency)은 하나의 프로세서에서 여러 작업을 처리하는 방식이다. 실제로 동시에 실행되는 것이 아니라, 운영체제가 매우 빠르게 프로세서를 번갈아가며 할당하는 ‘선점(preemption)’ 기법을 통해 마치 동시에 실행되는 것처럼 보이게 만든다. 즉, 시간대를 미세하게 나누어 각 작업에 CPU 자원을 교대로 주는 것이다. 반면 병렬성(Parallelism)은 여러 개의 프로세서를 동시에 활용한다. 각 프로세서가 독립적으로 하나의 작업을 맡아 진짜로 동시에 실행되기 때문에, 진정한 의미의 ‘동시 처리’가 가능하다.

이러한 차이는 프로그래밍 실무에서 큰 의미를 갖는다. 병렬 처리는 운영체제의 부담이 적지만, 프로그래머가 작업을 잘게 나누어 각각의 프로세서에 분배해야 하는 어려움이 있다. 작업을 어떻게 나누고, 어떻게 동기화하며, 데이터 의존성을 어떻게 해결할 것인지에 대한 깊은 지식과 경험이 필요하기 때문이다. 그래서 병렬 프로그래밍은 흔히 “어렵다”고 평가받는다.

파이썬을 예로 들면, threading 모듈의 Thread 클래스는 병행성(Concurrency)을 활용한 방식이다. 하나의 프로세스 안에서 여러 스레드가 CPU 시간을 공유하며 작업을 처리한다. 반대로 multiprocessing 모듈의 Process 클래스는 병렬성(Parallelism)을 구현한다. 여러 개의 프로세스를 생성해 각각의 CPU 코어에서 독립적으로 실행되도록 만든다.

응용 프로그램 수준에서는 Process와 Thread가 큰 차이 없이 사용되기도 하지만, 관리적인 측면에서는 Thread를 더 권장하는 경우가 많다. Process는 종료 과정에서 문제가 생기면 ‘좀비 프로세스(Zombie Process)’가 되어 PID나 메모리 같은 시스템 자원을 불필요하게 점유할 위험이 있다. 반면 Thread는 자신이 속한 Process가 종료되면 자동으로 사라지기 때문에 자원 누출 위험이 거의 없다.

물론 모든 상황에서 Thread가 우월한 것은 아니다. 빅데이터 분석이나 대규모 과학 계산처럼 여러 프로세서의 자원을 최대한 활용해 속도를 극대화해야 하는 경우에는 Thread가 아니라 Process(혹은 진짜 병렬 처리 기법)를 반드시 사용해야 한다. Thread는 GIL(Global Interpreter Lock) 때문에 CPU-bound 작업에서는 진정한 병렬성을 발휘하지 못하기 때문이다.

결국 병행성과 병렬성은 ‘비슷하지만 전혀 다른’ 개념이다. 같은 ‘동시’라는 단어를 쓰지만, 그 실체는 프로세서의 수와 구현 방식, 프로그래머의 책임 범위까지 완전히 다르다. 개발자는 문제를 해결할 때 이 둘의 차이를 정확히 이해하고, 상황에 맞는 도구를 선택해야 한다. 단순히 “동시에 처리한다”는 막연한 생각이 아니라, 어떻게 동시에 처리할 것인지에 대한 명확한 설계가 좋은 소프트웨어의 출발점이기 때문이다.

Was this page helpful?