에러와 침묵을 설계한다—React 에러 핸들링과 의도적 UX 제약이 가리키는 것

에러와 침묵을 설계한다—React 에러 핸들링과 의도적 UX 제약이 가리키는 것

ErrorBoundary로 실패를 격리하고, AI를 일부러 침묵시키는 두 가지 선택이 동시에 가리키는 것—경험의 품질은 '무엇을 보여주느냐'가 아니라 '무엇을 설계적으로 감추느냐'에서 결정된다.

React 에러 핸들링 ErrorBoundary UX 설계 의도적 제약 Calm Technology DomainError Fallback 전략 프로덕트 사고
광고

프론트엔드 개발자가 에러를 다루는 방식은 생각보다 훨씬 많은 것을 드러낸다. 단순히 콘솔에 빨간 줄이 뜨지 않게 하는 문제가 아니다. 어떤 에러를 사용자에게 보여주고, 어떤 에러를 조용히 처리하며, 어떤 상황에서 앱이 스스로 회복하는가—이 선택들의 총합이 곧 사용자가 체감하는 서비스의 신뢰도다. 최근 velog에 올라온 React 에러 핸들링 심층 분석과, dev.to에서 공개된 AI 저널링 앱 Evengood의 빌드 일지를 함께 읽으면서 이 두 글이 놀랍도록 같은 질문을 향하고 있다는 걸 발견했다. 경험의 품질은 기능의 밀도가 아니라 설계된 제약에서 온다.


선언적 에러 처리: 컴포넌트가 실패를 '책임지지 않는' 구조

기존의 에러 처리 방식을 돌아보면, try-catch는 지극히 명령적이다. 컴포넌트 안에서 직접 에러를 잡고, 상태에 넣고, 그 상태에 따라 UI를 분기한다. 코드를 보면 isLoading, error, data가 한 컴포넌트 안에 뒤엉켜 있고, 이 구조는 컴포넌트가 "나는 성공 케이스를 렌더링하는 존재"가 아니라 "나는 모든 상태를 관리하는 존재"로 변질되게 만든다.

ErrorBoundarySuspense의 조합은 이 구조를 뒤집는다. Profile 컴포넌트는 오직 성공한 데이터가 있다는 전제 하에 UI를 그리고, 에러가 발생하면 React가 가장 가까운 ErrorBoundary를 찾아 fallback을 대신 렌더링한다. 컴포넌트가 실패를 직접 책임지지 않아도 된다. 이건 단순한 코드 정리가 아니라 책임 분리의 철학이다. 에러라는 예외 상황을 '어디서 처리할 것인가'를 미리 선언하는 것이다.

다만 ErrorBoundary가 만능은 아니다. 클릭 이벤트(onClick) 핸들러 내부의 에러, setTimeout 같은 비동기 콜백, 그리고 서버사이드 렌더링 중 발생한 에러는 ErrorBoundary가 감지하지 못한다. 이 경우엔 여전히 try-catch가 필요하다. 핵심은 두 방식을 무작정 섞는 게 아니라 에러의 성격에 따라 전략적으로 배치하는 것이다.


에러를 분류한다는 것: DomainError vs PresentationError

해당 글에서 특히 인상적이었던 부분은 커스텀 에러 클래스 설계다. JavaScript 기본 Error 객체를 상속해 DomainError(비즈니스 로직 위반—중복 닉네임, 권한 없음 등)와 PresentationError(시스템 문제—네트워크 단절, 데이터 포맷 불일치 등)로 나눈다. 이 분류는 단순한 타입 구분이 아니다. 에러의 '의도'를 코드 레벨에서 명시하는 행위다.

DomainError는 사용자에게 직접 알려야 할 정보를 담고 있다. 반면 PresentationError는 사용자가 이해하기 어렵고, 알아도 할 수 있는 게 없는 시스템 오류다. fallback UI 전략도 이 분류를 따라간다. 비즈니스 로직 실패엔 "요청 처리에 실패했습니다"를, 시스템 오류엔 "일시적인 오류가 발생했습니다"를 보여준다. 같은 에러 화면이지만 사용자에게 전달하는 맥락이 전혀 다르다. 이건 에러 메시지도 UX 카피라이팅이라는 걸 상기시킨다.


AI가 일부러 말하지 않는 앱: 의도적 침묵의 프로덕트 철학

dev.to에 연재 중인 Evengood 빌드 일지는 전혀 다른 맥락에서 시작하지만, 같은 결론에 도달한다. 빌더는 AI 저널링 앱 시장을 분석하면서 흥미로운 구조적 문제를 발견한다. Rosebud, Mindsera, Replika 등 모든 경쟁 제품의 핵심 가치 제안이 "AI가 더 많이 말한다"는 방향을 향하고 있다는 것. 더 깊이 파고들고, 더 많이 코칭하고, 더 자주 응답한다.

그가 주목한 건 2025년 브라운대학교 연구였다. LLM 기반 '치료 챗봇'들을 분석한 이 연구는 "deceptive empathy"—'I hear you', 'that sounds so hard' 같이 실제 공감 능력 없이 공감을 흉내 내는 표현들—를 가장 심각한 윤리적 문제로 꼽았다. 경쟁사들의 실패 모드는 기술적인 게 아니라 구조적이었다. AI가 너무 많이 말한다.

