동시성과 병렬성

박정민·2026년 1월 29일
post-thumbnail

CPU의 동시성과 병렬성

오늘 포스팅할 주제는 CPU의 동시성과 병렬성, 그리고 백엔드에서 이를 확인한 경험에 대해서 다루겠습니다.

동시성 VS 병렬성

동시성과 병렬성은 서로 다른 의미지만 헷갈려 하는 케이스가 많습니다. 어쩌면 "동시성은 동시에... 병렬도 동시에..."라고 답하는 경우도 있을 것입니다.

예시로 이해하기

동시성: 요리를 할 때 잠깐 재료 손질하고, 잠깐 물 끓이고, 잠깐 설거지하고 하는 방식
병렬성: 한 명은 재료 손질을 담당, 한 명은 설거지 담당 이렇게 진짜 동시에 하는 방식

CPU 관점에서 본 차이

  • 동시성: 시간을 쪼개 여러 작업을 아주 빠르게 번갈아 가며 수행하여 사용자의 눈에는 동시에 실행되는 것처럼 보임
  • 병렬성: 멀티코어 환경에서 각각의 CPU가 동시에 하나씩 작업을 수행하는 개념

핵심 정리

  • 동시성: 논리적 개념 (싱글코어 멀티태스킹, 비동기 I/O)
  • 병렬성: 물리적 개념 (멀티코어 필수, CPU 병렬연산 수행)

싱글코어의 동시성 제어

싱글코어에서 동시성이 필요한 이유: CPU의 '놀고 있는 시간'을 없애기 위해서입니다.

싱글코어에서 실제로 벌어지는 일

  • CPU는 동시에 1가지 작업만 수행 가능
  • 싱글코어는 한 순간에 딱 하나의 스레드만 실행
  • 동시성은 진짜 병렬이 아니라 빠른 컨텍스트 스위칭 기반
  • CPU 연산 자체를 빠르게 만드는 것은 불가능

그렇다면 동시성이 왜 필요할까?

작업 흐름

현실 서버의 작업 흐름은 아래와 같습니다:

요청 수신
→ DB 조회 (대기)
→ 외부 API 호출 (대기)
→ 파일 I/O (대기)
→ 약간의 CPU 계산

대부분 요청이 들어오면 스레드가 할당되고, 대부분의 시간은 CPU 작업이 아닌 기다리는 시간을 동반합니다.

문제 상황 예시

String user = userRepository.find();   // DB 대기
String profile = externalApi.call();   // 네트워크 대기

문제점:

  • DB 응답 올 때까지 CPU는 아무것도 안 함
  • 외부 API 기다리는 동안도 CPU는 놀고 있음
  • 싱글코어 기준: 스레드는 잡혀있고 CPU는 놀고 있음

비동기/논블로킹 방식 (동시성의 진짜 목적)

Future<User> userFuture = findUserAsync();
Future<Profile> profileFuture = callApiAsync();

장점:

  • I/O 요청을 던지고 즉시 반환
  • CPU는 다른 요청을 처리, 다른 콜백 실행, 다른 스레드 스케줄링을 수행

CPU가 노는 시간을 줄인다의 진짜 의미

⚠️ 작업 자체의 소요시간이 줄어드나?아닙니다.

구분줄어드나?
DB 쿼리 시간
네트워크 왕복 시간
CPU 연산 시간

✅줄어드는 것: CPU가 '아무것도 안 하는 시간'

타임라인으로 보기

1. 동기/블로킹

[CPU] A 실행
[CPU] ── 대기(DB) ─────────
[CPU] A 재개
[CPU] ── 대기(API) ────────

2. 비동기/논블로킹

[CPU] A 실행
[CPU] B 실행
[CPU] C 실행
[CPU] A 재개
[CPU] B 재개

대기 시간 사이에 다른 작업을 끼워 넣음으로써 '전체 요청 완료 시점'이 당겨집니다.

즉, 대기시간과 실행 시간을 서로 겹치게 배치하여 전체 완료 시점을 빠르게 하는 것입니다.


레이턴시 vs Throughput

조금 더 본질적으로는 레이턴시 최적화가 아닌 Throughput 최적화입니다.

  • 목적: 개별 요청의 레이턴시를 줄이기 위한 것보다는 같은 시간 동안 처리할 수 있는 요청 수를 늘리기 위함

요청 관점에서 비교

단일 요청:

  • 동기든 비동기든 이 요청이 완료되는 순수 시간은 거의 동일

다수 요청:

  • 동기/블로킹: 뒤에 온 요청들은 큐에 오래 대기 → P95/P99 지표가 나쁘게 책정
  • 비동기/논블로킹: 큐 대기시간 감소 → P95/P99가 좋아짐

비동기는 레이턴시를 직접 줄이지는 않지만, 시스템 처리 용량을 키워서 큐 대기로 인한 레이턴시 악화를 방지합니다.


⚠️ 흔히 생각하는 오해

"비동기는 빠르다" ❌

오답입니다.

오히려 비동기 작업이 이미지 리사이징 혹은 암/복호화(BCrypt)의 경우 더 느려질 수 있습니다.

비동기는 "많이 처리한다"의 개념입니다. 특히 I/O-bound 작업에서 효과적입니다.


💬 마무리

다음 포스팅에서는 이를 기반으로 실제 Spring Boot 기반 예시 코드와 함께 비교해보겠습니다.

감사합니다.

profile
Backend Developer

0개의 댓글