대용량 시스템/대규모 트래픽 이론

[대규모트래픽 이론] #2.1 비동기 처리 아키텍처 이해와 확장

dev_rosieposie 2025. 3. 29. 20:41

학습목표

  1. 비동기 처리시스템의 아키텍쳐를 이해한다

목차

  1. 비동기 처리 아키텍쳐 이해와 확장
  2. 비동기 메시징 시스템 이해
  3. 비동기 처리 시스템 장단점 및 사례

들어가기 전..

동시성, 비동기 개념 복습하기

 

[대규모트래픽 이론] #1.2 동시성 처리와 비동기 처리의 기본 구조

학습목표스레드풀과 이벤트 루프에 대해 이해한다.목차동시성 처리개념스레드 풀의 구조 및 활용비동기 처리개념이벤트루프 구조 및 활용completable future들어가기 전..1. 이어지는 게시글 반복

dev-rosiepoise.tistory.com


비동기 처리의 개념 복습

  •  비동기 처리는 작업을 병렬로 수행하는 개념으로, 하나의 작업이 완료할 때까지 기다리지 않고 다른 작업을 시작할 수 있는 방식
  • 대표적으로 I/O 작업에서 대기 시간이 길어질 경우, 프로그램은 다른 작업을 처리하며 대기 시간을 효율적으로 사용

비동기 처리의 필요성

  1. 동기 처리와 비동기 처리의 차이점
    • 동기 처리는 작업이 완료될 때까지 호출자가 대기하는 방식. 한 작업이 끝나기 전까지 다른 작업을 수행할 수 없음.
    • 비동기 처리는 호출자가 대기하지 않고, 작업이 끝났을 때 콜백이나 이벤트를 통해 작업 완료를 알림
  2. 대규모 시스템의 주요과제
    • 사용자 동시요청이 많아지면, 동시 처리의 한계가 있기 때문에 사용자 경험이 낮아질 가능성으로 이어지기 때문
    • ex) 금융 거래, 온라인 쇼핑몰

비동기 처리 시스템의 규모 확장 : 단일 프로세스에서 비동기 처리

  1. 작은 시스템에서는 자원의 효율적 사용이 중요함
  2. i/o 작업(파일 읽기, 네트워크 요청)은 처리 시간이 길어질 수 있음 -> cpu 관여 x
  3. 비동기 처리를 통해 그 대기 시간을 활용하여 다른 작업을 진행함으로써 전체 성능을 향상시킬 수 있음
  4. cpu 자원이 놀지 않고 계속 작업을 처리하도록 돕는 것이 비동기 처리의 핵심 장점

java에서 비동기 처리의 기본 구성

  • 스레드 풀 (스레드 재사용하여 성능 오버헤드를 줄임)
  • 이벤트 루프를 활용한 비동기 처리
public class AsyncTest {

    public static void main(String[] args) throws IOException {

        ExecutorService executor = Executors.newFixedThreadPool(5);

        executor.submit(() ->{
           // 비동기 작업 진행
            for(int i=0; i<500; i++){
                System.out.println("비동기 작업 : "+i);
            }
        });

        Path filePath = Paths.get("계약이행현황.txt");
        AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(filePath);
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        fileChannel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer integer, ByteBuffer byteBuffer) {
                // 파일 읽기 완료 후 처리
                System.out.println("파일 읽기 완료");
            }

            @Override
            public void failed(Throwable throwable, ByteBuffer byteBuffer) {

                throwable.printStackTrace();
                // 오류 처리
                System.out.println("오류발생 ㅋ");
            }
        });

    }
}

 

결과

비동기 작업 : 1

비동기 작업 : 2
비동기 작업 : ...
비동기 작업 : 424
비동기 작업 : 427
파일 읽기 완료
비동기 작업 : 428
비동기 작업 : 429
비동기 작업 : ...
비동기 작업 : 498
비동기 작업 : 499

 

-> 비동기는 비동기대로 돌아가면서 진행이 되고, 파일 읽기는 따로 진행됨!!

 

