Windows 로컬 웹앱에서 WiFi QR 자동 입력값이 null로 나올 때
무용 연습용 영상·대형 동기화 웹앱(formation)의 로컬 접속 화면을 다듬고 있었다. Windows PC의 Node 서버에서 현재 WiFi 이름과 비밀번호를 읽어 WiFi 접속용 QR의 입력값을 채우려 했지만, 첫 검증에서 /wifi 응답은 null이었다.
결론
이 사례에서 선택한 방법은 브라우저가 아니라 로컬 Node 서버에서 WiFi 정보를 읽는 것이었다. netsh wlan show interfaces로 현재 SSID(무선 네트워크 이름)를 읽고, netsh wlan export profile ... key=clear로 내보낸 XML의 <keyMaterial>에서 비밀번호를 얻어 /wifi로 전달하는 구조다. 아래 명령의 ...는 생략 표시이며, 그대로 실행할 완성 명령이나 실제 구현 코드는 기록에 없다.
null이 나오면 먼저 서버 PC가 WiFi에 연결돼 있는지 확인한다. 당시 확인 보고는 WiFi 연결이 끊겼고 PC가 유선을 사용하고 있다는 내용이었다. 연결된 상태에서 SSID·비밀번호가 채워지는지는 확인 못 했다. 연결이 없다는 설명은 가능하지만, 그것만으로 파싱 코드가 정상이라고 입증되지는 않는다.
또한 /wifi에 평문 비밀번호를 담는 설계였다. 운영자 페이지만 호출한다는 설명은 있지만, 다른 기기의 직접 요청을 서버가 차단한다는 근거는 없다. 동작 검증과 함께 접근 제한도 별도로 확인해야 한다.
상황
문제의 대상은 Windows PC에서 실행하는 로컬 서버와 운영자 화면이었다. 운영자 화면은 WiFi 정보를 입력받아 브라우저 저장소인 localStorage에 보관하고 QR을 만들었으며, 여기에 “현재 연결된 WiFi 정보를 기본값으로 쓰기”가 요청됐다. 변경 대상으로 보고된 파일은 live/server.js와 live/public/server.html이다.
증상
출발점은 자동 입력 기능 요청이었다. 서버를 띄워 검증한 단계에서 /wifi가 null을 반환했고, 이어진 확인에서는 WiFi가 끊긴 상태라고 보고됐다. 화면 렌더링과 “현재 연결된 WiFi 불러오기” 버튼 표시는 확인됐지만, 실제 WiFi 정보가 입력됐다는 보고는 없었다.
원인
먼저 정보를 읽는 위치를 바꿔야 했다. 당시 설계 판단은 브라우저에서 WiFi 비밀번호를 직접 읽을 수 없으므로, PC에서 실행되는 Node 서버가 운영체제 명령을 호출하도록 한다는 것이었다. 이 구조가 읽으려는 대상은 서버 PC의 연결 정보다.
실제 null에 대해서는 WiFi 미연결 상태가 설명으로 제시됐다. 다만 기록에는 netsh 출력 전체나 파서 코드가 없고, State: disconnected라는 확인 요약만 있다. 당시의 “파싱 로직 자체는 정상”이라는 결론은 연결된 상태의 시험 결과로 뒷받침되지 않으므로, 이 글에서는 정상 판정으로 받아들이지 않는다.
해결
서버에서 읽고, 저장값이 없을 때 채운다
구현 설명에 나타난 흐름은 다음과 같다. 실제 코드를 재현한 예제가 아니라 당시 보고된 설계다.
- 서버가
netsh wlan show interfaces로 현재 SSID를 읽는다. - 프로필을
key=clear옵션으로 XML에 내보내고<keyMaterial>에서 비밀번호를 읽는다. 번역되는 출력 문구에 덜 의존하려는 선택이었다. 한국어·영문 환경에서 각각 검증한 결과는 없다. /wifi응답을 운영자 페이지에서 받아 저장값이 없을 때 자동 입력하고, 버튼으로 다시 불러오게 한다.
명령 자체의 조건도 구분해야 한다. Microsoft 문서는 export profile의 key=clear가 로컬 관리자 실행 조건에서 키를 평문으로 내보낸다고 설명한다. 이는 명령에 대한 외부 근거이며, 당시 서버의 실행 권한을 확인해 주지는 않는다. Microsoft Learn: netsh wlan
평문이 어디까지 가는지 확인한다
이 설계에서 확인되는 노출 지점은 /wifi 응답이다. 뷰어·리더 페이지는 호출하지 않는다고 했지만, 서버의 인증이나 접속 위치 제한은 설명되지 않았다. “버튼이 없는 페이지”와 “요청해도 비밀번호를 받을 수 없는 클라이언트”는 구분해서 검증해야 한다.
XML 내보내기 뒤 파일을 어떻게 처리하는지도 기록에 없다. SSID와 프로필 이름이 다를 때의 처리, 명령 호출 방식, XML 파싱 방식, 응답 JSON 형태 역시 확인 못 했다. 따라서 이 기록만으로 복사해 쓸 서버 코드를 만들거나 평문 파일이 남지 않는다고 보증할 수는 없다.
후속 검증에서는 WiFi에 연결한 서버 PC에서 명령 결과와 /wifi 응답, 폼 입력까지 이어서 확인할 필요가 있다. 다른 기기에서 직접 호출할 수 있는지와 내보낸 파일의 처리도 확인 대상이다. 현재 기록의 도달점은 미연결 상태의 null과 화면 렌더링 확인까지다.
같은 화면에서는 WiFi QR과 뷰어 접속 QR이 가까워 카메라에 함께 들어오는 불편도 있었다. 카드 안에서 벌리는 수정 뒤에도 더 넓은 간격이 요구돼 width:100vw와 space-between으로 화면 양 끝에 배치했다고 보고됐다. 이후 실제 휴대폰 스캔이 개선됐다는 확인은 없으므로, 배치 변경까지만 확인된 곁가지다.
취재 후기 — 값이 없다는 것과 코드가 맞다는 것
/wifi라는 요청 경로로 돌려주게 하자. 우리가 가져오려는 건 서버 PC가 연결한 WiFi 정보야. netsh라는 Windows 네트워크 명령으로 읽는 설계야. 비밀번호도 서버 쪽에서 가져오게 돼 있어. keyMaterial 항목을 읽기로 했어. 번역되는 출력 문구에 덜 의존하려는 선택이지. /wifi 응답은 null, 값이 없는 상태야. 아직 이름과 비밀번호가 돌아오는 장면은 확인하지 못했어. netsh의 실제 출력을 먼저 확인하자. WiFi 연결 자체가 있는지 알아야 값을 추출하는 단계까지 시험했는지 판단할 수 있어. localStorage에 저장값이 없을 때 하도록 했어. 이미 값이 있으면 자동으로 덮는 대신 버튼으로 다시 읽는 흐름이야. /wifi 응답에 평문 비밀번호가 들어가고 운영자 화면만 호출하는 구조지만, 직접 요청을 막는지는 아직 몰라.