최범균 님의 "주니어 백엔드 개발자가 반드시 알아야 할 실무 지식" 책을 정리한 포스팅 입니다.
1. 동기 연동과 비동기 연동
동기 연동
- 순차적으로 진행됨
- ✅ 외부 연동 시, 외부 연동 실패가 전체 기능의 실패인지 확인해야 함
- ✅ 외부 연동 시, 외부 서비스의 응답 시간 고려하기
- ⚠️ 전체 서비스가 먹통될 수 있음
비동기 연동
- 한 작업이 끝날때까지 기다리지 않고 바로 다음 작업을 처리함
- ✅ 외부 연동 결과가 즉시 필요하지 않을 경우
- ✅ 연동에 약간의 시차가 생겨도 문제가 생기지 않을 경우
- ✅ 실패했을 때 재시도가 가능한 경우
- ✅ 실패했을 때 수동으로 복구 가능한 경우
예시) 비동기 연동
더보기
- 로그인 시, 포인트 적립
- 주문이 들어오면 판매자에게 푸시 보내기
- 학습을 완료하면 포인트 적립
- 컨텐츠 등록 시 검색 서비스에도 등록
- 인증 번호 요청 시 SMS로 인증 메시지 발송
2. 별도 스레드로 실행하기
코드) 스레드 풀 사용
더보기
ExecutorService executor = Executors.newFixedThreadPool(50);
public OrderResult placeOrder(OrderRequest req) {
// ...
executor.submit(() -> pushClient.sendPush(pushData));
return successResult(...);
}
가상 스레드
- 런타임에서 관리하는 경량 스레드 (네이티브 스레드 ❌)
- ✅ 적은 메모리를 사용함
- ➡️ 한 번에 만들 수 있는 스레드 수가 많음
예시) 대용량 푸쉬 메시지 발송
더보기
- 10만 개의 푸쉬 메시지를 비동기로 발송할 경우, 10만개의 스레드를 생성해야 함
- ⚠️ 메모리 부족 ("스레드 1개의 메모리 * 10만" 메모리가 필요)
- ‼️ 사용량에 비해 많은 메모리를 확보해야 함
- ➡️ 가상 스레드를 활용하여 적은 메모리로 스레드 생성 가능
3. 메시징
- 서로 다른 시스템이 비동기적으로 데이터를 주고받는 통신 방식
- 메시지 브로커를 매개로 사용함
이점
구분 | 세부 내용 | 설명 |
느슨한 결합 | 시간적 결합 해제 | 소비자가 꺼져 있어도 브로커가 메시지를 버퍼링 |
주소/프로토콜 결합 해제 | 생산자는 소비자의 위치·언어·기술 스택을 몰라도 됨 | |
모델 결합 완화 |
동기 호출처럼 즉시 응답 스키마에 묶이지 않음
|
|
장애 격리 | 생산자 장애 | 메시지는 브로커에 남아 있어 재기동 후 이어받기 가능 |
소비자 장애 | 특정 소비자만 느려지거나 중단되어도 다른 서비스에는 영향 없음 | |
Poison Message 격리 | 반복 실패 메시지는 DLQ(Dead Letter Queue)로 격리 처리 | |
확장성 | 소비자 수평 확장 | 컨슈머 그룹에 인스턴스 추가만으로 병렬 처리량 증가 |
읽기 스케일아웃 | 소비자마다 독립 Offset 보유 → 각자 원하는 속도로 메시지 소비 | |
흐름 제어 | 소비자 측량 조절 | prefetch, max.poll.records, prefetchCount 등으로 처리량 조절 |
백프레셔 | 소비자가 느리면 가져오는 속도를 낮추거나 일시 중단 가능 |
메시지 생성 고려사항
- DB와의 연동 시, db 커밋이 완료된 후 메시지를 전송해야 함
메시지 소비 고려사항
고려사항 | 설명 | 목적 |
메시지에 고유 ID 부여 + 처리 여부 기록 |
메시지마다 messageId를 부여 및 처리 이력을 DB에 기록 | 동일 메시지가 여러 번 도착해도 중복 처리 방지 |
API 멱등성 보장 | 같은 요청이 여러 번 들어와도 결과가 변하지 않도록 API 설계 | 재수신·재처리 상황에서도 데이터 정합성 보장 |
메시지 소비 모니터링 | 큐 적체 상태 지속 모니터링 | 큐가 가득 차면 소비자뿐 아니라 생산자까지 영향 → 시스템 안정성 확보 |
예시) API 멱등성 보장
더보기
- PUT
- UPSERT
- idempotency-key (요청마다 고유 키 부여)
- 조건부 요청: ETag/If-Match, Version field 등
- CAS/원자 연산 (값이 내가 기대한 상태일 떄만 새 값으로 원자적으로 바꾸고, 아니면 실패)
예시) 메시지 소비 모니터링
더보기
- Lag
- 메시지 수
- 처리 속도
메시지 종류
종류 | 설명 | 특징 |
이벤트 | 어떤 일이 발생했음을 알려주는 메시지 | 해당 이벤트에 관심있는 소비자가 수신해서 알맞게 처리함 |
커맨드 | 상태 변경을 명령하는 메시지 | 메시지를 수신할 측의 기능 실행에 초점이 맞춰져 있음 |
4. 트랜잭션 아웃박스 패턴
- 먼저 해당 데이터를 DB에 저장하기
- 저장된 메시지를 읽어 메시징 시스템에 전송하기
- 메시지 중계 프로세스가 주기적으로 읽어서 메시징 시스템에 전송함
- ✅ 메시지를 생성할 때 유실되지 않도록 하는 방법
5. 배치 전송
- 대표적인 비동기 연동 방법
예시
더보기
- 결제 승인 데이터를 모아 다음날에 보내기
- 택배 발송 요청 데이터를 1시간 간격으로 보내기
실행 과정
- 전송할 데이터 조회
- 조회한 결과를 파일로 기록
- 파일을 연동 시스템에 전송
- 파일 전송 프로토콜 (FTP, SFTP)
- 명령어 (SCP)
재처리
- 지정한 시간에 전송하지 못할 경우 발생 (네트워크 오류 등)
- ➡️ 수동으로 배치를 쉽게 실행할 수 있도록 API 만들어두기