네트워크 I/O와 이벤트 루프 (Network I/O and Event Loop)

목차


네트워크 I/O와 이벤트 루프를 왜 묻나

백엔드 면접에서 이 주제는 단순히 “async/await를 쓸 줄 아는가”를 보려는 질문이 아닙니다.

보통은 다음을 같이 확인합니다.

  • 처리 모델 이해: 요청이 들어오면 CPU가 일하는지, I/O를 기다리는지 구분할 수 있는가
  • 동시성 감각: 스레드 수를 늘리는 것과 이벤트 루프 기반 처리가 어떻게 다른가
  • 병목 판단: 느린 원인이 계산인지, 네트워크 대기인지 설명할 수 있는가
  • 운영 감각: 타임아웃, 연결 수, backpressure 같은 실제 문제를 아는가

즉, 핵심은 이벤트 루프 자체보다
I/O가 많은 서버를 어떤 실행 모델로 다룰지 설명할 수 있는가입니다.

관련 일반론은 동시성 (Concurrency), 언어별 예시는 JavaScript, Python 문서와 연결해서 보면 좋습니다. 응답 포맷 선택과 직렬화 비용은 직렬화 (Serialization) 문서와 함께 보면 더 직접적입니다.


네트워크 I/O의 기본 개념

네트워크 I/O는 보통 소켓을 열고, 데이터를 읽고, 쓰는 과정입니다.

이때 중요한 점은 CPU가 네트워크 데이터를 “계산”하는 시간이 아니라,
대부분의 시간을 상대방 응답을 기다리며 보낼 수 있다는 점입니다.

예를 들어 API 서버는 다음 작업을 자주 합니다.

  • 클라이언트 요청 읽기
  • DB나 캐시 서버에 질의 보내기
  • 외부 API 응답 기다리기
  • 응답 직렬화 후 다시 쓰기

이 중 상당수는 계산보다 대기(waiting) 가 더 큰 비용입니다.
그래서 네트워크 I/O 모델은 “CPU를 어떻게 더 쓰게 할까”보다
대기 시간을 어떻게 효율적으로 겹칠까에 더 가깝습니다.


동기와 비동기, 블로킹과 논블로킹

이 네 가지는 면접에서 자주 섞여 나오므로 구분해서 설명하는 편이 좋습니다.

개념 질문 설명
동기 (Synchronous) 결과를 언제 받는가 호출한 쪽이 결과 흐름을 직접 이어받음
비동기 (Asynchronous) 결과를 나중에 어떻게 받는가 콜백, Future, Promise, coroutine 등으로 이어받음
블로킹 (Blocking) 호출 중에 실행 흐름이 멈추는가 완료될 때까지 현재 실행 흐름이 기다림
논블로킹 (Non-blocking) 바로 제어를 돌려주는가 아직 완료되지 않아도 즉시 반환 가능

중요한 점은 동기/비동기블로킹/논블로킹이 같은 축이 아니라는 것입니다.

  • 동기 호출도 논블로킹 구조 위에서 만들 수 있습니다.
  • 비동기 API를 써도 내부에서 블로킹 작업이 섞이면 전체 효율이 떨어질 수 있습니다.

면접에서는 “async면 무조건 빠르다”가 아니라,
I/O 대기를 다른 작업과 겹칠 수 있느냐로 설명하는 편이 좋습니다.


이벤트 루프란

이벤트 루프(Event Loop)는 준비된 작업을 계속 확인하면서 실행 흐름에 넣어 주는 런타임 메커니즘입니다.

핵심 아이디어는 단순합니다.

  1. 오래 걸리는 I/O 작업은 운영체제나 런타임에 맡긴다
  2. 현재 실행 흐름은 다른 작업을 계속 처리한다
  3. I/O 완료 이벤트가 오면 그때 후속 작업을 실행한다

이벤트 루프를 설명할 때 자주 같이 나오는 요소는 다음과 같습니다.

  • Call Stack: 현재 실행 중인 함수 흐름
  • Queue / Task Queue: 나중에 실행할 작업 대기열
  • Callback / Future / Promise / Coroutine: 완료 후 이어질 작업 표현
  • Event Loop: 준비된 작업을 스케줄링하는 루프

JavaScript의 런타임 모델이나 Python의 asyncio는 이 개념을 이해하는 데 좋은 예시입니다.12


멀티플렉싱과 운영체제 지원

이벤트 루프가 많은 연결을 다룰 수 있는 이유는 운영체제의 I/O 멀티플렉싱 지원 덕분입니다.

대표적으로 다음 메커니즘이 나옵니다.

  • select
  • poll
  • epoll (Linux)
  • kqueue (BSD, macOS)

