Blocking과 Non-blocking은 프로그램이나 시스템에서 작업이 완료될 때까지 대기하는지 여부에 대한 중요한 개념이다. 이 두 개념은 주로 I/O(입출력) 작업, 스레드, 네트워크 통신과 같은 상황에서 사용된다. 이 개념들을 이해하는 것은 프로그램의 성능, 응답성, 자원 사용에 큰 영향을 미치기 때문에 중요하다.
1. Blocking (블로킹)
Blocking이란?
- Blocking은 어떤 작업이 완료될 때까지 해당 작업이 끝날 때까지 프로세스나 스레드가 대기하는 방식을 의미한다. 작업이 완료되기 전까지 다른 작업을 수행하지 않고, 해당 작업이 끝난 후에야 다음 작업으로 넘어갈 수 있다.
- 보통 입력이나 출력(I/O) 작업에서 많이 사용되며, 네트워크 통신, 파일 시스템 접근, 스레드 동기화 등 다양한 상황에서 Blocking 방식이 사용된다.
Blocking의 특징
- 작업 대기: 블로킹 호출을 하는 동안 해당 호출이 완료될 때까지 작업이 중단된다. 예를 들어, 파일을 읽는 작업이 완료될 때까지 프로그램은 파일이 모두 읽힐 때까지 대기한다.
- 간단한 구현: 블로킹 방식은 프로그래밍이 간단하고 직관적이다. 작업이 완료될 때까지 대기하므로, 다음 작업을 언제 시작해야 하는지 고민할 필요가 없다.
- 성능 저하 가능성: 네트워크 요청이나 파일 읽기/쓰기 같은 작업은 시간이 오래 걸릴 수 있기 때문에, 블로킹 방식은 프로그램의 응답성을 저하시킬 수 있다. 특히, 사용자 인터페이스(UI)를 차단하는 경우 프로그램이 "멈춘" 것처럼 보일 수 있다.
Blocking의 예시
다음은 Python에서 블로킹 I/O 작업의 예시이다. 네트워크 소켓에서 데이터를 읽을 때, 소켓으로부터 데이터를 받을 때까지 대기하는 동작이다.
import socket
# 서버에 연결
s = socket.socket()
s.connect(('example.com', 80))
# 서버로부터 데이터 받기 (blocking)
data = s.recv(1024) # 데이터가 올 때까지 기다림
print("Received:", data)
위의 코드에서 s.recv(1024)는 서버로부터 1024바이트의 데이터를 받을 때까지 차단(Blocking) 된다. 서버가 응답을 보낼 때까지 프로그램은 대기하고, 그 동안 다른 작업은 수행되지 않는다.
Blocking의 장점과 단점
- 장점:
- 구현이 간단하고 이해하기 쉽다.
- 순차적으로 실행되므로 프로그램의 흐름을 예측하기가 용이하다.
- 단점:
- 대기 시간이 길어질 경우 성능이 저하될 수 있다.
- 특히 네트워크나 파일 I/O 작업에서 대기 시간이 길어지면, 전체 프로그램의 응답성이 낮아진다.
- 멀티스레드 환경에서, 하나의 스레드가 블로킹 상태일 경우 다른 스레드도 영향을 받을 수 있다.
2. Non-blocking (논블로킹)
Non-blocking이란?
- Non-blocking은 작업이 즉시 완료되지 않더라도, 프로세스나 스레드가 해당 작업을 기다리지 않고 바로 다음 작업으로 넘어가는 방식을 의미한다. 즉, 작업을 요청한 후 작업이 완료되기를 기다리지 않고, 즉각적으로 다른 작업을 수행할 수 있다.
- 비동기적(Asynchronous) 작업 처리 방식과 관련이 있으며, 프로그램의 응답성을 높이기 위한 중요한 기법이다.
Non-blocking의 특징
- 즉시 반환: Non-blocking 호출은 결과가 준비되지 않은 경우에도 즉시 반환된다. 작업이 완료되지 않았더라도, 다른 작업을 계속 진행할 수 있다.
- 다른 작업 병행 가능: Non-blocking 방식에서는 대기하는 대신 다른 작업을 계속할 수 있으므로, 여러 작업이 동시에 이루어질 수 있는 장점이 있다.
- 복잡한 제어 흐름: Non-blocking 방식은 블로킹 방식보다 코드가 복잡할 수 있다. 작업의 완료 시점을 직접 관리해야 하며, 이를 위해 콜백 함수나 이벤트 루프를 사용하는 경우가 많다.
Non-blocking의 예시
다음은 Python에서 Non-blocking 소켓 작업의 예시이다. 소켓을 논블로킹 모드로 설정하여 데이터를 기다리지 않고, 작업을 계속 진행한다.
import socket
# 서버에 연결
s = socket.socket()
s.setblocking(False) # 논블로킹 모드로 설정
try:
s.connect(('example.com', 80))
except BlockingIOError:
# 연결이 완료되지 않았더라도 다른 작업을 계속 수행
pass
# 다른 작업을 수행하는 동안 데이터가 준비될 때까지 대기하지 않음
try:
data = s.recv(1024) # 데이터가 아직 준비되지 않았을 수 있음
print("Received:", data)
except BlockingIOError:
# 데이터가 아직 준비되지 않았으면 즉시 반환
print("No data available")
위의 코드에서 s.setblocking(False)를 사용하여 소켓을 Non-blocking 모드로 설정한다. 이로 인해 s.recv(1024)는 데이터가 없을 경우 즉시 반환되며, 프로그램이 계속 실행된다. 즉, 데이터를 기다리며 멈추지 않고 다른 작업을 처리할 수 있다.
Non-blocking의 장점과 단점
- 장점:
- 프로그램의 응답성이 높아진다. 하나의 작업을 기다리지 않고 다른 작업을 처리할 수 있다.
- 멀티태스킹에 유리하며, 특히 네트워크 통신이나 파일 I/O 작업에서 유용하다.
- 이벤트 기반 또는 비동기 프로그래밍과 잘 맞다.
- 단점:
- 제어 흐름이 복잡해진다. Non-blocking 작업이 완료되었는지 확인하고, 필요한 경우 다시 시도하거나 콜백 함수를 사용해야 한다.
- 타이밍 문제를 처리하는 코드가 더 복잡해지며, 여러 작업을 동시에 처리하는 경우 코드 유지보수가 어려울 수 있다.
3. Blocking과 Non-blocking의 비교
특징 | Blocking (블로킹) | Non-blocking (논블로킹) |
작업 처리 방식 | 작업이 완료될 때까지 대기 | 작업을 기다리지 않고 즉시 반환 |
응답성 | 작업 완료 시까지 다른 작업을 진행하지 않음 | 작업이 완료되지 않더라도 다른 작업을 즉시 진행 가능 |
사용 편리성 | 구현이 간단하고 이해하기 쉬움 | 비동기 작업의 복잡성으로 인해 구현이 복잡해질 수 있음 |
성능 | 대기 시간이 긴 경우 성능 저하 | 더 나은 응답성과 성능을 제공 |
예시 | 파일 읽기/쓰기, 네트워크 소켓 대기 등 | 논블로킹 I/O, 비동기 함수 호출, 이벤트 기반 프로그래밍 |
코드 예시 | recv()가 데이터를 받을 때까지 대기 | recv()가 데이터를 받을 때까지 대기하지 않음 |
4. Blocking과 Non-blocking 사용 사례
Blocking 사용 사례
- 단일 스레드 프로그램: 프로그램이 작업 완료까지 기다려도 상관없는 경우. 예를 들어, 계산을 수행한 후 결과를 출력하는 경우에는 블로킹 방식이 적합할 수 있다.
- 입출력 작업: 간단한 파일 입출력, 네트워크 소켓 통신 등에서 블로킹 방식은 적합할 수 있다. 이 방식에서는 작업 순서가 직관적이므로 유지보수가 쉬울 수 있다.
- 일반적 사용자 인터페이스(UI) 작업: 입력 이벤트를 처리할 때 순차적으로 입력을 처리하는 방식.
Non-blocking 사용 사례
- 네트워크 프로그래밍: 네트워크 응답 시간이 길 경우, Non-blocking 소켓이나 비동기 네트워크 통신을 사용하여 프로그램이 응답을 기다리는 동안 다른 작업을 수행할 수 있다.
- 멀티태스킹: 여러 작업을 병렬로 처리해야 하는 경우. 예를 들어, 서버에서 다수의 클라이언트 요청을 처리할 때 Non-blocking 방식이 유리하다.
- 비동기 이벤트 처리: 이벤트 기반 프로그래밍(예: JavaScript의 async/await 또는 Python의 asyncio)에서는 Non-blocking 방식이 필수적이다.
- 그래픽 처리 및 게임 개발: 빠른 응답과 함께 다양한 이벤트를 처리해야 하므로, Non-blocking 방식이 중요하다.
- Blocking은 작업이 완료될 때까지 해당 프로세스나 스레드가 대기하는 방식으로, 구현이 간단하지만 대기 시간이 길면 성능에 영향을 줄 수 있다. 주로 단순한 I/O 작업이나 단일 스레드 프로그램에서 사용된다.
- Non-blocking은 작업을 기다리지 않고 즉시 반환하여 다른 작업을 진행할 수 있는 방식으로, 응답성을 높이고 비동기적 작업에 적합하다. 하지만 더 복잡한 제어 흐름을 요구하며, 주로 멀티태스킹, 네트워크 프로그래밍, 비동기 I/O에서 사용된다.
이 두 개념은 시스템의 요구 사항에 따라 적절히 선택해야 하며, 특히 응답성이나 성능이 중요한 경우에는 Non-blocking 방식이 유리할 수 있다. 반면, 구현의 간단함이 중요할 때는 Blocking 방식이 더 적합할 수 있다.
'Backend study > Backend theory' 카테고리의 다른 글
TCP's 3-way handshake, 4-way handshake (0) | 2024.09.20 |
---|---|
TCP 와 UDP (1) | 2024.09.19 |
경쟁 조건(Race Condition)과 교착 상태(Deadlock) (0) | 2024.09.17 |
프로세스(process)와 스레드(thread) (2) | 2024.09.16 |
HTTP와 HTTPS (1) | 2024.09.15 |