투케이2K

183. (TWOK/UTIL) [Web/JavaScript] 자바스크립트 img.src 및 fetch api 사용해 브라우저 실제 네트워크 사용 가능 상태 확인 본문

투케이2K 유틸파일

183. (TWOK/UTIL) [Web/JavaScript] 자바스크립트 img.src 및 fetch api 사용해 브라우저 실제 네트워크 사용 가능 상태 확인

투케이2K 2026. 3. 27. 19:39
728x90
반응형

[설 명]

프로그램 : Web / JavaScript

설 명 : [Web/JavaScript] 자바스크립트 img.src 및 fetch api 사용해 브라우저 실제 네트워크 사용 가능 상태 확인

 

[소스 코드]

-----------------------------------------------------------------------------------------
[사전 설명 및 설정 사항]
-----------------------------------------------------------------------------------------

- 개발 환경 : Web


- 개발 기술 : JavaScript (자바스크립트) / Browser / network use / navigator.connection / img.src / fetch api


- 사전) 👉 자바스크립트 navigator.connection 간략 설명 : 

  >> navigator.connection 는 브라우저가 사용자의 네트워크 품질에 대한 힌트를 제공해, 앱이 적응형(Adaptive) 으로 동작하도록 돕는 API 입니다

  >> navigator.connection 는 사용자의 현재 네트워크 품질을 대략적으로 추정해서 알려줍니다.

    - effectiveType : 네트워크 품질을 4단계로 분류한 문자열 → "slow-2g" | "2g" | "3g" | "4g"
    - downlink : 추정 다운로드 대역폭 (Mbps)
    - rtt : 추정 왕복 지연시간 (ms)
    - saveData : 데이터 절약 모드 (저대역폭 모드) 여부 (true/false)
    - type : (제한적 지원) 실제 전송 기술 힌트 (예: "wifi", "cellular", "ethernet" 등). 많은 브라우저에서 제공하지 않음

  >> ⚠️ navigator.connection 값들은 “추정치/힌트” 로 인터넷 연결 여부(외부망 도달 가능) 를 보장하지 않습니다.

-----------------------------------------------------------------------------------------





-----------------------------------------------------------------------------------------
[소스 코드]
-----------------------------------------------------------------------------------------

