[Trouble Shooting] ClientAbortException : Broken Pipe 대응
[Trouble Shooting] ClientAbortException : Broken Pipe 대응
1. 에러 상황 요약
엑셀 다운로드 기능에서 종종 이런 로그가 찍힌다.
1
2
org.apache.catalina.connector.ClientAbortException
Caused by: java.io.IOException: Broken pipe
스택트레이스를 보면 보통 다음과 같은 흐름이다.
- SXSSFWorkbook.write
- ZipOutputStream.close
- OutputBuffer.write
- Broken pipe
2. Broken pipe는 무슨 뜻일까?
먼저 용어부터 정확히 보자.
✔ Broken pipe란?
이미 끊어진 네트워크 연결에 데이터를 쓰려고 할 때 발생하는 오류다.
조금 쉽게 말하면:
서버: “여기 엑셀 파일 다 만들었어요!”
클라이언트: (이미 나감)
서버가 뒤늦게 말을 걸었기 때문에 에러가 난 것이다.
3. 왜 엑셀 다운로드에서 자주 발생할까?
(1) 사용자가 다운로드를 취소했을 때
가장 흔한 원인이다.
- 브라우저 탭 닫기
- 뒤로 가기
- 다운로드 취소 버튼 클릭
이건 버그가 아니라 사용자 행동이다.
(2) 엑셀 생성 시간이 길 때
엑셀 다운로드는 생각보다 무겁다.
- DB 조회
- 엑셀 row 생성
- ZIP 압축
- 네트워크 전송
이 중간에 클라이언트가 “너무 오래 걸린다”고 판단하면 연결을 끊는다.
3) XLSX 파일의 구조적 특성
XLSX는 ZIP 파일이다.
- 파일이 끝날 때 메타데이터를 작성
- close() 시점에 write가 발생
그래서 에러가 마지막에 터지는 경우가 많다.
4. 이 에러는 장애일까?
아니다.
Tomcat 예외 이름을 보면 힌트가 있다.
ClientAbortException
의미 그대로:
클라이언트가 요청을 중단했다 서버 코드가 틀렸다는 뜻이 아니다.
5. 그런데 왜 ERROR 로그로 보일까?
Tomcat은 네트워크 write 실패를 예외로 던질 수밖에 없다. 하지만 이걸 그대로 ERROR로 찍으면 문제가 생긴다.
- 로그에 ERROR가 쌓임
- 장애처럼 보임
- 실제로는 조치 불가
6. 실무에서의 트러블슈팅 방법
(1) 로그 레벨부터 확인
이 에러가 많다고 해서 바로 코드를 고치지 말자.
먼저 확인할 것:
- 사용자 취소 가능한 기능인가?
- 대용량 다운로드인가?
그렇다면 정상 로그일 가능성이 높다.
(2) 코드에서 이렇게 처리한다
1
2
3
4
5
6
7
8
9
catch (ClientAbortException e) {
// 사용자가 연결을 끊은 경우 // ERROR로 찍지 않는다
} catch (IOException e) {
if (e.getMessage().contains("Broken pipe")) {
// DEBUG 레벨 }
else {
throw e;
}
}
핵심: 무시해도 되는 예외를 구분하는 눈
(3) “다 고쳐야 한다”는 생각 버리기
이 에러는:
- 재시도해도 해결 안 됨
- 서버에서 막을 수도 없음
없애는 게 목표가 아니다.
7. 그럼 언제 진짜 문제일까?
아래 경우라면 선배에게 바로 물어봐야 한다.
- 작은 엑셀에서도 반복 발생
- 응답 시작도 전에 바로 터짐
- 특정 API에서만 계속 발생
- 배포 이후 갑자기 증가
이 경우는:
- 타임아웃 설정
- 프록시 / 로드밸런서
- 필터 체인 문제
일 가능성이 있다.
This post is licensed under CC BY 4.0 by the author.