Skip to content

[FEATURE] 검사 결과 화면 수정#31

Merged
kbh0218 merged 10 commits into
devfrom
feat/#26-scan-result-screen-update
May 16, 2026
Merged

[FEATURE] 검사 결과 화면 수정#31
kbh0218 merged 10 commits into
devfrom
feat/#26-scan-result-screen-update

Conversation

@kbh0218
Copy link
Copy Markdown
Contributor

@kbh0218 kbh0218 commented May 10, 2026

Closes #26

개요

검사 결과 화면에서 기존 안내 문구인 저장 후 바로 접속하거나, 즉시 URL로 이동할 수 있어요. 영역을 URL 검사 결과에 대한 판정 이유 표시 영역으로 변경했습니다.

기존에는 저장 및 URL 이동 기능을 안내하는 문구가 표시되고 있었지만, 검사 결과 화면에서는 사용자가 왜 해당 URL이 안전/주의/위험으로 판정되었는지 이해할 수 있는 정보가 더 중요하다고 판단했습니다.

이번 작업에서는 우선 테스트용 mock 판정 이유 데이터를 구성하고, 검사 결과 상태에 따라 안전/주의/위험에 맞는 판정 이유 문구가 표시되도록 연결했습니다. 추후 백엔드에서 판정 이유 텍스트를 응답으로 전달하면 mock 데이터를 실제 응답 데이터로 교체할 수 있도록 TODO 주석을 남겼습니다.

또한 판정 이유 영역 추가에 맞춰 검사 결과 화면의 위치와 간격을 조정하고, 검사 대상 URL 표시 영역의 글씨 크기도 함께 정리했습니다.

주요 구현 내용

  • 검사 결과 화면의 기존 안내 문구 영역을 판정 이유 표시 영역으로 변경
  • 안전/주의/위험 결과별 판정 이유 mock 데이터 추가
  • 검사 결과 상태에 따라 알맞은 판정 이유 문구 표시
  • 판정 이유 표시용 공통 UI 컴포넌트 추가
  • 판정 이유 문구 최대 글자 수 제한 적용
  • mock 데이터가 테스트용이며 추후 백엔드 응답으로 교체 예정임을 TODO로 명시
  • 검사 결과 화면의 상단 위치 및 요소 간격 조정
  • 검사 대상 URL 표시 영역의 글씨 크기 조정
  • 기존 저장 버튼 및 즉시 URL 접속 버튼 동작 유지
  • 검사 대상 URL 표시 영역 유지

파일별 역할

  • constants/scan-result-reasons.ts: 안전/주의/위험 상태별 테스트용 판정 이유 mock 데이터 및 글자 수 제한 관리
  • components/ui/scan-result-reason.tsx: 판정 이유를 표시하는 공통 UI 컴포넌트
  • app/(tabs)/(home)/scan-result.tsx: 안전 결과 화면에 판정 이유 영역 적용 및 레이아웃 조정
  • app/(tabs)/(home)/scan-result-caution.tsx: 주의 결과 화면에 판정 이유 영역 적용 및 레이아웃 조정
  • app/(tabs)/(home)/scan-result-block.tsx: 위험/차단 결과 화면에 판정 이유 영역 적용 및 레이아웃 조정

해결한 이슈 목록

  • 검사 결과 화면의 기존 안내 문구 영역을 판정 이유 표시 영역으로 변경
  • 안전/주의/위험 결과에 맞는 판정 이유 mock 데이터 작성
  • 검사 결과 상태에 따라 알맞은 판정 이유 문구 표시
  • 추후 백엔드 응답 데이터로 교체할 수 있도록 TODO 주석 작성
  • 판정 이유 문구가 길어져도 화면 레이아웃이 깨지지 않도록 표시 영역 구성
  • 기존 저장 버튼과 즉시 URL 접속 버튼 동작 유지
  • 검사 대상 URL 표시 영역 유지
  • 판정 이유 영역 추가에 맞춰 화면 크기와 위치 조정
  • 검사 대상 URL 글씨 크기 조정

