오류는 그 동작이 시작된 자리에 보여준다. 토스트는 보여줄 자리가 없는 제자리·백그라운드 동작에만.
- 모달·폼에서 저장·만들기·보내기가 실패할 때
- 확인 모달에서 삭제·나가기·제거가 실패할 때
- 목록·대화처럼 화면 영역 전체가 불러와지지 않을 때
- 복사·인라인 이름 변경·동기화·메시지 전송처럼 제자리에서 끝나는 동작이 실패할 때
오류가 난 동작이 어디서 시작됐나?
├─ 열려 있는 모달·폼 안 ───────────────────── 그 모달 안에 표시, 모달 유지 (토스트 X)
│ 입력값 문제 → 입력칸 아래(TextField error)
│ 요청 실패 → 모달 안 InlineAlert
├─ 확인 모달의 확인 버튼 ─────────────────── ConfirmDialog error, 닫지 않음 → 바로 다시 시도
├─ 화면 안 영역 전체가 못 뜸 ──────────────── 그 영역에 InlineAlert + 다시 시도 버튼
└─ 제자리·백그라운드 동작 ─────────────────── 토스트 (danger)
- 쓰는 곳: 채팅방 이름 바꾸기, 새 팀 채팅, 방장 넘기기, 팀 공유, 새 프로젝트(GitHub 연결·만들기), 섹션·폴더 모달, 멤버 내보내기
- 요청 상태는 React Query mutation 의
error/isError를 그대로 쓴다. 모달을 닫을 때mutation.reset()으로 지워 다시 열었을 때 남지 않게 한다.
- 쓰는 곳: 프로젝트·섹션·개인 채팅 삭제, 멤버 제거·프로젝트 나가기, 팀 채팅 삭제·나가기, 공유 취소
- 실패해도 모달을 닫지 않는다. 확인 버튼이 곧 "다시 시도".
- 쓰는 곳: 채팅 목록·참여자 목록·저장소 목록·동기화 상태 조회 실패
- 쓰는 곳: 복사 실패, 사이드바·헤더 인라인 이름 변경, 동기화 요청, 메시지 전송, 첫 메시지로 채팅 자동 생성, 참여자 불러오기
- 사용자 잘못이 아닌 상태 알림(예: "해당 프로젝트가 삭제되었습니다.")은 오류가 아니라
toast.info.
- 원인 + 다음 행동:
friendlyErrorMessage(error, context)로 사람 말로. 서버 메시지·상태 코드를 그대로 노출하지 않는다. - 한 곳에만: 같은 오류를 모달 안과 토스트에 동시에 띄우지 않는다.
- 남겨 둔다: 사용자가 읽고 고쳐야 하는 오류는 사라지는 토스트에 두지 않는다.
- 스크린리더: 오류만
role="alert"(InlineAlert danger·Toast danger).
| Do | Don't |
|---|---|
| 이름 바꾸기 실패 → 입력칸 아래 오류, 모달 유지 | 입력칸 아래 오류 + 같은 내용 토스트 |
| 삭제 실패 → 확인 모달 안 오류, [삭제] 로 다시 시도 | 확인 모달을 닫고 토스트 |
| 복사 실패 → 토스트 "텍스트를 직접 선택해 복사해주세요" | 복사 실패를 모달로 띄움 |
- 2026-09-26: 오류 토스트 28곳을 분류해 정리. 모달 안 중복 토스트 3곳 제거, 토스트만 있던 모달 7곳은 모달 안 InlineAlert 로, 확인 모달 실패 5곳 + 공유 취소는 모달 유지 + 안에 표시, "프로젝트 삭제됨"은 info 로. 제자리·백그라운드 11곳은 토스트 유지. 확인 모달 실패도 토스트로 둘지 검토했으나 바로 다시 시도할 수 있게 모달 안 표시로 결정.
- 같은 정리 중 확인 없이 실행되던 공유 취소에 확인(간단)을 추가.