[FEATURE] 검사 결과 화면 수정#31
Conversation
a0bfd07 to
8fb766e
Compare
sunm2n
left a comment
There was a problem hiding this comment.
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 패턴이나 의심스러운 접근 흐름이 감지되어, 저장하거나 접속하지 말고 공식 주소를 통해 다시 확인하세요.', | ||
| }; |
There was a problem hiding this comment.
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>
다음과 같은 수정 방식을 제안드립니다.
There was a problem hiding this comment.
반영했습니다.
백엔드에서 판정 이유의 글자 수를 제한해 내려주는 구조라면, 프론트에서 slice()로 다시 자르는 것은 책임이 중복된다고 판단했습니다.
다만 화면에서는 긴 문구로 인해 UI가 과도하게 늘어나는 것을 방지할 필요가 있어, 표시 영역인 ScanResultReason 컴포넌트에서 numberOfLines={4}를 적용하는 방식으로 수정했습니다.
변경 사항:
ScanResultReason의 판정 이유 텍스트에numberOfLines={4}적용- mock 데이터 반환 시 사용하던
SCAN_REASON_MAX_LENGTH와slice()제거
| chipBackground: Colors.brand.textWarning, | ||
| chipTextColor: '#FFFFFF', | ||
| chipTextColor: Colors.brand.text, | ||
| }, |
There was a problem hiding this comment.
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(흰색)이 명암비 상으로는 더 적합하다는 의견이 있어 이 부분은 확인 부탁드립니다.
There was a problem hiding this comment.
반영했습니다!
danger / block 상태 칩은 빨간 배경(#E61F1F) 위에 텍스트가 표시되는데, 기존 어두운 텍스트 색상(#1D2623)은 WCAG AA 일반 텍스트 기준인 4.5:1 대비를 충족하지 못하는 것으로 확인했습니다.
칩 텍스트는 13~14px 크기의 일반 텍스트에 해당하므로, 접근성과 가독성을 위해 대비 기준을 충족하는 흰색 텍스트를 사용하는 방향이 적절하다고 판단했습니다.
변경 사항:
danger/block칩의 텍스트 색상을Colors.brand.text에서Colors.light.background로 변경- 테스트 확인을 위해 검사 완료 후 결과 화면을
scan-result-block으로 이동하도록 임시 변경
| reason: string; | ||
| } | ||
|
|
||
| export function ScanResultReason({ reason }: ScanResultReasonProps) { |
There was a problem hiding this comment.
빈 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 추가를 제안드립니다.
There was a problem hiding this comment.
반영했습니다!
백엔드 연동 후 reason이 빈 문자열이거나 공백 문자열로 내려올 경우, 기존 구현에서는 판정 이유 라벨만 있는 빈 카드가 렌더링될 수 있었습니다.
사용자에게 의미 없는 빈 UI가 노출되는 것을 막기 위해, ScanResultReason 컴포넌트에서 표시 가능한 문자열인지 먼저 확인하도록 했습니다.
변경 사항:
reason.trim()으로 앞뒤 공백을 제거한 값을 사용하도록 수정- trim 이후 값이 비어 있으면
null을 반환해 판정 이유 카드가 렌더링되지 않도록 guard 추가 - 정상 문자열은 공백이 정리된 상태로 기존처럼 최대 4줄까지 표시
테스트:
- 앞뒤 공백이 포함된 reason 입력 시, 공백이 제거된 문구가 정상 표시되는 것 확인
- reason이 빈 문자열일 때,
판정 이유빈 카드가 노출되지 않는 것 확인
| paddingHorizontal: 16, | ||
| paddingVertical: 12, | ||
| gap: 8, | ||
| marginBottom: 24, |
There was a problem hiding this comment.
marginBottom을 컴포넌트 내부에서 관리
container: {
...
marginBottom: 24, // 외부 레이아웃 간격을 컴포넌트가 직접 결정
},
현재는 세 화면 모두 동일하게 쓰이므로 문제없지만, 다른 화면에서 재사용할 때 간격이 강제됩니다.
style prop을 받거나 호출 측에서 View로 감싸는 방식이 재사용성에 더 유리할 것이라고 생각합니다.
There was a problem hiding this comment.
반영했습니다!
제안해주신 방식 중 style prop 방식을 선택한 이유는, 호출부에서 별도의 wrapper View를 추가하지 않고도 기존 간격을 유지할 수 있고, 컴포넌트 사용 코드가 더 간결하게 유지되기 때문입니다.
또한 React Native 컴포넌트에서 외부 스타일을 style prop으로 확장하는 패턴이 일반적이라, 이후 다른 화면에서 marginBottom, marginTop 등 필요한 간격만 유연하게 조정하기에 적합하다고 판단했습니다.
변경 사항:
ScanResultReason에styleprop 추가- 컴포넌트 내부
container에서marginBottom: 24제거 - 기존 결과 화면의 UI 간격은 유지되도록 각 호출부에서
style={styles.reasonCard}전달 safe,caution,block결과 화면에reasonCard: { marginBottom: 24 }추가
확인해보니 결과 타이틀 크기를 30px로 맞추려는 의도로 직접 override했던 것 같습니다. 다만 말씀주신 것처럼 따라서 |
8fb766e to
e2e335b
Compare
| const timer = setTimeout(() => { | ||
| router.replace({ pathname: '/(tabs)/(home)/scan-result', params: { url } }); | ||
| router.replace({ pathname: '/(tabs)/(home)/scan-result-block', params: { url } }); | ||
| }, 3000); |
There was a problem hiding this comment.
테스트 확인용으로 바꾼 scan-result-block 라우팅이 그대로 남아 있는 것으로 보입니다...!
현재 플로우에서는 어떤 URL을 입력해도 3초 뒤 위험/차단 결과 화면으로 이동하고, 안전 결과의 저장/접속 액션에도 도달할 수 없어 실제 검사 결과 화면 동작이 회귀합니다. 이 부분 알고 계시면 좋을 것 같습니다.


Closes #26
개요
검사 결과 화면에서 기존 안내 문구인
저장 후 바로 접속하거나, 즉시 URL로 이동할 수 있어요.영역을 URL 검사 결과에 대한 판정 이유 표시 영역으로 변경했습니다.기존에는 저장 및 URL 이동 기능을 안내하는 문구가 표시되고 있었지만, 검사 결과 화면에서는 사용자가 왜 해당 URL이 안전/주의/위험으로 판정되었는지 이해할 수 있는 정보가 더 중요하다고 판단했습니다.
이번 작업에서는 우선 테스트용 mock 판정 이유 데이터를 구성하고, 검사 결과 상태에 따라 안전/주의/위험에 맞는 판정 이유 문구가 표시되도록 연결했습니다. 추후 백엔드에서 판정 이유 텍스트를 응답으로 전달하면 mock 데이터를 실제 응답 데이터로 교체할 수 있도록 TODO 주석을 남겼습니다.
또한 판정 이유 영역 추가에 맞춰 검사 결과 화면의 위치와 간격을 조정하고, 검사 대상 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: 위험/차단 결과 화면에 판정 이유 영역 적용 및 레이아웃 조정해결한 이슈 목록
체크 사항
npx tsc --noEmit통과npm run lint확인 필요참고
npm run lint는 기존 파일에서 발생하던expo-linear-gradientimport resolver 오류와 일부 warning으로 실패합니다. 이번 작업에서 수정한 파일의 타입 오류는 없으며,npx tsc --noEmit은 통과했습니다.Screenshots or Video
안전

주의

위험
