| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
- javascript
- junit5
- 테스트자동화
- 문자열
- 인텔리제이
- HashMap
- ArrayList
- 정규식
- 단위테스트
- Java
- input
- html
- 자바문법
- Eclipse
- IntelliJ
- Array
- java테스트
- SpringBoot
- 자바
- math
- 스프링부트
- vscode
- CSS
- list
- junit
- js
- 배열
- Visual Studio Code
- string
- 자바스크립트
- Today
- Total
어제 오늘 내일
[Troubleshooting] WebFlux 도입 전 꼭 알아야 할 주의사항 (BlockHound 사용법) 본문
[Troubleshooting] WebFlux 도입 전 꼭 알아야 할 주의사항 (BlockHound 사용법)
hi.anna 2026. 4. 4. 08:24
MVC에서는 쓰레드 하나가 막혀도(Blocking) 다른 쓰레드 199개는 잘 돌아갑니다.
하지만 WebFlux는 쓰레드가 고작 CPU 코어 수(예: 4개)만큼밖에 없습니다. 하나가 막히면 서버 성능의 25%가 날아가는 셈이죠.
문제는 실수로 JDBC를 쓰거나, Thread.sleep을 써도 컴파일 에러가 안 난다는 것입니다. 배포하고 나서야 서버가 죽는 걸 보게 되죠.
이걸 막아주는 수호신, BlockHound를 소개합니다.
1. BlockHound: "블로킹 코드가 보이면 에러를 뱉어라!"
Reactor 팀이 만든 도구로, 논블로킹 쓰레드(Reactor Thread)에서 블로킹 작업이 감지되면 즉시 예외(BlockingOperationError)를 던져서 테스트를 실패하게 만듭니다.
① 의존성 추가
dependencies {
testImplementation 'io.projectreactor:reactor-test' // 여기에 포함되어 있음
}
② 설정 ( 메서드나 테스트 설정에 추가)
public static void main(String[] args) {
// ★ 앱 시작 시 최상단에 선언!
BlockHound.install();
SpringApplication.run(MyApplication.class, args);
}
③ 효과 확인
이제 아래 코드를 실행하면 에러가 납니다.
Mono.delay(Duration.ofSeconds(1))
.doOnNext(it -> {
try {
Thread.sleep(100); // ❌ BlockHound가 잡아서 에러 냄!
} catch (InterruptedException e) {
e.printStackTrace();
}
})
.subscribe();
개발/테스트 단계에서 Thread.sleep, InputStream.read, JDBC 호출 등을 원천 봉쇄할 수 있습니다. (필수 적용 권장!)
2. 디버깅: "스택 트레이스가 이상해요..."
WebFlux에서 에러가 나면 스택 트레이스(Stack Trace)가 수백 줄이 나오는데, 정작 내 코드는 안 보이고 Reactor 내부 클래스만 잔뜩 보입니다.
비동기라서 "누가 호출했는지" 정보가 런타임에 사라지기 때문입니다.
🛠 해결책 1:
의심 가는 부분에 .checkpoint("설명")를 붙이세요.
flux.map(x -> logicA(x))
.checkpoint("logicA-after") // 에러 나면 이 지점을 알려줌
.flatMap(x -> logicB(x))
.checkpoint("logicB-after")
.subscribe();
에러 로그에 Assembly trace from producer [reactor.core.publisher.FluxMap] : ... logicA-after라고 친절하게 뜹니다.
🛠 해결책 2:
개발 환경(dev)에서는 앱 시작 시 이 옵션을 켜두면, 모든 연산자의 스택 트레이스를 기록합니다. (단, 운영 환경에선 성능 저하가 심하므로 끄세요!)
3. 언제 WebFlux를 쓰면 안 되나요?
WebFlux가 만능은 아닙니다. 오히려 독이 되는 경우도 많습니다.
❌ 1. CPU를 많이 쓰는 작업 (암호화, 동영상 인코딩)
이벤트 루프는 "주문 받고 넘기는 일(I/O)"에 특화되어 있습니다.
주방장(Event Loop)이 직접 요리(CPU 연산)를 하면 주문을 못 받습니다.
이런 작업은 별도 쓰레드 풀이나 MVC가 낫습니다.
❌ 2. 팀원들의 러닝 커브
JPA도 모르는데 R2DBC와 flatMap까지 배우라고 하면 퇴사자가 속출할 수 있습니다.
단순한 CRUD 서비스라면 생산성이 높은 MVC + JPA가 정답입니다.
❌ 3. 복잡한 트랜잭션 로직
쇼핑몰 결제처럼 "A 호출하고, 실패하면 B 호출하고, C 업데이트하고..." 로직이 복잡하면, WebFlux의 콜백 지옥(Callback Hell)보다 더한 Operator Hell을 맛보게 됩니다. 코드를 읽을 수가 없습니다.
'IT > SpringBoot' 카테고리의 다른 글
| [Test] "비동기 코드는 어떻게 테스트해요?" StepVerifier로 스트림 검증하기 (0) | 2026.04.04 |
|---|---|
| [R2DBC] "트랜잭션은 어떻게 걸죠?" Reactive Transactional과 R2dbcEntityTemplate (0) | 2026.04.03 |
| [R2DBC] "WebFlux에서 JPA 쓰면 망합니다!" R2DBC와 Reactive DB 연결 (0) | 2026.04.03 |
| [WebClient] "RestTemplate은 이제 Deprecated!" 비동기 HTTP 요청의 정석, WebClient 사용법 (0) | 2026.04.02 |
| [WebFlux] "컨트롤러가 없다고?" 함수형 엔드포인트(Router & Handler) 작성법 (0) | 2026.04.02 |
