Manus에서 모든 스킬 실행
원클릭으로
원클릭으로
원클릭으로 Manus에서 모든 스킬 실행
시작하기backpressure
스타1
포크0
업데이트2026년 1월 29일 12:49
Backpressure 개념, 전략, 구현 가이드
설치
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SKILL.md
readonly메뉴
Backpressure 개념, 전략, 구현 가이드
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
코드 품질 가이드, 클린 코드 원칙, 리팩토링 패턴
Reactive Streams 디버깅 전략, 로깅, 에러 추적
Reactive Operator 구현 패턴, 체이닝, 변환
Reactive Streams 전체 규약 (39개 규칙) 상세 설명
테스트 작성 전략, JUnit 5, Reactive Streams TCK
| name | backpressure |
| description | Backpressure 개념, 전략, 구현 가이드 |
Backpressure는 데이터 생산자(Publisher)가 소비자(Subscriber)보다 빠를 때 발생하는 문제를 해결하는 메커니즘입니다.
빠른 생산자 (수도꼭지)
💧💧💧💧💧
↓↓↓↓↓
┌─────────────────┐
│ Buffer Tank │ ← 버퍼가 가득 차면?
│ 💧💧💧💧💧💧💧 │ 1. 넘친다 (데이터 손실)
└────────┬────────┘ 2. 막힌다 (블로킹)
↓ 3. 수도꼭지 잠근다 (Backpressure!)
느린 소비자 (배수구)
💧
Publisher Subscriber
│ │
│────── data ───────────────>│
│────── data ───────────────>│
│────── data ───────────────>│ ← 처리 못함!
│────── data ───────────────>│ ← OutOfMemory!
│ │
Subscriber Publisher
│ │
│────── request(2) ─────────>│ "2개 줘"
│<─────── data ──────────────│
│<─────── data ──────────────│
│ │
│────── request(1) ─────────>│ "1개 더 줘"
│<─────── data ──────────────│
│ │
subscription.request(n);
public class DemandTracker {
private final AtomicLong demand = new AtomicLong(0);
public void request(long n) {
// demand 추가 (overflow 방지)
long current;
long next;
do {
current = demand.get();
if (current == Long.MAX_VALUE) {
return; // unbounded
}
next = current + n;
if (next < 0) {
next = Long.MAX_VALUE; // overflow → unbounded
}
} while (!demand.compareAndSet(current, next));
}
public boolean tryConsume() {
long current;
do {
current = demand.get();
if (current == 0) {
return false; // demand 없음
}
if (current == Long.MAX_VALUE) {
return true; // unbounded
}
} while (!demand.compareAndSet(current, current - 1));
return true;
}
}
┌─────────────────────────────────────┐
│ Publisher → [Buffer] → Subscriber │
│ │
│ request(n)이 올 때까지 버퍼에 저장 │
│ 버퍼가 가득 차면? → 전략 선택 │
└─────────────────────────────────────┘
public class BufferedSubscription<T> implements Subscription {
private final Queue<T> buffer = new ArrayDeque<>();
private final int maxSize;
@Override
public void request(long n) {
while (n > 0 && !buffer.isEmpty()) {
subscriber.onNext(buffer.poll());
n--;
}
}
public void onProduced(T item) {
if (buffer.size() >= maxSize) {
// 전략에 따라 처리
}
buffer.offer(item);
}
}
public void onProduced(T item) {
if (buffer.size() >= maxSize) {
buffer.poll(); // 가장 오래된 것 제거
}
buffer.offer(item);
}
public void onProduced(T item) {
if (buffer.size() >= maxSize) {
return; // 새 아이템 무시
}
buffer.offer(item);
}
public void onProduced(T item) {
if (buffer.size() >= maxSize) {
subscriber.onError(
new IllegalStateException("Buffer overflow")
);
return;
}
buffer.offer(item);
}
public void onProduced(T item) throws InterruptedException {
while (buffer.size() >= maxSize) {
Thread.sleep(10); // 공간이 생길 때까지 대기
// 주의: 데드락 가능!
}
buffer.offer(item);
}
public class ArrayPublisher<T> implements Publisher<T> {
private final T[] array;
@Override
public void subscribe(Subscriber<? super T> subscriber) {
subscriber.onSubscribe(new ArraySubscription<>(subscriber, array));
}
static class ArraySubscription<T> implements Subscription {
private final Subscriber<? super T> subscriber;
private final T[] array;
private int index = 0;
private final AtomicLong requested = new AtomicLong(0);
private final AtomicBoolean cancelled = new AtomicBoolean(false);
@Override
public void request(long n) {
if (n <= 0) {
subscriber.onError(new IllegalArgumentException("n must be > 0"));
return;
}
// demand 추가
long current;
long next;
do {
current = requested.get();
next = current + n;
if (next < 0) next = Long.MAX_VALUE;
} while (!requested.compareAndSet(current, next));
// 데이터 발행
drain();
}
private void drain() {
while (requested.get() > 0 && index < array.length) {
if (cancelled.get()) {
return;
}
T item = array[index++];
subscriber.onNext(item);
// demand 감소 (unbounded가 아닌 경우)
if (requested.get() != Long.MAX_VALUE) {
requested.decrementAndGet();
}
}
// 완료 체크
if (index >= array.length && !cancelled.get()) {
subscriber.onComplete();
}
}
@Override
public void cancel() {
cancelled.set(true);
}
}
}
request(Long.MAX_VALUE)는 "무제한으로 달라"는 의미입니다.
// Backpressure 비활성화 (주의!)
subscription.request(Long.MAX_VALUE);
사용 시기:
reactive-spec: 규약 상세operator-pattern: Operator에서의 Backpressure