체크 사항

  • 커밋/코딩 컨벤션에 맞게 작성
  • npx tsc --noEmit 통과
  • npm run lint 확인 필요

참고

npm run lint는 기존 파일에서 발생하던 expo-linear-gradient import resolver 오류와 일부 warning으로 실패합니다. 이번 작업에서 수정한 파일의 타입 오류는 없으며, npx tsc --noEmit은 통과했습니다.

Screenshots or Video

안전
안전

주의
주의

위험
위험

@kbh0218 kbh0218 requested review from minsoo0506 and sunm2n May 10, 2026 12:38
@kbh0218 kbh0218 self-assigned this May 10, 2026
@kbh0218 kbh0218 added the feature 기능개발 label May 10, 2026
@kbh0218 kbh0218 force-pushed the feat/#26-scan-result-screen-update branch from a0bfd07 to 8fb766e Compare May 10, 2026 12:43
Copy link
Copy Markdown
Contributor

@sunm2n sunm2n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fontSize: 30이 테마 토큰을 직접 override

  • scan-result.tsx:125-126
  • scan-result-caution.tsx
  • scan-result-block.tsx:82-84

현재 3개의 파일에서 덮어쓰는 의도가 궁금합니다.

resultTitle: {
    ...Typography.display,   // theme.ts:104 → fontSize: 32
    fontSize: 30,            // 매직 넘버로 override
    ...
  },

Typography.display의 32px를 30px로 덮어쓰는 이유가 명확하지 않습니다.
의도된 크기라면 theme.ts에 displayMedium처럼 별도 토큰으로 추가하는 게 일관성 있어 보지 않을까 제안드립니다.

safe: '위험 신호와 차단 이력이 발견되지 않아 안전합니다. 도메인 형식과 URL 패턴이 일반적이며, 알려진 피싱 키워드나 의심 리다이렉트가 없어 접속 전 주소만 한번 더 확인하면 됩니다.',
caution: '일부 의심 신호가 있어 주의가 필요합니다. 도메인 신뢰도나 URL 패턴에서 확인이 필요한 요소가 있어, 로그인이나 결제처럼 민감한 행동 전에는 공식 주소인지 다시 확인하세요.',
danger: '피싱 의심 신호가 강해 위험합니다. 악성 페이지와 비슷한 URL 패턴이나 의심스러운 접근 흐름이 감지되어, 저장하거나 접속하지 말고 공식 주소를 통해 다시 확인하세요.',
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SCAN_REASON_MAX_LENGTH가 백엔드 연동 후엔 무효화 문제

지금 해당 코드를 보면

xport const SCAN_REASON_MAX_LENGTH = 100; // export되어 있으나

  export function getMockScanResultReason(verdict: ScanResultVerdict) {
    return MOCK_SCAN_RESULT_REASONS[verdict].slice(0, SCAN_REASON_MAX_LENGTH);
  // mock에서만 사용
  }

mock이 제거되면 이 상수는 어디서도 쓰이지 않습니다.
글자 수 제한이 실제 요구사항이라면, 제한은 ScanResultReason 컴포넌트 안에서 해야 백엔드 연동 후에도 유지되는 것으로 보입니다.

 <Text style={styles.reason} numberOfLines={4}>{reason}</Text>
  // 또는
  <Text style={styles.reason}>{reason.slice(0, SCAN_REASON_MAX_LENGTH)}</Text>

다음과 같은 수정 방식을 제안드립니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영했습니다.

백엔드에서 판정 이유의 글자 수를 제한해 내려주는 구조라면, 프론트에서 slice()로 다시 자르는 것은 책임이 중복된다고 판단했습니다.
다만 화면에서는 긴 문구로 인해 UI가 과도하게 늘어나는 것을 방지할 필요가 있어, 표시 영역인 ScanResultReason 컴포넌트에서 numberOfLines={4}를 적용하는 방식으로 수정했습니다.

