Post

[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.