<!DOCTYPE HTML>
<html lang="ko">
<head>
    <title>javaScriptTest</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">


    <!-- 반응형 구조 만들기 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">


    <!-- 내부 CSS 스타일 지정 -->
    <style>

        html, body {
            width: 100%;
            height: 100%;
            margin : 0 auto;
            padding : 0;
            border : none;
            background-color: #666;
        }

    </style>





    <!-- [CDN 주소 설정] -->
    <script src="https://code.jquery.com/jquery-latest.min.js"></script>






    <!-- [자바스크립트 코드 지정] -->
    <script type="module">

        // [html 최초 로드 및 이벤트 상시 대기 실시]
        window.onload = async function() {
          console.log("[window onload] : [start]");

          try {

            // -------------------------------------
            // 현재 네트워크 연결 상태 확인 수행
            // -------------------------------------
            await getConnectionSnapshot(0); // ✔️ API 호출 방식 확인
            // -------------------------------------
            await getConnectionSnapshot(1); // ✔️ Img 호출 방식 확인
            // -------------------------------------

          }
          catch (exception) {
            console.error("[window onload] : [Exception] : ", exception);
          }

        };





        // [네트워크 연결 상태 확인 함수 생성]        
        async function getConnectionSnapshot(type) {

          // 리턴 반환 json 생성
          var returnJson = {
            navigatorSupport: null,
            connectType: null,
            effectiveType: null,
            rtt: null,
            saveData: null,
            onlineHint: null,
            timestamp: null,
            networkUse: null,
          };


          var windowLocation = null;
          try {
            windowLocation = window.location.href;

            if (windowLocation !== null && windowLocation !== undefined && windowLocation !== ''){
              console.warn('window location check : value : ', windowLocation);

              // ---------------------------------------------
              // 로컬 html 파일 형식 체크 >> Img 호출 자동 전환
              // ---------------------------------------------
              // ⚠️ file://은 null origin 이라 CORS로 차단됩니다. 로컬 개발 서버 (http://localhost) 위에서 테스트하거나, <img> 로드를 이용한 이미지 핑 방식을 쓰세요.
              // ---------------------------------------------
              // 예시 : file:///C:/Users/twok/Desktop/testHtml.html
              // ---------------------------------------------
              
              if (windowLocation.startsWith('file:///') == true) {
                console.error('window location [ file:/// ] start');

                if (type == 0){
                  type = 1; // ✅ Set Image Call Type
                }                
              }
              
            }            
            else {
              console.error('window location check : value : is null');
            }
          }
          catch(err){
            console.error('window location check : exception : ', err);
            windowLocation = null;
          }



          // ✅ [Http API 테스트 호출 위한 URL 배열 생성]

          // favicon 호출이 일반 페이지(예: https://www.google.com/) 호출보다 훨씬 더 빠릅니다.
          const apiArray = [            
            "https://www.google.com/favicon.ico",
            "https://www.amazon.com/favicon.ico",
            "https://www.microsoft.com/favicon.ico",
            "https://www.apple.com/favicon.ico",
            "https://www.youtube.com/favicon.ico",
            "https://www.cloudflare.com/favicon.ico",            
            "https://www.wikipedia.org/favicon.ico",            
            "https://www.naver.com/favicon.ico",
            "https://www.daum.net/favicon.ico",
            "https://www.nate.com/favicon.ico",
          ];


          // 로직 처리 수행
          try {
            const supported = typeof navigator !== undefined && navigator !== null && navigator !== 'undefined' && 'connection' in navigator;
            const conn = supported ? navigator.connection : null;

            console.log('getConnectionSnapshot : connection : ', conn);

            returnJson = {
              navigatorSupport: supported ?? null,
              connectType: conn?.type ?? null, // true → Wi‑Fi에 연결된 것으로 추정 : false → Wi‑Fi가 아닌 것으로 추정 : null → 이 브라우저에서는 판단 불가
              effectiveType: conn?.effectiveType ?? null, // 네트워크의 품질을 단순화한 분류 : "slow-2g", "2g", "3g", "4g" 네 가지 중 하나가 옵니다
              rtt: conn?.rtt ?? null, // 예상 왕복 시간 (ms) 
              saveData: conn?.saveData ?? null,
              onlineHint: typeof navigator !== undefined && navigator !== null && navigator !== 'undefined' ? navigator.onLine : null,
              timestamp: Date.now(),
            };


            // -------------------------------------------------
            // 동기 순차 대기 필요 변수 선언 : async await  
            // -------------------------------------------------
            const timeoutMs = 1000; // 1 초            
            var successFlag = false; // 인터넷 사용 가능 여부 체크 플래그


            if (type !== null && type !== undefined && type == 0){

              // -------------------------------------------------
              // ✅ API 호출을 통해 실제 네트워크를 사용할 수 있는지 확인 : async await  
              // -------------------------------------------------
              //* 
              const controller = new AbortController();
              const timer = setTimeout(() => controller.abort(), timeoutMs);
                          
              try {

                for (var i=0; i<apiArray.length; i++){
                  const url = apiArray[i];

                  await fetch(url, {
                    method: "GET",
                    signal: controller.signal,
                    cache: "no-store",
                  }).then((response) => {
                    console.log(`API : ${url} / Status : ${response.status}`);

                    if (response.status !== undefined && response.status !== null && response.status >= 200 && response.status < 300){
                      returnJson.networkUse = true; // 👌 set value
                      successFlag = true;
                    }

                  }).catch((error) => {
                    console.error(`API : ${url} / Error : ${error.name}`);
                  });

                  if (successFlag == true){
                    break; // for end
                  }
                }

                console.warn('api call result : ', successFlag);

              } 
              catch(err){
                console.error('api call exception : ', err);
              }
              finally {
                clearTimeout(timer);
              }
              // */
              // -------------------------------------------------
              
            }
            else {

              // -------------------------------------------------
              // ✅ 이미지 호출을 통해 실제 네트워크를 사용할 수 있는지 확인 : async await  
              // -------------------------------------------------
              //* 
              const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

              try {

                for (var i=0; i<apiArray.length; i++){
                  const url = apiArray[i];

                  const timestampUrl = url + (url.includes('?') ? '&' : '?') + '_=' + Date.now()

                  const img = new Image();
                  
                  img.onload = () => { console.log(`Img : ${timestampUrl} / Load : Success`); successFlag = true; }; // 이벤트 등록
                  img.onerror = () => { console.error(`Img : ${timestampUrl} / Load : Error`); }; // 이벤트 등록

                  img.src = timestampUrl; // 이미지 로드 수행

                  await sleep(timeoutMs); // 지정 된 시간 대기
                  
                  URL.revokeObjectURL(timestampUrl); // 곧바로 무효화 → 로딩 실패 유도

                  if (successFlag == true){
                    returnJson.networkUse = true; // 👌 set value
                    break; // for end
                  }
                }

                console.warn('img call result : ', successFlag);

              }
              catch(err){
                console.error('img call exception : ', err);
              }
              // */
              // -------------------------------------------------
              
            }

            console.log('getConnectionSnapshot : return : ', JSON.stringify(returnJson));
          }
          catch(exception){
            console.error('getConnectionSnapshot : exception : ', exception);

            returnJson = {
              navigatorSupport: null,
              connectType: null,
              effectiveType: null,
              rtt: null,
              saveData: null,
              onlineHint: null,
              timestamp: null,
              networkUse: null,
            };

          }

          return returnJson;
          
        };

    </script>


</head>


<body>

</body>

</html>

-----------------------------------------------------------------------------------------





-----------------------------------------------------------------------------------------
[참고 사이트]
-----------------------------------------------------------------------------------------

[자바스크립트 navigator.connection 네트워크 품질 확인 및 img.src , fetch api 호출로 실제 네트워크 사용 가능 확인]

https://kkh0977.tistory.com/8675

https://blog.naver.com/kkh0977/224207600000


[자바스크립트 navigator.onLine 사용해 현재 연결 된 네트워크 온라인 및 오프라인 상태 확인]

https://kkh0977.tistory.com/8064

https://blog.naver.com/kkh0977/223902534905?trackingCode=blog_bloghome_searchlist


[navigator (네비게이터) 사용해 브라우저 정보 확인 실시 - userAgent , cookieEnabled]

https://kkh0977.tistory.com/853

https://blog.naver.com/kkh0977/222393616945?trackingCode=blog_bloghome_searchlist


[navigator platform 사용해 pc 및 모바일 접속 확인, navigator userAgent 사용해 접속한 모바일 종류 확인]

https://kkh0977.tistory.com/873

https://blog.naver.com/kkh0977/222399340657?trackingCode=blog_bloghome_searchlist

-----------------------------------------------------------------------------------------
 
728x90
반응형
Comments