Evengood의 응답은 두 가지였다. 첫째는 'Quiet Mode'—사용자가 "아빠가 지난주에 돌아가셨어"나 "공황 발작이 왔었어" 같은 무거운 내용을 입력하면 AI가 침묵하고, 화면엔 "어떤 날들은 다시 해석할 필요가 없어요. 오늘 밤은 스스로에게 조심스럽게 대하세요"라는 한 줄만 남긴다. 팝업도, 이모지도, 애널리틱스 이벤트도 없다.

두 번째는 'Witness Mode'—매주 한 번(기본값 일요일 저녁), AI는 60초 저널을 받고 단 한 문장만 돌려준다. 열다섯 단어 이하. 내용의 의미가 아니라 형식에 대해—반복된 단어, 부재한 주제, 예상치 못한 표현. 예를 들면 이런 식이다: "오늘 밤 당신은 '괜찮아'라는 단어를 세 번, 세 가지 다른 방식으로 사용했습니다." 그리고 4초간 침묵. 그리고 화면엔 "내일 다시 돌아오세요."가 전부다.


경쟁사가 복사할 수 없는 이유

빌더의 분석이 예리한 지점은 여기다. 이 기능은 기술적으로 어렵지 않다. 새 LLM 시스템 프롬프트, 몇 개의 localStorage 키, 정규식 가드 모듈—코드 변경량은 약 2,800줄이고 AI 코딩 도구로 7분 만에 빌드됐다. 경쟁사가 따라 하지 않는 이유는 기술이 아니라 비즈니스 구조 때문이다.

월간 리텐션 지표로 움직이는 구독 저널링 앱은 아무 일도 없는 평온한 날에 세션 길이를 늘려야 한다. AI가 주 1회 의도적으로 덜 말하는 날을 설계한다는 건 모든 대시보드에서 '퇴행'으로 읽힌다. 그리고 철학적으로도 불가능하다. "AI가 당신의 코치입니다"라는 브랜드 포지션을 가진 제품이 "AI가 오늘은 당신 곁에 조용히 앉아 있을 뿐입니다"라고 말하는 순간, UVP 전체를 다시 써야 한다.


두 설계가 만나는 지점

React ErrorBoundary의 fallback 전략과 Evengood의 Witness Mode는 표면적으로 전혀 다른 문제를 다룬다. 하나는 DX와 코드 아키텍처, 다른 하나는 프로덕트 철학과 AI 윤리다. 그런데 두 접근이 공유하는 핵심 직관이 있다. 좋은 경험은 더 많이 보여주는 것이 아니라, 무엇을 언제 보여주지 않을지를 설계하는 데서 온다.

ErrorBoundary의 3단계 fallback 전략—Global, Feature, Component 레벨—은 에러가 발생했을 때 앱 전체를 멈추지 않고 피해를 격리한다. 사용자는 에러가 발생했다는 사실을 알지만, 그 에러가 얼마나 심각한지, 시스템 어디에서 발생했는지는 알 필요가 없다. Evengood의 LLM 응답 가드도 같은 원리다: 모델이 spec에 위반되는 문장을 반환하면 기본 라인 "tonight, i'm just sitting with you" 로 클라이언트에서 교체하고, 사용자는 아무것도 알지 못한다. 실패는 조용히 처리된다.

빠른 AI 프로토타이핑 시대에 이 감각은 더 중요해진다. v0.dev로 30분 만에 UI를 뽑아내고, Claude로 비즈니스 로직을 채우고, Cursor로 에러 처리를 붙이는 워크플로우가 일반화되면서, 오히려 '무엇을 안 만들 것인가'의 판단이 제품의 품질을 결정하는 핵심 변수가 된다. Evengood 빌더가 명시적으로 나열한 "의도적으로 만들지 않은 것들"의 목록—streak 카운터, Witness Night 푸시 알림, 배지, 감정 트렌드 차트—은 어쩌면 기능 목록보다 더 중요한 설계 문서다.


전망: 제약이 차별화가 되는 시대

AI가 코드 생성 속도를 평준화하면서 역설적으로 설계 판단의 가치가 올라가고 있다. 기능을 추가하는 건 쉬워졌지만, 어떤 기능을 추가하지 말아야 하는지, 에러가 났을 때 사용자에게 얼마나 솔직해야 하는지, AI가 침묵해야 할 순간은 언제인지—이 판단들은 여전히 사람이 해야 한다.

React 에러 핸들링에서 DomainErrorPresentationError를 나누는 습관, 그리고 Evengood의 Witness Mode처럼 AI가 말을 아끼는 제품 설계—이 두 가지는 모두 같은 곳에서 출발한다. 사용자의 맥락을 먼저 읽고, 그 맥락에 맞게 경험을 조각하는 것. 에러도, 침묵도, 결국은 사용자에게 보내는 신호다. 그 신호를 설계하는 것이 프론트엔드 개발자의 진짜 일이다.

출처

더 많은 AI 트렌드를 Seedora 앱에서 확인하세요