💻 프로그래밍

동시성

Concurrency

여러 작업을 동시에 처리하는 개념. 병렬성과 달리 논리적 동시 실행. 스레드, 코루틴으로 구현.

📖 상세 설명

동시성(Concurrency)은 여러 작업이 논리적으로 동시에 진행되는 것처럼 보이게 하는 프로그래밍 개념입니다. 병렬성(Parallelism)이 물리적으로 동시에 여러 작업을 실행하는 것이라면, 동시성은 작업들 사이를 빠르게 전환하며 동시 진행하는 것처럼 처리합니다.

단일 코어 CPU에서도 동시성은 가능합니다. 운영체제의 스케줄러가 여러 프로세스나 스레드를 빠르게 전환하며 실행하기 때문입니다. 이를 통해 I/O 대기 시간 동안 다른 작업을 처리할 수 있어 전체 시스템 효율이 높아집니다.

동시성 프로그래밍의 주요 도전은 공유 자원에 대한 안전한 접근입니다. 레이스 컨디션, 데드락, 라이브락 같은 문제를 피하기 위해 뮤텍스, 세마포어, 모니터 같은 동기화 기법을 사용합니다. 최근에는 액터 모델이나 CSP(Communicating Sequential Processes) 같은 패러다임도 인기입니다.

각 언어는 다양한 동시성 모델을 제공합니다. JavaScript는 이벤트 루프와 async/await, Go는 고루틴과 채널, Rust는 소유권 기반의 안전한 동시성, Java는 스레드와 CompletableFuture를 사용합니다.

💻 코드 예제

Python
import asyncio
import threading
import time

# 동시성 vs 순차 실행 비교

# 순차 실행 (느림)
def sequential_io():
    for i in range(3):
        time.sleep(1)  # I/O 시뮬레이션
        print(f"순차 작업 {i} 완료")

# 동시성: asyncio (단일 스레드, 협력적 멀티태스킹)
async def async_task(name, delay):
    await asyncio.sleep(delay)
    print(f"비동기 작업 {name} 완료")
    return name

async def concurrent_io():
    tasks = [
        async_task("A", 1),
        async_task("B", 1),
        async_task("C", 1)
    ]
    results = await asyncio.gather(*tasks)  # 동시 실행
    return results

# 동시성: 스레딩 (I/O 바운드 작업에 적합)
def threaded_task(name, delay):
    time.sleep(delay)
    print(f"스레드 작업 {name} 완료")

def concurrent_threads():
    threads = [
        threading.Thread(target=threaded_task, args=(f"T{i}", 1))
        for i in range(3)
    ]
    for t in threads:
        t.start()
    for t in threads:
        t.join()

# 실행 비교
print("=== 순차 실행 ===")
start = time.time()
sequential_io()
print(f"소요 시간: {time.time() - start:.2f}초")  # ~3초

print("\n=== 비동기 동시 실행 ===")
start = time.time()
asyncio.run(concurrent_io())
print(f"소요 시간: {time.time() - start:.2f}초")  # ~1초

🗣️ 실무 대화 예시

백엔드 개발자
"사용자 요청마다 외부 API 3개를 호출하는데, 순차적으로 하니까 응답이 3초나 걸려요."
시니어 개발자
"동시성 처리로 병렬 호출하면 가장 느린 API 응답 시간 정도로 줄일 수 있어요. Python이면 asyncio.gather를 써보세요."
백엔드 개발자
"결과를 조합하는 로직이 있는데, 하나가 실패하면 전체가 실패해야 할까요?"
면접관
"동시성과 병렬성의 차이를 설명해주세요."
지원자
"동시성은 여러 작업을 번갈아가며 진행하여 동시에 처리하는 것처럼 보이게 합니다. 병렬성은 실제로 여러 작업을 동시에 실행합니다. 단일 코어에서는 동시성만 가능하고, 멀티 코어에서 병렬성이 가능합니다."
면접관
"레이스 컨디션이란 무엇이고 어떻게 방지하나요?"
지원자
"두 개 이상의 스레드가 공유 자원에 동시에 접근할 때 결과가 실행 순서에 따라 달라지는 현상입니다. 뮤텍스로 상호 배제하거나, 원자적 연산을 사용하거나, 불변 데이터 구조를 사용해서 방지합니다."
리뷰어
"이 코드에서 여러 스레드가 같은 리스트에 append하고 있어요. Python 리스트의 append는 원자적이지만, 다른 연산과 조합되면 레이스 컨디션이 발생할 수 있어요."
작성자
"queue.Queue를 사용하거나 Lock으로 보호하는 게 더 안전하겠네요."
리뷰어
"네, 그리고 가능하면 스레드 간 공유 상태를 최소화하는 설계가 더 좋습니다. 결과를 반환받아 메인 스레드에서 조합하세요."

⚠️ 주의사항

🔗 관련 용어

📚 더 배우기