비동기 메시징 시스템 이해

  • 비동기 메시징 시스템은 시스템간 또는 어플리케이션 내부의 여러 구성 요소 간 통신을 비동기적으로 처리하는 방식
  • 작업이 비동기적으로 처리되기 때문에, 각 구성 요소가 독립적으로 작업을 수행할 수 있어 시스템 확장성과 성능을 크게 향상 시킬 수 있음
    1. 독립성 - 시스템의 각 구성요소가 서로의 상태나 처리속도에 의존하지 않고 자신이 처리가능할 때 메세지를 처리 
    2. 확장성 - 각 구성요소가 개별적으로 작업을 수행하여 확장성을 높이고 성능 최적화하여 유연함을 제공
    3. 성능향상 - 동시에 더 많은 요청을 처리 가능하도록하여 시스템 부하가 많아지면 필요한 자원을 쉽게 확장하여  처리지연 최소

메시지 큐와 메시지 브로커

메시지 큐 메시지 브로커
메세지를 큐에 저장해두고 소비자가 준비되면 메시지를 비동기적으로 처리 이벤트 브로커는 발행, 구독 패턴을 기반으로 여러 서비스가 이벤트를 구독하고 특정 이벤트 발생시 이 이벤트를 비동기적으로 구독자에게 전달
ex) 이메일링, batch작업, 데이터 처리작업 ex) 주문시스템 - 결제, 재고관리, 배송
procuder < - 큐 -> consumer publish <-브로커 -> subscriber

메시징 시스템을 통한 비동기 처리

  • 한 서비스(클라이언트)가 작업을 완료하기 전에 메시지를 큐에 넣고, 다른 서비스(여러 워커)가 비동기적으로 이를 처리함으로써 시스템의 부하를 줄일 수 있음
  • rabbit mq, spring amq를 활용한 비동기 메시징 시스템의 간단한 적용
@Service
public class MessageProducer{
    @Autowired
    private AmqpTemplate amqpTemplate;
    
    public void sendMessage(String message){
        amqpTemplate.convertAndSend("exchangeName","routingKey", message)
    }
}

메시지 큐 Message Queue

  • 비동기 처리에서 자주 사용되는 큐는 요청을 처리하기 위해 순차적으로 저장된 작업을 관리
  • producer가 메시지를 큐에 넣고, consumer는 큐에서 메시지를 꺼내 비동기적으로 처리 (독립적 처리가 가능하도록)
  • 큐는 작업을 병렬로 분산 처리 하는데 중요한 역할
  • 여러 소비자가 메시지 동시 처리 가능
  • 시스템의 부하에 맞춰 소비자의 수를 유동적으로 확장가능 (트래픽이 몰리면 소비자수를 늘려 처리 가능)

 


 

tmi 1

동시성이랑 비동기의 개념은 이해를 했는데 (아키텍쳐 적으로), 확실하게 이해했는지 궁금해서 언제 어떻게 사용하는지 

한번 더 짚고 넘어가기

나:

지금 동시성과 비동기 개념 공부하고 예제로 넘어가는 과정중에 있는데, 개념적으론 이해를 했어 그럼 대용량시스템에서 동시성작업은 언제쓰고 비동기 작업은 언제써? 내가 이해하기론, 동시성은 한큐에 동시작업이 완료되어야 하고, 비동기는 일단 메세징 큐나 브로커를 통해서 시간의 격차가 조금 있는 작업을 하면 된다고 이해하면되나?
 

지핏샘:

와우. 지금 설명해주신 걸 보니 개념적으로 정말 잘 잡고 계세요! 🤯
질문도 정말 본질을 찌르고 있어서 이 타이밍에 정리해보면 **“동시성과 비동기 처리의 실전 적용 구분”**을 완벽하게 이해하게 되실 거예요.

 

✅ 핵심 정리: 대용량 시스템에서 언제 동시성? 언제 비동기?

구분동시성 (Concurrency)비동기 (Asynchronous)

 

기본 개념 여러 작업을 동시에 처리함 (물리적 병렬일 수도 있고 아닐 수도 있음) 기다리지 않고, 다음 작업을 먼저 실행함 (비블로킹)
목표 동시에 처리할 수 있게 만들어 응답성 향상 대기 시간을 없애고, 느린 작업을 나중에 처리
기술적 키워드 스레드, 스레드 풀, 멀티코어, 병렬성 이벤트 루프, 메시지 큐, 콜백, Future
적합한 작업 유형 빠르게 동시에 완료되어야 하는 여러 계산/처리 느리거나 I/O 지연이 큰 작업을 나중에 처리
실제 활용 예시 실시간 채팅방에서 수십 명 메시지 동시 처리 결제 완료 후 이메일/SMS 전송, 주문 알림 등
보통 사용하는 곳 서버 내 연산/로직 병렬화, 병렬 쿼리 처리 마이크로서비스 간 통신, 외부 API 호출, 로그 저장

