동시성(Concurrency) vs 병렬성(Parallelism): 차이점 한 번에 정리!
-
반응형
동시성(Concurrency) vs 병렬성(Parallelism)
시스템 설계에서 자주 헷갈리는 개념인 **동시성(Concurrency)**과 **병렬성(Parallelism)**에 대해 이야기해보려고 합니다.
비슷해 보이지만 완전히 다른 이 개념들을 예제와 함께 쉽게 풀어볼게요. 끝까지 읽으면 두 개념의 차이와 실세계 적용 사례를 확실히 이해할 수 있을 거예요! 🚀
🧩 1. 동시성(Concurrency)이란?
동시성은 여러 작업을 동시에 관리하는 개념입니다. 하지만 꼭 여러 작업이 "한 번에 실행"되는 건 아니에요. CPU가 빠르게 작업을 전환하며 진행 상황을 만들어가는 것이 핵심입니다.
💡 예제
예를 들어, 음악을 들으면서 코딩을 하는 상황을 생각해보세요. 단일 CPU는 한 번에 한 작업만 처리할 수 있지만, 아주 빠르게 두 작업을 번갈아 실행하면서 우리가 "동시에 된다"고 느끼는 것이죠. 🎵💻
🔍 동시성은 어떻게 작동할까?
CPU는 **컨텍스트 전환(context switching)**을 통해 동시성을 구현합니다:
현재 작업의 상태(레지스터, 프로그램 카운터 등)를 저장
다음 작업의 상태를 불러와 실행
이 과정을 초고속으로 반복!
⚠️ 하지만 컨텍스트 전환에는 오버헤드가 있어서 너무 자주 전환하면 성능이 저하될 수 있어요.
📌 실세계 사례
웹 브라우저: 페이지 렌더링, 이미지 로드, 사용자 클릭 처리
웹 서버: 여러 클라이언트 요청을 동시에 처리
채팅 앱: 메시지 수신, UI 업데이트, 메시지 전송을 동시에 수행
비디오 게임: 그래픽, 입력, 물리 연산, 사운드를 동시에 관리
🐍 파이썬 코드 예제 (threading 사용)
import threading
import time
def task(name):
for i in range(3):
print(f"{name} - Step {i+1}")
time.sleep(0.5) # 작업 대기 시뮬레이션
# 스레드 생성
t1 = threading.Thread(target=task, args=("Task A",))
t2 = threading.Thread(target=task, args=("Task B",))
t3 = threading.Thread(target=task, args=("Task C",))
# 스레드 시작
t1.start()
t2.start()
t3.start()
# 모든 스레드가 끝날 때까지 대기
t1.join()
t2.join()
t3.join()
출력 예시 (중첩 실행):
Task A - Step 1
Task B - Step 1
Task C - Step 1
Task A - Step 2
Task B - Step 2
Task C - Step 2
...
스레드가 서로 번갈아 실행되면서 동시성이 구현되는 걸 볼 수 있습니다.
반응형
⚡ 2. 병렬성(Parallelism)이란?
병렬성은 여러 작업을 진짜로 동시에 실행하는 것입니다. 이를 위해 작업을 여러 개의 작은 조각으로 나누고, 각 조각을 여러 CPU 코어나 GPU에 분산해서 처리합니다. 즉, 단일 CPU로는 불가능하고 멀티코어 환경이 필수입니다. 🖥️⚙️
🔍 병렬성은 어떻게 작동할까?
작업을 독립적인 하위 작업으로 분할
각 하위 작업을 별도의 코어에 할당
모든 코어가 동시에 실행 후 결과를 합침
📌 실세계 사례
머신 러닝: 데이터 배치를 여러 GPU에서 병렬 훈련
비디오 렌더링: 프레임을 나눠 동시에 렌더링
웹 크롤러: 여러 URL을 나눠 동시에 크롤링
빅 데이터 처리: Apache Spark로 대규모 로그 분석
과학 시뮬레이션: 날씨 모델링 계산을 여러 코어로 분산
🐍 파이썬 코드 예제 (multiprocessing 사용)
from multiprocessing import Pool
import time
def compute_sum(segment):
return sum(segment)
if __name__ == "__main__":
array = list(range(1000000)) # 큰 배열
segment_size = len(array) // 4 # 4개로 분할
segments = [array[i:i + segment_size] for i in range(0, len(array), segment_size)]
start_time = time.time()
# 병렬 처리
with Pool(processes=4) as pool:
results = pool.map(compute_sum, segments)
total = sum(results)
print(f"총합: {total}")
print(f"소요 시간: {time.time() - start_time:.2f}초")
설명:
배열을 4개로 나누고, 4개의 프로세스가 병렬로 합계를 계산합니다.
멀티코어 CPU에서 실행하면 속도가 훨씬 빨라지는 걸 경험할 수 있어요! 🚀
🔄 3. 동시성과 병렬성의 조합
이 두 개념을 조합하면 네 가지 상황이 나옵니다:
동시적이지만 병렬 아님: 단일 코어에서 여러 작업을 번갈아 처리 (예: 음악 듣기 + 코딩)
병렬적이지만 동시 아님: 한 작업을 여러 코어로 분할 (예: 비디오 렌더링)
둘 다 아님: 순차 실행 (예: 단일 코어에서 하나씩 실행)
동시성 + 병렬성: 여러 작업을 동시에 관리하면서 멀티코어로 병렬 처리 (예: 게임 엔진)
🎯 4. 언제 무엇을 사용할까?
특징
동시성(Concurrency)
병렬성(Parallelism)
목적
여러 작업을 효율적으로 관리
여러 작업을 동시에 실행
필요 조건
단일 코어로도 가능
멀티코어 필요
예시
웹 서버, 채팅 앱
머신 러닝, 비디오 렌더링
파이썬 도구
threading
multiprocessing
✅ 동시성은 작업이 겹칠 때 CPU를 바쁘게 유지하며 응답성을 높이고,
✅ 병렬성은 작업을 나눠 속도를 극대화해요.
상황에 맞게 선택하면 시스템 성능을 최적화할 수 있답니다!
🏁 마무리
이제 동시성과 병렬성의 차이점이 확실해졌나요? 😃 실제 프로젝트에서 이 개념을 적용하면 성능을 최적화할 수 있습니다.