변경 사항:

  • ScanResultReason의 판정 이유 텍스트에 numberOfLines={4} 적용
  • mock 데이터 반환 시 사용하던 SCAN_REASON_MAX_LENGTHslice() 제거

chipBackground: Colors.brand.textWarning,
chipTextColor: '#FFFFFF',
chipTextColor: Colors.brand.text,
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

danger / block 칩 텍스트 색상 접근성

// result-status-icon.tsx:31-35
  danger: {
    chipBackground: Colors.brand.textWarning,  // #E61F1F (빨강)
    chipTextColor: Colors.brand.text,          // #1D2623 (어두운 색) —
  #FFFFFF에서 변경됨
  },

theme.ts:13에서 textWarningColor = #E61F1F
theme.ts:9에서 textPrimaryColor = #1D2623. 빨간 배경(#E61F1F)에 어두운 텍스트(#1D2623)의 명암비는 약 3.6:1
수준으로, WCAG AA 기준(소형 텍스트 4.5:1)을 미달한다고 합니다.
기존 #FFFFFF(흰색)이 명암비 상으로는 더 적합하다는 의견이 있어 이 부분은 확인 부탁드립니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영했습니다!

danger / block 상태 칩은 빨간 배경(#E61F1F) 위에 텍스트가 표시되는데, 기존 어두운 텍스트 색상(#1D2623)은 WCAG AA 일반 텍스트 기준인 4.5:1 대비를 충족하지 못하는 것으로 확인했습니다.
칩 텍스트는 13~14px 크기의 일반 텍스트에 해당하므로, 접근성과 가독성을 위해 대비 기준을 충족하는 흰색 텍스트를 사용하는 방향이 적절하다고 판단했습니다.

변경 사항:

  • danger / block 칩의 텍스트 색상을 Colors.brand.text에서 Colors.light.background로 변경
  • 테스트 확인을 위해 검사 완료 후 결과 화면을 scan-result-block으로 이동하도록 임시 변경

적용된 화면 캡쳐 이미지 입니다.
image

Comment thread components/ui/scan-result-reason.tsx Outdated
reason: string;
}

export function ScanResultReason({ reason }: ScanResultReasonProps) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

빈 reason 문자열 방어 없음

 export function ScanResultReason({ reason }: ScanResultReasonProps) {
    return (
      <View style={styles.container}>       {/* reason이 '' 이면 빈 카드 렌더링
  */}
        <Text style={styles.label}>판정 이유</Text>
        <Text style={styles.reason}>{reason}</Text>
      </View>
    );
  }

백엔드 연동 후 응답이 없거나 빈 문자열일 경우 빈 카드가 노출됩니다.
간단한 guard 추가를 제안드립니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영했습니다!

백엔드 연동 후 reason이 빈 문자열이거나 공백 문자열로 내려올 경우, 기존 구현에서는 판정 이유 라벨만 있는 빈 카드가 렌더링될 수 있었습니다.
사용자에게 의미 없는 빈 UI가 노출되는 것을 막기 위해, ScanResultReason 컴포넌트에서 표시 가능한 문자열인지 먼저 확인하도록 했습니다.

변경 사항:

  • reason.trim()으로 앞뒤 공백을 제거한 값을 사용하도록 수정
  • trim 이후 값이 비어 있으면 null을 반환해 판정 이유 카드가 렌더링되지 않도록 guard 추가
  • 정상 문자열은 공백이 정리된 상태로 기존처럼 최대 4줄까지 표시

테스트:

  • 앞뒤 공백이 포함된 reason 입력 시, 공백이 제거된 문구가 정상 표시되는 것 확인
  • reason이 빈 문자열일 때, 판정 이유 빈 카드가 노출되지 않는 것 확인

값이 비어있을 때 보이는 화면입니다!
스크린샷 2026-05-14 165117