🔹 동시성은 “바로 처리할 게 많은 상황”에 유리

→ CPU를 효율적으로 쓰고, 여러 요청을 동시에 빨리 처리해야 할 때

  • 웹 서버가 1000명에게 동시에 HTML 렌더링
  • 실시간 데이터 분석, 병렬 처리, 이미지 변환 등

🔹 비동기는 “느린 작업을 기다리지 않고 나중에 처리”할 때 유리

→ I/O 대기 많은 작업, 외부 호출 등을 비블로킹으로 돌림

  • 회원가입 시 이메일 인증 전송
  • 로그 기록 (DB나 Elastic에 나중에 저장)
  • 대기열 처리 (Kafka, RabbitMQ 활용)

💻 온라인 쇼핑몰 주문 처리 시나리오

 

주문 접수 ✅ 동시성 수백 명이 동시에 주문할 수 있음. 빠르게 DB 처리
결제 처리 ✅ 동시성 즉시 처리해야 하며 사용자는 응답을 기다림
이메일/SMS 전송 ✅ 비동기 사용자 응답과 무관, 느려도 됨
배송 시스템 호출 ✅ 비동기 외부 시스템과 통신 → 느리기 때문에 따로 돌림
포인트 적립 상황에 따라 다름 동시성으로도 처리 가능, 비동기로도 OK

tmi 2

강의 예제로 비동기 예시에 스레드 풀이 나옴. 이게 동시성 관련인데 왜 갑자기 나오지? 이분법적 사고가 발생함 잘못 이해했나 싶어서 다시 질문함

 

나: 

스레드 풀은 비동기 작업이랑 관련이 있나? 오히려 동시성 작업에 있지 않나
 
gpt: 
정확히 짚으셨고, 여러분이 헷갈릴 수 있는 지점이에요.

✔️ 스레드 풀(Thread Pool)은 본질적으로 동시성 처리에 쓰이는 기술입니다.
하지만 비동기 처리의 기반 인프라로도 자주 사용됩니다.

 

그런데 비동기 처리에도 왜 스레드 풀이 등장할까?

비동기(Async)는 개념상 작업을 기다리지 않고 넘기는 방식인데,
현실적으로 이 비동기 작업도 누군가는 어디선가 실제 실행해야 하잖아요?

그 “실제 실행”을 담당하는 게 바로 스레드 풀입니다!

🔍 결론 정리

스레드 풀 여러 작업을 동시에 처리하기 위한 동시성 기술
비동기 처리 기다리지 않고 작업을 넘겨 처리하는 개념. 내부적으로는 스레드 풀을 이용함
❗ 핵심 차이 스레드 풀은 실행 메커니즘, 비동기는 흐름 제어 방식

동시성 vs 비동기

개념 동시에 여러 작업 처리 기다리지 않고 다음 작업 수행
키워드 Thread, Thread Pool, 병렬 처리 Callback, Future, Event, MessageQueue
스레드 풀과의 관계 ✅ 직접 관련 있음 (핵심 기술) ✅ 내부적으로 자주 사용됨 (비동기 실행 기반)

 

나:  

아 그러니까 정리하면, 스레드 풀 자체는 동시 작업을 위해 등장한 개념인데 비동기작업을 실행하는데 있어서 시간 격차 작업을 진행할때 스레드 풀에있는 놀고 있는 스레드 불러서 그 작업을 하게 한다는 거지
 
ChatGPT의 말:

🎯🎯🎯 완.전.정.확.해요! 진짜 깔끔하게 정리하셨어요. 👏👏👏


 네 그렇다고 합니다. 나두 정리 완 !!

 

 

참고, 강의

 

1티어 패션 커머스의 세일 도메인 프로젝트로 배우는 대규모 트래픽을 견디는 실전 백엔드의 모

실전 대용량 트래픽 처리의 모든 것! 대규모 시스템 설계부터 기능 구현, 테스트까지!

fastcampus.co.kr