이런 메커니즘은 “어떤 소켓이 읽기/쓰기 가능 상태가 되었는가”를 한 번에 확인하게 도와줍니다.

그래서 이벤트 루프 기반 서버는 다음 식으로 설명할 수 있습니다.

  • 연결마다 스레드를 하나씩 붙이지 않아도 됨
  • 준비된 I/O만 골라 처리할 수 있음
  • 많은 연결 수를 상대적으로 적은 실행 흐름으로 다룰 수 있음

물론 이것이 공짜는 아닙니다.

  • 콜백 체인이나 비동기 흐름이 복잡해질 수 있음
  • 블로킹 코드가 끼면 전체 응답성이 나빠질 수 있음
  • CPU-heavy 작업은 별도 분리가 필요할 수 있음

이벤트 루프가 잘 맞는 경우와 한계

잘 맞는 경우

  • 동시에 많은 연결을 유지해야 하는 서버
  • 외부 API, DB, 캐시 I/O가 많은 서비스
  • WebSocket, 채팅, 알림, 스트리밍처럼 대기 시간이 긴 연결

한계

  • 요청당 CPU 계산량이 큰 서비스
  • 압축, 이미지 처리, 암호화처럼 계산이 무거운 작업
  • 블로킹 라이브러리를 많이 써야 하는 환경

즉, 이벤트 루프는 “I/O-bound 동시성“에 강한 모델입니다.
CPU 병목이 크면 이벤트 루프 하나만으로는 해결이 어렵고,
워커 프로세스 분리나 작업 큐 같은 다른 구조가 같이 필요할 수 있습니다.


백프레셔, 타임아웃, 연결 관리

이벤트 루프를 설명할 때 실무 감각을 드러내려면 단순 구조보다 운영 포인트를 같이 말하는 편이 좋습니다.

백프레셔 (Backpressure)

생산 속도가 소비 속도보다 빠를 때 큐나 버퍼가 계속 쌓이는 문제입니다.

  • 요청은 계속 들어오는데 처리 속도가 못 따라감
  • 읽기는 빠른데 쓰기가 느려 버퍼가 커짐
  • 메시지를 소비하는 속도보다 발행 속도가 빠름

이런 상황에서는 무한 버퍼링보다
속도 제한, 큐 길이 제한, 드롭 정책, 재시도 정책을 같이 봐야 합니다.

타임아웃

네트워크 I/O는 영원히 기다리면 안 됩니다.

  • connect timeout
  • read timeout
  • write timeout
  • 전체 요청 timeout

타임아웃이 없으면 일부 느린 하위 시스템 때문에 전체 워커나 연결이 묶일 수 있습니다.

연결 관리

  • keep-alive를 어떻게 쓸 것인가
  • connection pool 크기를 어떻게 잡을 것인가
  • 한 클라이언트가 너무 오래 연결을 점유하지 않는가

좋은 답변은 “이벤트 루프는 빠르다”가 아니라,
대기 모델을 효율화하는 대신 타임아웃, 큐, 백프레셔 관리가 중요하다고 설명하는 답변입니다.


코드 예시

아래 예시는 asyncio로 여러 네트워크 성격의 작업을 겹쳐 처리하는 기본 패턴입니다.3

import asyncio


async def fetch_service(name: str, delay: float) -> str:
    await asyncio.sleep(delay)
    return f"{name}:ok"


async def main() -> None:
    results = await asyncio.gather(
        fetch_service("user-api", 0.1),
        fetch_service("billing-api", 0.2),
        fetch_service("inventory-api", 0.15),
    )
    print(results)


asyncio.run(main())

이 예시에서 중요한 포인트는 다음과 같습니다.

  • 각 작업은 CPU 계산보다 I/O 대기 시간이 큰 작업이라고 가정합니다
  • gather()를 통해 여러 작업의 대기 시간을 겹칠 수 있습니다
  • 이런 모델은 I/O에는 잘 맞지만, CPU-heavy 계산을 빠르게 만드는 모델은 아닙니다

면접 포인트

  • 네트워크 I/O의 핵심은 CPU 계산보다 대기 시간이 크다는 점입니다.
  • 동기/비동기와 블로킹/논블로킹은 다른 축이므로 구분해서 설명해야 합니다.
  • 이벤트 루프는 준비된 I/O 작업을 효율적으로 스케줄링하는 모델이며, I/O-bound 동시성에 강합니다.
  • 많은 연결을 적은 실행 흐름으로 다룰 수 있지만, CPU-heavy 작업이나 블로킹 코드에는 약합니다.
  • 실무 답변에서는 backpressure, timeout, connection pool 같은 운영 포인트를 같이 말하는 편이 좋습니다.

참고 자료