본문으로 건너뛰기

예외 · 에러 표시 · 로깅

본 문서는 실패를 어디서 잡고, 사용자에게 무엇을 보여주며, 무엇을 기록하는지를 정의합니다.

1. 책임 분담

실패를 각 화면이 개별적으로 처리하면 표시 방식이 화면마다 달라지고 누락이 생깁니다. 공통 처리와 화면 처리의 경계를 고정합니다.

계층 책임
HTTP 인터셉터 (shared/api) 에러 응답 해석, 인증 만료 처리, 재시도, 관측 전송
전역 에러 핸들러 (app) 처리되지 않은 예외 포착, 관측 전송
화면 (pages) 사용자에게 보여줄 내용과 위치 결정

인터셉터는 무엇이 일어났는지를 판별하고, 화면은 무엇을 보여줄지를 정합니다. 인터셉터가 토스트를 띄우기 시작하면 화면이 표시를 통제할 수 없게 됩니다.

2. 에러 분류

응답을 다음 다섯 가지로 분류하고, 분류에 따라 처리 위치가 갈립니다.

분류 조건 처리 위치 사용자에게
네트워크 실패 응답 없음, 타임아웃 인터셉터가 재시도 후 화면에 전달 연결 문제 안내와 재시도 수단
인증 만료 401 인터셉터가 세션 정리 후 로그인 이동 이동 사유 안내
권한 없음 403 화면 접근 불가 안내
입력 오류 400, 422 화면 필드별 메시지
서버 오류 5xx 화면 일시적 오류 안내와 재시도 수단

401만 인터셉터가 이동까지 처리합니다. 세션이 끊긴 상태에서 화면이 각자 판단하면 여러 화면이 동시에 로그인으로 이동시키려 하기 때문입니다.

3. 사용자에게 보여줄 것

3.1 메시지 원칙

구분 준수 지침 (Do) 금지 지침 (Don't)
내용 무엇이 실패했고 다음에 무엇을 할 수 있는지 씁니다 기술 용어와 상태 코드를 그대로 노출합니다
어조 사실을 진술합니다 사용자를 탓하거나 사과를 반복합니다
출처 서버가 준 사용자 대상 메시지를 우선 사용합니다 프론트엔드가 임의로 문구를 지어냅니다
내부 정보 추적 식별자만 노출합니다 스택 트레이스, 쿼리, 내부 식별자를 표시합니다

서버가 사용자 대상 메시지를 내려주면 그것을 표시합니다. 프론트엔드가 상태 코드를 보고 문구를 만들면 서버가 아는 맥락이 소실됩니다.

문의를 위해 추적 식별자를 함께 보여줍니다. 사용자가 그 값을 전달하면 로그에서 해당 요청을 찾을 수 있습니다.

3.2 표시 위치

실패의 범위로 결정합니다.

범위 표시 위치
화면 전체를 그릴 수 없음 화면 영역 전체를 에러 상태로 대체
화면 일부 영역만 실패 해당 영역만 에러 상태로 대체
사용자 동작의 결과 토스트 또는 동작 지점 인근
입력값 문제 해당 필드 아래

목록 조회가 실패했는데 토스트만 띄우고 빈 목록을 보여주는 것을 금지합니다. 사용자는 데이터가 없는 것으로 오해합니다. 실패한 영역은 실패했음을 그 자리에서 표시합니다.

3.3 재시도

일시적 실패(네트워크, 5xx)에는 재시도 수단을 함께 제공합니다. httpResourcereload()를 호출하는 버튼이면 충분합니다.

인터셉터의 자동 재시도는 조회 요청에만 적용합니다. 변경 요청을 자동 재시도하면 중복 처리가 발생할 수 있습니다.

4. 전역 에러 핸들러

처리되지 않은 예외를 포착합니다. 기본 제공되는 리스너를 등록합니다.

// app/app.config.ts
providers: [provideBrowserGlobalErrorListeners()]

전역 핸들러의 역할은 기록과 최소한의 안내입니다. 여기서 업무 로직을 수행하지 않습니다. 이 지점에 도달했다는 것은 예상하지 못한 상태라는 뜻이며, 추가 로직은 상황을 악화시킬 수 있습니다.

5. 로깅

5.1 무엇을 기록하는가

기록 기록하지 않음
실패한 요청의 경로와 상태 코드 요청 본문 전체
추적 식별자 인증 토큰
발생 화면의 라우트 개인식별정보 (이름, 연락처, 주민번호 등)
브라우저와 화면 크기 사용자가 입력한 값

주의

개인정보와 토큰을 로그에 출력하는 것을 금지합니다

개발 중 편의로 추가한 console.log(response)가 운영 빌드에 남으면 브라우저 콘솔과 관측 도구에 개인정보가 그대로 축적됩니다. 응답 객체 전체를 출력하는 습관이 가장 흔한 경로입니다. 필요한 필드만 골라 출력합니다.

5.2 콘솔 사용

console.log는 개발 중 임시 확인에만 사용하고 커밋하지 않습니다. 운영에서 의미를 갖는 기록은 관측 도구로 보냅니다.

ESLint의 no-console 규칙으로 차단하되, console.error는 전역 핸들러에서 필요하므로 예외로 둡니다.

5.3 관측

관측 도구 도입 여부는 프로젝트가 결정합니다. 도입하면 다음을 보냅니다.

  • 처리되지 않은 예외
  • 5xx 응답
  • 네트워크 실패

400·403 같은 정상적인 거부는 보내지 않습니다. 잡음이 되어 실제 문제를 가립니다.

전송 코드는 shared/api/에 두고 인터셉터와 전역 핸들러만 호출합니다. 화면이 직접 관측 도구를 호출하는 것을 금지합니다.

6. 개발 환경과 운영 환경

항목 개발 운영
콘솔 상세 출력 허용 금지
스택 트레이스 화면 표시 허용 금지
원본 에러 객체 보존 보존 보존 (기록용). 화면에는 미표시

빌드 설정으로 분기하며 런타임 조건문으로 판단하지 않습니다. 런타임 분기는 운영 번들에 개발용 코드를 남깁니다.

7. 금지 사항

금지 사유
화면마다 401을 개별 처리 여러 화면이 동시에 로그인 이동을 시도합니다
인터셉터에서 토스트 표시 화면이 표시를 통제할 수 없게 됩니다
조회 실패를 빈 상태로 표시 사용자가 데이터 없음으로 오해합니다
변경 요청의 자동 재시도 중복 처리가 발생합니다
스택 트레이스·내부 식별자 화면 노출 내부 구조가 드러납니다
응답 객체 전체를 콘솔 출력 개인정보와 토큰이 함께 출력됩니다
console.log 커밋 운영 빌드에 남습니다
400·403을 관측 도구로 전송 잡음이 실제 문제를 가립니다
© 2026 dev.goraebap