6개월 동안 에러를 묵인했다가 사용자들이 모든 에러를 찾아내기까지
요약
에러를 catch한 뒤 적절한 후속 조치를 취하지 않는 '침묵하는 실패(Silent Failure)' 패턴의 위험성을 경고합니다. 에러를 단순히 잡는 것에 그치지 않고 사용자에게 알리고 가시화하는 것이 서비스 운영의 핵심임을 강조합니다.
핵심 포인트
- 에러를 catch한 후 아무 조치도 취하지 않으면 대시보드는 정상이나 사용자는 피해를 입음
- 침묵하는 실패는 사용자 경험을 저해하고 재시도 횟수를 높이는 원인이 됨
- 에러 발생 시 사용자에게 상황을 알리고 해결 방법(재시도 등)을 제시해야 함
- 에러 핸들링의 목적은 충돌 방지를 넘어 실패를 가시화하는 것에 있음
나는 내 에러 처리 (error handling) 방식이 "충분히 괜찮다"고 생각하며 6개월을 보냈다.
모든 곳에 try/catch 블록이 있었다. 콘솔에 로그를 남겼다. 심지어 화려한 Sentry 대시보드도 갖추고 있었다.
하지만 사용자들은 여전히 망가진 흐름을 겪고 있었다. 파일이 업로드되다가 사라지거나, 확인 없이 결제가 진행되거나, 폼 제출이 소리 없이 실패하는 등의 문제였다.
문제는 내가 에러를 잡지 못하고 있었던 것이 아니었다. 에러를 잡고 나서 아무것도 하지 않았던 것이 문제였다.
침묵하는 실패 패턴 (The Silent Failure Pattern)
내 코드는 다음과 같은 모습이었다:
try {
await uploadFile(file);
await notifyUser("Upload complete");
...
그 // TODO 주석 말인가? 그것은 6개월 동안 그 자리에 머물러 있었다.
그동안 파일 업로드가 실패할 때마다 다음과 같은 일이 일어났다:
- 사용자는 결코 끝나지 않는 로딩 스피너를 보았다.
- 파일은 업로드되지 않았다.
- 사용자는 무언가 잘못되었다는 사실을 전혀 알지 못했다.
- 사용자는 다시 시도했다. 그리고 또 시도했다. 그러다 결국 포기했다.
나를 깨운 수치들
한 고객의 불만 제기 이후, 나는 마침내 우리의 분석 데이터 (analytics)를 파헤쳐 보았다. 내가 발견한 것은 다음과 같다:
- 파일 업로드의 23%가 소리 없이 실패함 — 대략 4번 중 1번의 업로드가 그냥 사라졌다.
- 평균 재시도 횟수: 2.7회 — 사용자들이 포기하기 전까지 거의 3번씩 시도했다.
- 에러 알림 0건 — 우리가 모든 에러를 잡고(catch) 있었기 때문에 우리의 Sentry 대시보드는 "정상"으로 표시되었다.
우리는 침묵하는 재앙을 운영하고 있었다. 우리의 대시보드는 초록색이었지만, 우리 사용자들은 피해를 입고 있었다.
해결책은 간단했다 (하지만 쉽지는 않았다)
나는 모든 침묵하는 catch를 다음과 같은 패턴으로 교체했다:
try {
await uploadFile(file);
showSuccess("Upload complete!");
...
핵심 원칙:
- 잡고 나서 아무것도 하지 마라 — 최소한 문맥 (context)과 함께 로그를 남겨라.
- 사용자에게 알려라 — "무언가 잘못되었습니다"라고 말하는 것이 무한 로딩보다 낫다.
- 앞으로 나아갈 길을 제시하라 — 재시도, 고객 지원 문의, 다른 형식으로 시도하기 등.
- 에러 유형별로 분류하라 — 네트워크 문제는 권한 문제와는 다른 처리가 필요하다.
결과
이를 적용한 후:
- 조용한 업로드 실패 (Silent upload failures)가 23%에서 0.4%로 감소했습니다.
- 사용자가 보고한 업로드 문제 (User-reported upload issues)가 89% 감소했습니다.
- "파일 누락"에 관한 고객 지원 티켓 (Support tickets)이 주당 15건에서 주당 1건으로 줄었습니다.
하지만 가장 큰 성과는 숫자가 아니었습니다. 무언가 잘못되었을 때, 우리 팀이 화가 난 이메일을 기다리는 대신 즉시 그 사실을 알게 되었다는 점입니다.
진짜 교훈
에러 핸들링 (Error handling)은 단순히 코드가 충돌(crash)하지 않게 만드는 것이 아닙니다. 그것은 실패를 사용자에게, 그리고 팀에게 가시화 (visible) 하는 것에 관한 것입니다.
충돌 (Crash)은 정직합니다. 조용한 실패 (Silent failure)는 거짓말입니다.
당신이 catch (error) { console.log(error) }라고 작성하고 그냥 넘어가 버릴 때마다, 당신은 문제를 해결하는 대신 숨기기로 선택하는 것입니다.
다음에 에러를 잡을(catch) 때는 스스로에게 물어보세요: "만약 이것이 실패한다면, 누가 이 사실을 알아야 하며, 그들은 무엇을 해야 하는가?"
만약 대답이 "아무도"라면, 당신은 아마 에러 핸들러 (error handler)가 없는 것보다 더 큰 문제를 안고 있을 가능성이 높습니다.
운영 환경 (production)에서 발견한 최악의 조용한 실패 (silent failure)는 무엇인가요? 댓글로 남겨주세요 — 저만 혼자인 게 아니라는 걸 느끼고 싶습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기