Comment thread components/ui/scan-result-reason.tsx Outdated
paddingHorizontal: 16,
paddingVertical: 12,
gap: 8,
marginBottom: 24,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

marginBottom을 컴포넌트 내부에서 관리

container: {
    ...
    marginBottom: 24,  // 외부 레이아웃 간격을 컴포넌트가 직접 결정
  },

현재는 세 화면 모두 동일하게 쓰이므로 문제없지만, 다른 화면에서 재사용할 때 간격이 강제됩니다.
style prop을 받거나 호출 측에서 View로 감싸는 방식이 재사용성에 더 유리할 것이라고 생각합니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영했습니다!

제안해주신 방식 중 style prop 방식을 선택한 이유는, 호출부에서 별도의 wrapper View를 추가하지 않고도 기존 간격을 유지할 수 있고, 컴포넌트 사용 코드가 더 간결하게 유지되기 때문입니다.
또한 React Native 컴포넌트에서 외부 스타일을 style prop으로 확장하는 패턴이 일반적이라, 이후 다른 화면에서 marginBottom, marginTop 등 필요한 간격만 유연하게 조정하기에 적합하다고 판단했습니다.

변경 사항:

  • ScanResultReasonstyle prop 추가
  • 컴포넌트 내부 container에서 marginBottom: 24 제거
  • 기존 결과 화면의 UI 간격은 유지되도록 각 호출부에서 style={styles.reasonCard} 전달
  • safe, caution, block 결과 화면에 reasonCard: { marginBottom: 24 } 추가

@kbh0218
Copy link
Copy Markdown
Contributor Author

kbh0218 commented May 14, 2026

fontSize: 30이 테마 토큰을 직접 override

  • scan-result.tsx:125-126
  • scan-result-caution.tsx
  • scan-result-block.tsx:82-84

현재 3개의 파일에서 덮어쓰는 의도가 궁금합니다.

resultTitle: {
    ...Typography.display,   // theme.ts:104 → fontSize: 32
    fontSize: 30,            // 매직 넘버로 override
    ...
  },

Typography.display의 32px를 30px로 덮어쓰는 이유가 명확하지 않습니다. 의도된 크기라면 theme.ts에 displayMedium처럼 별도 토큰으로 추가하는 게 일관성 있어 보지 않을까 제안드립니다.

확인해보니 결과 타이틀 크기를 30px로 맞추려는 의도로 직접 override했던 것 같습니다.

다만 말씀주신 것처럼 Typography.display를 사용하면서 fontSize만 다시 덮어쓰면 토큰 사용 의도가 불명확해지고,
동일한 값이 여러 화면에 반복되어 유지보수 측면에서도 좋지 않아 보였습니다.

따라서 theme.tsTypography.displayMedium 토큰을 추가하고,
세 결과 화면에서는 직접 fontSize: 30을 지정하지 않고 해당 토큰을 사용하도록 수정했습니다.

@kbh0218 kbh0218 force-pushed the feat/#26-scan-result-screen-update branch from 8fb766e to e2e335b Compare May 14, 2026 08:17
const timer = setTimeout(() => {
router.replace({ pathname: '/(tabs)/(home)/scan-result', params: { url } });
router.replace({ pathname: '/(tabs)/(home)/scan-result-block', params: { url } });
}, 3000);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트 확인용으로 바꾼 scan-result-block 라우팅이 그대로 남아 있는 것으로 보입니다...!

현재 플로우에서는 어떤 URL을 입력해도 3초 뒤 위험/차단 결과 화면으로 이동하고, 안전 결과의 저장/접속 액션에도 도달할 수 없어 실제 검사 결과 화면 동작이 회귀합니다. 이 부분 알고 계시면 좋을 것 같습니다.

@kbh0218 kbh0218 merged commit ce869de into dev May 16, 2026
@kbh0218 kbh0218 deleted the feat/#26-scan-result-screen-update branch May 16, 2026 04:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature 기능개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] 검사 결과 화면 수정

3 participants