개발 취재 노트
안드로이드 웨일에서 영상을 골라도 참여 버튼이 안 켜질 때
무용 연습실에서 여러 사람이 각자 폰으로 같은 안무 영상을 재생해 동작을 맞춰 보는 웹앱을 만들고 있었다. 리더가 방을 만들고, 뷰어들이 같은 영상을 고른 뒤 실시간 동기화로 따라 보는 구조였다 . 노트북 크롬과 아이폰에서는 되는데, 안드로이드의 네이버 웨일 브라우저에서는 영상 파일명이 보이는데도 "방 만들기"와 "참여" 버튼이 계속 회색이었다 . 파일을 고르려 하면 구글 포토나 "클라우드 미디어"라는 낯선 안내도 떴다 .
결론
버튼이 안 켜진 직접 원인은 fingerprint.js가 웨일에서 로드되지 않은 것이었다. 그 스크립트가 없으니 페이지 최상단 코드가 예외로 멈췄다. 파일명을 mediacheck.js로 바꾸자 버튼이 켜졌다 . 웨일이 파일명을 보고 막았다는 설명은 추정이다. 세션에는 차단 장면이 기록되지 않았다.
구글 포토 선택창 문제는 미해결, 시험 중이다. video/*는 이 선택창의 원인으로 확인되지 않았다. 아래 확장자 전용 accept는 시험 중인 방법일 뿐 검증된 해결책이 아니다. 이 방식은 이미 한 번 시도됐고 사용자가 "안돼네"라고 했다 .
당장 해볼 일:
- 버튼이 안 켜지면 주소 끝에
?debug=1을 붙여 열고 첫 에러 줄을 본다.Cannot destructure property 'fingerprintVideo' of 'window.FormationFingerprint'가 찍히면 스크립트가 로드되지 않은 것이므로 파일명부터 바꿔 본다 . - 버튼 문제의 확인된 우회는 같은 폰의 일반 크롬이다. 일반 크롬에서는 버튼이 켜졌다 .
- 선택창은 우회가 확인되지 않았다. 아래
후코드(확장자 전용accept, 최종 적용본 )를 넣고, 같은 폰에서 카톡으로 받은 로컬 mp4를 실제로 고를 수 있는지 본다. 같은 방식이 #159에서 실패로 보고됐으므로, 이번에도 되는지는 새로 확인해야 한다. 시험한 사람은기기 / 웨일 버전 / 영상만 뜸 여부 / mp4 선택 가능 여부네 항목을 자기 메모에 한 줄로 적는다. 적지 않으면 결과를 모르는 상태로 둔다. 이 글은 그 상태에서 선택창이 해결됐다고 주장하지 않는다.
<!-- 전 (#174 시점: accept 속성 없음. 그 이전에는 accept="video/*") -->
<input type="file">
<!-- 후 (최종 적용본) -->
<input type="file" accept=".mp4,.m4v,.mov,.webm,.mkv,.avi,.3gp,.ts,.mpeg,.mpg">
상황
formation은 한 명(리더)이 폰이나 노트북으로 영상을 재생하면 나머지(뷰어)가 각자 기기로 같은 지점을 따라 재생하게 해주는 연습실용 웹앱이다. iOS 테스트 안내에서도 리더와 뷰어가 각자 같은 mp4를 선택하는 흐름으로 설명됐다 . 이 사건 당시 앱은 로컬 테스트를 넘어 클라우드 배포판에서 방 만들기와 참여 흐름을 검증하던 중이었다 .
영상 파일을 고르면 브라우저가 그 파일의 지문(영상 내용을 해시한 값)을 계산한다 . 뷰어의 "참여" 버튼은 고른 파일의 지문이 방에 저장된 영상의 지문과 맞을 때 켜지는 구조라서, 지문 계산 스크립트가 로드되지 않으면 버튼이 켜질 수 없다 .
증상
안드로이드 폰의 네이버 웨일 브라우저(UA상 Android 10, Whale/3.9.14.9)에서 영상 파일을 고르면 파일명은 뜨는데 "방 만들기"와 "참여" 버튼이 켜지지 않았다 . 같은 기기의 일반 크롬은 됐고, 아이폰과 데스크톱도 멀쩡했다 .
선택기 쪽 증상도 따로 보고됐다. 사용자는 파일 선택 버튼을 누르면 기본으로 구글 포토가 열리는 것 같다고 했고 , 기본 설정을 지워도 "클라우드 미디어 설정" 안내가 뜬다고 했다 . 반면 동선 데이터 파일인 .json 입력은 문제없이 골라졌다 .
원인
확인된 버튼 원인과 선택창 가설을 구분해야 한다.
첫째, 버튼 증상은 스크립트 로드 실패였다. 디버그 패널을 넣고 보니, 리더 페이지를 여는 순간, 즉 파일을 고르기도 전에 아래 에러가 떠 있었다 .
window.error: Uncaught TypeError: Cannot destructure property 'fingerprintVideo'
of 'window.FormationFingerprint' as it is undefined.
웨일에서 fingerprint.js가 로드되지 않아 window.FormationFingerprint가 비어 있었고, 그 객체를 구조분해하는 코드가 페이지 최상단에서 예외를 던졌다 . 세션 후반에는 파일명을 바꾸자 버튼이 켜졌다는 점에서, 파일명 변경이 이 증상을 푼 조치로 정리됐다 . 다만 로드가 실패한 이유, 즉 웨일이 파일명을 기준으로 막았는지는 세션에서 직접 확인되지 않았다. 확인된 것은 "이 파일이 안 올라왔다"와 "이름을 바꾸니 됐다"까지다.
둘째, 선택기 증상은 accept의 MIME 힌트 때문이라는 가설이 나왔다. 근거는 .json 입력은 되고 video 입력만 구글 포토로 빠진다는 대비였다 . 하지만 이 가설은 페이지 스크립트와 무관하게 브라우저의 선택기 종류가 정해진다는 전제 위에 있다. 따라서 파일 로드 문제가 선택기 증상까지 설명하지는 않는다.
해결
accept 쪽에는 세 가지 수정이 순서대로 시도됐다. accept는 파일 입력이 어떤 파일을 고르게 할지 브라우저에 알려주는 속성이다.
- MIME 와일드카드(
video/*)를 제거했다. 이후 사용자는 "여전히 마찬가지"라고 했다 . - MIME을 전부 빼고 확장자만 지정했다. 사용자는 "안돼네 다음 수 쓰자"라고 했다 .
accept속성 자체를 제거했다 .
155와 159의 보고는 선택기 증상이었으므로, 이 시점의 accept 변경은 선택기 증상을 고치지 못했다. 3번(accept 제거) 이후에는 선택기 증상에 대한 보고가 기록에 없다.
버튼 증상은 디버그 패널이 잡았다. ?debug=1로 열자 스크립트 로드 실패에 따른 예외가 바로 찍혔고 , 파일명을 mediacheck.js로 바꾼 뒤 사용자가 즉시 성공을 확인했다 .
그 직후 영상 입력에는 확장자 전용 필터를 다시 넣었다 . 이 방식은 #158에서 이미 한 번 시도됐고, 사용자는 #159에서 "안돼네"라고 했다. 그때의 실패 원인은 기록되지 않았다. #190의 복원은 같은 방식을 다시 넣은 것이며, 그 뒤 새 테스트 결과는 없다.
<input type="file" accept=".mp4,.m4v,.mov,.webm,.mkv,.avi,.3gp,.ts,.mpeg,.mpg">
MIME을 일부러 넣지 않은 이유는, 세션에서 video/* 류가 안드로이드의 미디어 중심 선택 흐름으로 빠질 수 있다고 봤기 때문이다 .
검증 공백
- 마지막 확장자 필터 복원 뒤, 안드로이드 웨일에서 파일 선택기에 영상만 뜨는지, 카카오톡·다운로드 폴더의 mp4를 고를 수 있는지는 사용자 확인 없이 세션이 끝났다 .
- 같은 확장자 방식은 #159에서 "안돼네"라는 보고를 받았다. 따라서 #190의 복원을 해결 근거로 쓸 수 없다.
accept제거(161) 이후 선택기 증상에 대한 사용자 보고는 없다. 그래서 현재 선택기 동작은 확인되지 않았다.- 세션 후반에는 예전 확장자 필터 실패도 파일 로드 문제 탓이었다는 설명이 나왔다 . 그러나 근거가 제시되지 않았고, 선택기 종류는
accept속성에 따라 정해지는 브라우저 동작이라 이 설명은 받아들이기 어렵다. 이 글은 두 증상을 분리해 읽는다.
따라서 이 글의 적용 포인트는 두 가지로 나눠 읽어야 한다. 버튼이 안 켜진다면 먼저 콘솔 에러와 스크립트 로드 실패를 본다 . 선택기에서 구글 포토나 클라우드 미디어만 보인다면, 확장자 전용 accept를 시험해볼 만하다 . 다만 이 방법은 이 세션에서 독립적으로 검증되지 않았고, 한 번 실패 보고가 있었다 .
덤 — 증상 두 개를 한 원인으로 묶지 말 것
같은 기기에서 증상이 둘 이상 겹쳐 있으면, 한 증상의 원인을 찾았다고 다른 증상의 원인까지 찾은 것은 아니다. 이 사건에서 버튼 증상은 스크립트 로드 실패였고 파일명 변경으로 풀렸지만 , 선택기 증상은 그 로드 실패로 설명되지 않는다. 한쪽을 고쳤다고 다른 쪽 수정을 "맞았다"고 단정하는 것도, "틀렸다"고 기각하는 것도 증거가 부족하다.
취재 후기 — 버튼을 죽인 건 파일이 안 올라온 것이었고, 선택기는 따로 봐야 했다
.json은 잘 골라졌다며 ?.json은 되니까 video 입력의 accept가 수상해. 그래서 MIME을 빼고 확장자만 남겼어 .accept 변경은 효과가 없었다고 인정해야 해.accept 가설은 빗나간 거야?accept를 뺀 뒤로는 선택기 보고가 세션에 없어. 확인이 안 된 거야.fingerprint.js가 안 올라와서 파일 핸들러, 연결, 버튼 활성화 로직이 전부 등록되지 않은 거야 .fingerprint가 들어가서 웨일이 막은 것 같아. 이름을 바꿔 보면 갈리겠지 .window.FormationFingerprint가 undefined라는 에러가 찍혔어 . 파일명을 mediacheck.js로 바꾸니까 테스터가 "된다!! 됐어!"라고 확인했지 .accept를 고쳐라"는 아직 말하면 안 되겠다.