[CS-010][실무] 동시성·병렬성·비동기 쉽게 구분하기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[CS-010][실무] 동시성·병렬성·비동기 쉽게 구분하기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 126회 작성일 26-09-04 15:34

본문

[이번 수업]
여러 일을 함께 처리할 때 쓰는 동시성, 병렬성, 비동기를 구분합니다. 해결하는 문제가 어떻게 다른지 배우고 Python으로 기다리는 작업을 겹쳐 실행합니다.

[선수지식]
함수, 반복문, 예외를 알고 터미널에서 Python을 실행할 수 있어야 합니다. 프로세스는 실행 중인 프로그램, 스레드는 그 안의 실행 흐름입니다.

[학습목표]
1. 동시성·병렬성·비동기의 차이를 설명합니다.
2. I/O 대기와 CPU 계산에 알맞은 방식을 고릅니다.
3. 작업 수, 오류, 취소를 통제하는 이유를 이해합니다.

[핵심개념]
동시성은 여러 작업이 겹친 시간 구간에 조금씩 진행되도록 만드는 것입니다. 한 요리사가 물을 끓이는 동안 채소를 써는 모습과 같습니다. 병렬성은 여러 작업이 실제로 같은 순간에 실행되는 것입니다. 요리사 두 명처럼 여러 CPU 코어를 활용할 수 있으며 동시성이 곧 병렬성을 뜻하지는 않습니다.

비동기는 완료될 때까지 멈추지 않고 다른 일을 하다가 결과를 받는 방식입니다. Python asyncio의 코루틴은 잠시 멈췄다가 이어갈 수 있는 함수로, `await`에서 제어권을 돌려줍니다. 네트워크 응답처럼 기다림이 많은 I/O 작업에 알맞습니다. `await` 없이 오래 계산하면 이벤트 루프가 다른 작업을 실행하지 못합니다.

스레드는 메모리를 공유해 I/O 작업을 겹치기 편하지만, 같은 값을 함께 바꾸면 실행 순서에 따라 결과가 달라지는 데이터 레이스가 생길 수 있습니다. 잠금이나 메시지 큐를 쓰고 공유 변경 상태를 줄입니다. 일반 CPython은 GIL 영향 때문에 CPU 계산을 스레드로 늘린다고 항상 빨라지지 않습니다. 독립된 메모리를 쓰는 프로세스와 ProcessPoolExecutor는 CPU 계산을 여러 코어로 나눌 때 후보지만 시작·통신 비용이 있습니다.

먼저 병목을 측정합니다. 기다림이 대부분이면 asyncio나 제한된 스레드 풀, 큰 CPU 계산이 독립적이면 프로세스 풀을 검토합니다. 작은 작업은 순차 코드가 더 나을 수 있습니다. 완료 순서를 가정하지 말고 결과, 예외, 취소, 시간 제한을 처리합니다.

[따라하기]
다음을 async_demo.py로 저장합니다. 외부 패키지는 필요 없습니다.

```python
import asyncio
import time

async def job(name, seconds):
    print(f"{name} 시작")
    await asyncio.sleep(seconds)
    print(f"{name} 끝")
    return name

async def main():
    started = time.perf_counter()
    results = await asyncio.gather(
        job("A", 1.0),
        job("B", 0.5),
    )
    print("결과:", results)
    print(f"걸린 시간: {time.perf_counter() - started:.1f}초")

asyncio.run(main())
```

macOS/Linux는 `python3 async_demo.py`, Windows PowerShell은 `py async_demo.py`로 실행합니다. 세부 시간은 달라도 핵심 예상 결과는 다음과 같습니다.

```text
A 시작
B 시작
B 끝
A 끝
결과: ['A', 'B']
걸린 시간: 1.0초
```

대기 합계는 1.5초지만 겹쳐 약 1초가 걸립니다. B가 먼저 끝나도 `gather` 결과는 전달한 A, B 순서입니다. `asyncio.sleep`은 I/O 대기를 흉내 낸 것이며 CPU 병렬 실행 예제는 아닙니다.

[흔한 실수]
비동기를 무조건 빠른 코드로 생각하거나 작업을 제한 없이 만들면 안 됩니다. 공유 값을 잠금 없이 바꾸거나 한 번의 결과를 항상 같은 순서라고 믿는 것도 위험합니다. 실행 시간과 CPU 사용량을 측정하고 다시 비교합니다.

[보안 주의]
외부 요청을 무제한으로 만들면 연결, 메모리, 파일 핸들을 고갈시킬 수 있습니다. 세마포어나 작업 풀로 수를 제한하고 시간 제한, 취소, 재시도 상한을 둡니다. 로그에 토큰이나 개인정보를 남기지 않습니다. 실습은 본인 소유의 로컬 또는 허가된 격리 환경에서만 수행합니다.

[직접 해볼 과제]
`job("C", 0.2)`를 추가해 완료 순서와 전체 시간을 예상하고 확인하세요. 다음에는 A와 B를 차례로 `await`하여 약 1.5초가 되는지 비교하고 이유를 기록합니다.

[확인문제]
1. 동시성과 병렬성은 어떻게 다른가요?
2. `await` 없이 오래 계산하면 이벤트 루프에 어떤 일이 생기나요?
3. 동시 작업 수에 상한을 두어야 하는 이유는 무엇인가요?

[다음 학습]
다음 과정 TOOL-010에서는 비밀정보를 코드에서 분리해 관리하는 방법을 배웁니다. CS-011에서는 설계 패턴의 선택 기준을 다룹니다.

[공식 참고 자료]
- Python asyncio 공식 문서: https://docs.python.org/3/library/asyncio.html
- Python asyncio 작업과 gather: https://docs.python.org/3/library/asyncio-task.html
- Python threading 공식 문서: https://docs.python.org/3/library/threading.html
- Python multiprocessing 공식 문서: https://docs.python.org/3/library/multiprocessing.html
- Python concurrent.futures 공식 문서: https://docs.python.org/3/library/concurrent.futures.html
- Go 메모리 모델과 데이터 레이스: https://go.dev/ref/mem

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
4,129
어제
6,862
최대
16,772
전체
770,080
Copyright © 소유하신 도메인. All rights reserved.