[FEATURE] 링크 검사 분석 요청 및 polling 연동#44
Conversation
| const reason = getMockScanResultReason('safe'); | ||
| const analysisId = getRouteParam(analysisIdParam); | ||
| const url = getRouteParam(urlParam); | ||
| const { analysis, isLoading, errorMessage } = useAnalysisResult(analysisId); |
There was a problem hiding this comment.
결과 화면에서 다시 받아온 analysis.verdict가 현재 화면 종류와 다른 경우가 처리되지 않는 것 같습니다. 예를 들어 /scan-result 화면으로 직접 들어왔는데, analysisId로 다시 조회한 결과가 danger라면 화면은 여전히 “안전한 웹사이트입니다.”로 보일 수 있습니다.
analysis.verdict를 확인해서 현재 화면과 다르면 맞는 결과 화면으로 이동시키거나, 결과 화면을 verdict 기준으로 공통 렌더링하면 더 안전할 것 같습니다.
일반적인 검사 흐름에서는 scanning.tsx에서 verdict에 맞는 결과 화면으로 보내기 때문에 문제가 잘 생기지는 않을 것 같습니다만... PR 설명처럼 결과 화면 직접 진입이나 앱 상태 유실 상황까지 고려한다면, 결과 화면에서 analysisId로 조회한 analysis.verdict가 현재 화면과 맞는지 한 번 확인해도 좋을 것 같습니다.
There was a problem hiding this comment.
맞습니다. 일반 검사 흐름에서는 scanning 화면에서 verdict별 결과 화면으로 이동해서 문제가 잘 드러나지 않지만, 결과 화면 직접 진입이나 앱 상태 유실 상황에서는 route와 재조회된 analysis.verdict가 어긋날 수 있다고 판단했습니다.
그래서 각 결과 화면에서 analysisId가 있으면 verdict가 확인되기 전까지 판정 UI를 보여주지 않고 로딩 상태만 표시하도록 했고, 조회된 verdict가 현재 화면 타입과 다르면 해당 verdict에 맞는 결과 화면으로 replace하도록 보완했습니다. 이 방식으로 “안전 화면이 잠깐 보였다가 위험 화면으로 이동”하는 깜빡임도 막았습니다!
| const reason = getAnalysisReasonText(analysis, getMockScanResultReason('safe')); | ||
| const [saveModalVisible, setSaveModalVisible] = useState(false); | ||
|
|
||
| const handleSave = (title: string) => { |
There was a problem hiding this comment.
analysisId만 가지고 결과 화면에 직접 들어온 경우, 분석 결과를 불러오기 전에도 저장 버튼을 누를 수 있습니다. 이때 아직 URL 정보가 없어서 빈 URL이 저장될 수 있을 것 같습니다.
분석 결과 로딩 중이거나 표시할 URL이 없을 때는 저장 버튼을 비활성화하거나, handleSave에서 displayUrl이 없으면 저장하지 않도록 막으면 좋을 것 같습니다...!
There was a problem hiding this comment.
맞습니다. analysisId 직접 진입이나 조회 실패 케이스에서 displayUrl이 비어 있는 상태로 저장될 여지가 있어 보였습니다.
저장 버튼은 로딩 중이거나 표시할 URL이 없으면 비활성화하도록 수정했고, 혹시 모달 상태 경계에서 저장 핸들러가 호출되더라도 canSave가 false면 저장하지 않도록 가드도 추가했습니다. 같은 저장 흐름을 쓰는 주의 결과 화면에도 동일하게 반영했습니다!
Closes #43
개요
링크 검사 중 화면에서 기존 mock 타이머 기반 이동 흐름을 실제 백엔드 분석 API 연동 흐름으로 교체했습니다.
기존에는
scanning.tsx에서 일정 시간이 지나면 mock 결과 화면으로 이동했지만, 이번 작업에서는POST /api/v1/analyses로 분석을 요청하고, 응답으로 받은analysisId를 기준으로GET /api/v1/analyses/{analysisId}를 polling하여 실제 분석 상태를 확인하도록 구현했습니다.분석이 완료되면 백엔드 응답의
verdict값에 따라 안전, 주의, 위험 결과 화면으로 이동합니다. 결과 화면으로는AnalysisResponse전체 객체를 넘기지 않고analysisId,url,verdict만 전달하며, 각 결과 화면에서analysisId를 기준으로 분석 결과를 다시 조회해 화면 표시용AnalysisResponse를 확보하도록 구성했습니다.이 구조를 통해 route params를 작고 안정적으로 유지하면서도, 결과 화면 직접 진입이나 앱 상태 유실 상황에서도
analysisId만 있으면 분석 결과를 다시 확보할 수 있도록 했습니다.주요 구현 내용
POST /api/v1/analyses분석 요청 API 연동getToken()기반 보호 API 호출 구조 적용GET /api/v1/analyses/{analysisId}polling 구현queued상태에서는 polling 유지failed상태 또는 API 에러 발생 시 사용자 안내 메시지 표시succeeded상태에서verdict값에 따라 결과 화면 분기safe결과는scan-result화면으로 이동caution결과는scan-result-caution화면으로 이동danger결과는scan-result-block화면으로 이동AnalysisResponse전체 객체 대신analysisId,url,verdict만 전달analysisId기준AnalysisResponse조회summary -> reasons -> mock reason순서로 판정 이유 표시analysis?.originalUrl ?? url ?? ''기준으로 표시 URL 정리analysis?.finalUrl을 즉시 URL 접속 및 mock 저장 데이터에 반영analysisId를 우선 사용POST /saved-links실제 저장 API 연동은 다음 작업으로 분리파일별 역할
api/analyses.ts: 분석 요청/조회 API 타입 및 호출 함수 추가app/(tabs)/(home)/scanning.tsx: 분석 요청, polling, 상태별 에러 처리, 결과 화면 분기 처리hooks/use-analysis-result.ts: 결과 화면에서analysisId기준으로 분석 결과를 조회하는 공통 hook 추가utils/analysis-result-display.ts: route param, 표시 URL, 최종 URL, 판정 이유, 사이트명 표시 유틸 추가app/(tabs)/(home)/scan-result.tsx: 안전 결과 화면에서analysisId수신 및 분석 결과 조회 반영app/(tabs)/(home)/scan-result-caution.tsx: 주의 결과 화면에서analysisId수신 및 분석 결과 조회 반영app/(tabs)/(home)/scan-result-block.tsx: 위험 결과 화면에서analysisId수신 및 분석 결과 조회 반영해결한 이슈 목록
scanning.tsx의 mock 타이머 기반 결과 이동 흐름을 실제 분석 API 흐름으로 교체analysisId기준 polling 수행queued상태 처리verdict에 따라 안전/주의/위험 결과 화면으로 이동analysisId,url,verdict전달AnalysisResponse전체 객체를 route params로 전달하지 않도록 처리analysisIdroute param 수신fetchAnalysis()기반 분석 결과 조회summary또는reasons기반 판정 이유 표시analysisId우선 반영체크 사항
fetch()를 호출하지 않음Authorization헤더를 붙이지 않음{ data: ... }응답을 직접 unwrap하지 않음authenticatedApiRequest()기반fetchAnalysis()를 통해 호출/auth/me를 수동 선호출하는 흐름을 만들지 않음AnalysisResponse전체 객체를JSON.stringify해서 route params로 넘기지 않음POST /api/v1/saved-links저장 API 연동은 이번 작업에 포함하지 않음검증
GET /api/v1/analyses/{analysisId}응답이ApiResponseAnalysisResponse -> AnalysisResponse구조임을 확인참고
이번 PR에서는 분석 결과 화면의 저장 버튼이 아직 실제
POST /api/v1/saved-links를 호출하지 않습니다.safe/caution 결과 화면의 저장 흐름은 기존 mock
addLink기반으로 유지하되, 이후 저장 API 연동 작업에서 바로 사용할 수 있도록 실제analysisId를 우선 반영하도록 정리했습니다.결과 화면은 앱 내부 이동 직후에도
analysisId기준으로 분석 결과를 조회합니다. 따라서 polling 중 이미 받은AnalysisResponse를 route params로 직접 전달하지 않고, 결과 화면에서 필요한 시점에 다시 조회하는 구조입니다.Screenshots or Video