Skip to content

fix(mindrecord): 예외 원문이 화면에 그대로 실린다 2곳 — UiText.DynamicOrResource 가 fallback 을 덮는다 #1882

Closed

Description

@Sadturtleman

작업 유형

bug — 사용자에게 보이는 결함 수정

주 담당 모듈

mindrecord — 마음의 기록

무슨 일이 일어나는가

UiText.DynamicOrResource(value = e.message, …) 가 임의 throwable 의 문구를 그대로 화면에 싣습니다. 마음의 기록에 두 곳 남아 있습니다.

자리 실리는 값
DailyQuestionWriteViewModel.kt:92 questionLoadError — 오늘의 질문 조회 실패
WeeklyReportViewModel.kt:207 LoadPhase.Failed.message — 주간 리포트 조회 실패

UiText.asString() 이 value ?: stringResource(fallbackResId) 라 e.message 가 있으면 fallback 은 쓰이지 않습니다. 두 fallback 문자열은 이미 제대로 된 한국어 안내입니다.

mindrecord_error_daily_question_today_failed  →  오늘의 질문을 불러오지 못했습니다.
mindrecord_error_weekly_report_failed         →  주간 리포트를 불러오지 못했습니다.

왜 지금 올리는가

이건 가정이 아니라 한 번 일어났던 일입니다. 저장소에 그 사고가 테스트 주석으로 남아 있습니다.

feature/mindrecord/data/src/test/java/.../EmotionAnalysisContractTest.kt:112-113

// 필수로 두던 시절에는 여기서 MissingFieldException 이 나 탭 전체가 ErrorBox 였고,
// UiText.DynamicOrResource 가 e.message 를 우선해 영문 예외 원문까지 노출됐다.

그때는 DTO 필드를 옵셔널로 내려 그 예외가 안 나게 막았습니다. 노출 기전 자체는 그대로 살아 있어서, 다른 예외가 그 자리에 오면 같은 일이 다시 납니다. 직렬화 예외 문구·서버 오류 원문·SocketTimeoutException 같은 영문 스택 용어가 그대로 사용자에게 갑니다.

이 저장소는 이미 반대 방향으로 판정했습니다 — 서버 오류 원문은 화면에 내지 않고 로그·텔레메트리로만 보냅니다 (#1339 에서 수신자 흐름에 적용, 커밋 9aeb1e437 에서 재확인).

어떻게 고치는가

  1. 두 자리의 value = e.message 를 걷고 UiText.resource(...) 로 fallback 만 남긴다.
  2. 원문은 잃지 않는다 — ErrorReporter.recordMindRecordFailure 로 보낸다. 단계 enum 은 refactor(mindrecord): 마음의 기록 읽기 실패 계측을 선별해 승격한다 (#964 분리) #1874 (PR refactor(mindrecord): 읽기 실패 계측을 선별해 승격한다 (#1874) #1714) 가 들이는 DAILY_QUESTION_LOAD 를 쓰고, 주간 리포트 몫은 그 PR 이 머지된 뒤 같은 규격으로 하나 더 둔다.
  3. UiText.DynamicOrResource 자체의 처분을 정한다. 이 타입을 쓰는 프로덕션 자리는 위 둘뿐이라, 걷어내면 같은 실수를 다시 할 수 있는 문법이 사라진다. KDoc 이 「서버/예외가 메시지를 주면 그대로」라고 적어 두어 지금은 안티패턴을 권하는 모양입니다. 다만 core:ui 는 담당이 다르므로(reconcile-issue-metadata.mjs:49), 이 이슈는 소비처 0 으로 만드는 데까지 하고 타입 삭제는 별건으로 넘긴다.
  4. 회귀를 잠근다 — 두 ViewModel 이 실패했을 때 상태에 실리는 UiText 가 Resource 인지 단언한다. value = e.message 를 되살리면 빨개져야 한다.

완료 조건

  • git grep "DynamicOrResource" -- '*/src/main/*' 이 core/ui 의 타입 정의 외 0건
  • 두 화면의 실패 안내가 기존 한국어 fallback 문자열로 고정된다
  • 두 실패가 ErrorReporter 로 단계 키와 함께 기록된다 (원문 유실 없음)
  • 되돌림을 잡는 단언이 붙는다 — 그 줄을 되살리면 실패하는 것을 실제로 확인한 근거를 PR 에 적는다
  • UiText.DynamicOrResource 타입 삭제는 후속 이슈로 분리한다 (core:ui 담당 몫)

겹침

Activity

  1. github-actions commented on Sep 4, 2026

    @github-actions
    Contributor

    이 이슈는 필수 메타데이터를 판정할 수 없어 자동으로 닫았습니다.

    • 작업 유형이 없거나 허용된 값이 아닙니다.
    • 주 담당 모듈이 없거나 허용된 값이 아닙니다.

    이슈 등록 양식에 맞게 본문을 보완한 뒤 다시 열어 주세요.

  2. github-actions commented on Sep 4, 2026

    @github-actions
    Contributor

    bug 이슈는 사이드바 Fields > Priority 로 심각도를 지정해야 합니다. 판정 기준:

    • Urgent: 치명 — 크래시·데이터 소실·보안 무력화·핵심 경로 차단·가짜 성공
    • High: 심각 — 실패·틀린 값의 정상 위장, 핵심 기능 무동작
    • Medium: 불편 — 우회로가 있는 오동작·틀린 표시, 핵심 흐름은 유지
    • Low: 경미 — 문구·정렬·마감 품질 흠, 기능 영향 없음

    값이 비어 있어도 이슈를 닫지는 않습니다. 이 안내는 이슈당 한 번만 답니다.

  3. added
    pr-open이 이슈를 구현하는 PR 이 열려 있다 — base 가 기본 브랜치가 아니어도 드러낸다
    on Sep 4, 2026
  4. removed
    pr-open이 이슈를 구현하는 PR 이 열려 있다 — base 가 기본 브랜치가 아니어도 드러낸다
    on Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:mindrecord마음의 기록 기능 영역bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions