스터디/KAKAOCLOUDSCHOOL

[JavaScript] 개발자 지망생 스터디 - 10일차

shineIT 2022. 11. 15. 17:50

 HTML5 

■ Geo Location

  1. 개요
    • 디바이스의 물리적 위치 정보를 파악하기 위한 Javascript API
    • 위치 정보
      • GPS와 같은 위성 정보를 이용해서 가져오는 방법
        • 가까운 라우터의 위치
        • 기지국의 위치 (가장 부정확함)
    • 위치 정보 사용을 허용 해야만 사용 가능
  2. 위치 정보 사용 가능 여부 확인
    • navigator.geolocation 의 값을 확인
  3. 위치 정보를 가져와서 한 번만 사용하기
    • navigator.geolocation.getCurrentPosition(위치 정보를 가져오는데 성공했을 때 호출되는 함수, 위치정보를 가져오는데 실패했을 때 호출되는 함수, 옵션)
      • 위치정보를 가져오는데 성공했을 때 호출되는 함수에는 매개변수로 위치 정보롸 관련된 객체가 전달됨
        • 이 객체가 저장하고 있는 정보는 JavaScript 뿐 아니라 모바일 API에서도 동일
        • coords : latitude(위도), longitude(경도), altitude(고도-GPS가 아니면 없음), accuracy(정확도), altitudeAccuracy(고도의 정확성), heading(방향), speed(속도)
        • timestamp : 위치 정보를 가져온 시간
      • 위치정보를 가져오는데 실패했을 때 호출되는 함수에도 매개변수가 넘어가는데 이 경우에는 에러 객체가 전달되고 code 속성을 확인하면 실패의 이유를 알 수 있음
  4. 위치 정보를 계속 가져와서 사용하기
    • let 변수 navigator.geolocation.watchPosition(위치 정보를 가져오는데 성공했을 때 호출되는 함수, 위치 정보를 가져오는데 실패했을 때 호출되는 함수, 옵션)
      • 위치 정보를 계속해서 파악하고 clearWatch(변수)를 호출하면 더 이상 위치 정보를 가져오지 않음.
  5. 옵션
    • 객체 형태로 대입
      • { enableHighAccuracy : 정확도가 높은 위치 정보를 사용하도록 하는 옵션. 기본값은 false
      • timeout : 일정 시간이 지난 데이터는 폐기하는 옵션으로 밀리초 단위로 설정
      • maximumAge } : 0을 설정하면 항상 최신의 데이터를 가져옴. 위치 정보를 가져오는 주기
    • 스마트폰을 이용하는 경우 옵션 설정이 중요함.
      • 스마트폰 배터리문제로 배터리를 가장 많이 소모하는 2가지 문제가 블루투스, GPS 를 이용하는 경우임.
  6. 웹 화면에 현재 위치에 해당하는 카카오 맵을 출력
    • KAKAO Open API : https://developers.kakao.com/
    • Key 발급
      • 내 애플리케이션 ->애플리케이션 추가하기 -> key copy : -
      • key는 바로 사용이 불가능 - 플랫폼 등록이 필요
        • 네이티브 앱은 앱의 패키지 이름을 등록해야함
        • 웹의 경우는 도메인을 등록해야함
        • 연습할 때는 웹의 경우 http://localhost : 포트번호 형태로 등록하고 실제 서비스에 사용할 때는 localhost:포트번호 대신에 등록한 도메인이나 실 사용이 가능한 공인 IP 형태로 변경을 해야함
      • 플랫폼 등록 - http://localhost:5500
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GeoLocation</title>
</head>
<body>
    <div id="map" style="width:500px;height:400px;"></div>
	<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=--"></script>
	<script>
        var mapTypes = {
            terrain : kakao.maps.MapTypeId.TERRAIN,    
            traffic :  kakao.maps.MapTypeId.TRAFFIC,
            bicycle : kakao.maps.MapTypeId.BICYCLE,
            useDistrict : kakao.maps.MapTypeId.USE_DISTRICT
        };

        navigator.geolocation.getCurrentPosition((position) => {
            var container = document.getElementById('map');
            var options = {
                center: new kakao.maps.LatLng(
                    position.coords.latitude, position.coords.longitude
                ),
                level: 3
            };
            var map = new kakao.maps.Map(container, options);
            map.addOverlayMapTypeId(mapTypes.traffic);

            // 마커가 표시될 위치
            var markerPosition  = new kakao.maps.LatLng(
                position.coords.latitude, position.coords.longitude);
            // 마커 생성
            var marker = new kakao.maps.Marker({
                position: markerPosition
            });
            // 마커 지도 위에 표시
            marker.setMap(map);
        }, (error) => {

        })
	</script>
</body>
</html>

■ File API

  • File을 읽고 쓰기 위한 API
  • input type의 file에 miltiple 속성이 추가되서 이 속성의 값을 설정하면 여러 개의 파일을 선택하는 것이 가능
  • 텍스트 파일을 읽을 때는 인코딩 설정에 주의해야 함
  • 일반 파일을 읽을 때는 File Reader 객체를 생성한 후 reader.readAsDataURL(파일 객체)를 호출하고 load 이벤트와 error 이벤트를 처리 함
  • load는 전부 읽었을 때 FileReader 객체의 result에 읽은 내용을 저장하고 error 이벤트는 읽기에 실패했을 때 실패한 이유를 저장하고 있는 객체를 넘겨줌
  • 이미지 미리보기
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>이미지 미리보기</title>
</head>
<body>
    <!-- 이미지 파일만 선택할 수 있는 file 객체 -->
    <input type="file" accept="image/*" id="imginput"/>
    <!-- 이미지 미리보기 영역 -->
    <img id="display" width="250" height="250"/>

    <script>
        // 필요한 DOM 객체 찾아오기
        let imginput = document.getElementById("imginput");
        let display = document.getElementById("display");

        // imginput 의 선택이 변경되면
        imginput.addEventListener("change", (e) => {
            // 선택한 파일의 내용을 읽기 - 비동기적 수행
            let reader = new FileReader();
            // 파일이 선택되었는지 확인
            // JS에서는 0이 아닌 숫자, null, undefined 가 아니면 true로 간주 - turthy
            if(!(imginput.files && imginput.files[0])){
                alert("선택된 파일이 없음");
                display.src = null;
                return;
            }

            reader.readAsDataURL(imginput.files[0]);
            // 파일의 내용을 다 읽으면 - callback
            reader.addEventListener("load", () => {
                // 읽은 내용을 이미지의 소스로 사용
                display.src = reader.result;
            })
        });
    </script>
</body>
</html>

■ Drag & Drop API

  • 브라우저 내에서 사용할 수 있고 외부 프로그램과 브라우저 사이에서도 사용할 수 있음
    • 외부 프로그램과 사용할 때는 외부 프로그램에서 드래그를 하고 브라우저에 드랍을 해야 함
    • 파일을 첨부할 때 많이 사용함

  브라우저에 데이터를 저장

  1. 브라우저에 데이터를 저장하는 이유
    • 불필요한 트래픽을 줄이기 위해서
      • 메일 앱의 경우 매번 서버에 접속해서 서버의 데이터를 받아오는 것은 자원의 낭비가 될 수 있음.
      • 맨 처음 접속을 할 때는 데이터를 다운로드 받고 (파일의 존재 여부 확인)
      • 다음 부터는 마지막 업데이트된 시간을 비교해서 양쪽의 시간이 다르면 데이터가 수정된 것으로 간주하여 다운로드를 받고 양쪽의 시간이 같다면 업데이트된 내용이 없으므로 다운로드를 받지 않도록 구현함
        • 서버를 업데이트할 때는 마자막 업데이트 날짜 시간을 기록하는 것이 중요함
    • 오프라인 상태에서도 데이터를 사용하기 위해서
      • local에 데이터 저장
  2. 브라우저에 데이터를 저장하는 방법
    • Web Storage : Map의 형태로 저장
    • Web SQL : 관계형 데이터베이스(SQLite3 - 외부에서는 접속이 불가능한 저용량 데이터베이스, 사용법은 MySQL과 유사) 이용
    • Indexed DB : 자바스크립트 객체 형태로 저장 - NoSQL과 유사
    • 기존에는 쿠키를 사용했는데 Cookie를 사용하게 되면 문자열만 저장할 수 있고, 서버에 매번 전송됨.전송 여부를 클라이언트가 결정할 수 없다,
  3. Web Storage
    • 종류
      • LocalStorage : 브라우저에 저장해서 지우지 않는 한 절대 삭제가 되지 않는 저장소
      • SesstionStorage : 현재 접속 중인 브라우저에 해당하는 저장소로 접속이 종료되면 소멸
    • 데이터 저장과 가져오기 그리고 삭제
      • 저장 : 스토리지.키이름 = 데이터, 스토리지.["키이름"] = 데이터, 스토리지.setitem("키이름",데이터)
      • 가져오기 : 스토리지.키이름, 스토리지.["키이름"], 스토리지.getitem("키이름")
      • 삭제 : delet 스토리지.키이름, delet 스토리지.["키이름"], 스토리지.removeitem("키이름")
    • 저장소에 데이터가 변경되면 window 객체에 storage 이벤트가 발생하고 이벤트 객체에는 key, oldValue, newValue, url, storageArea 같은 속성이 만들어 짐
    • Local Storage는 전역 변수 localStorage로 사용할 수 있고 Session Storage는 sessionStorage로 사용할 수 있음
    • 저장된 내용을 확인하는 방법은 브라우저의 검사 창에서 application을 확인하면 됨
    • 세션 스토리지 - 브라우저를 종료했을 때 내용이 소멸되는지 와 현재 창에서 새창을 출력했을 때 내용이 복제가 되는지 확인
    • 로컬 스토리지 - id 저장을 구현하는데 브라우저를 종료하고 다시 연결했을 때 내용이 존재하는지 여부를 확인
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>세션 스토리지</title>
</head>
<body>
    <!-- 2개의 문자열 입력받는 도구와 버튼 3개 -->
    key<input type="text" id="keyinput"/>
    value<input type="text" id="valueinput"/>
    <input type="button" value="삽입" id="insertbtn"/>
    <button id="removebtn">삭제</button>
    <button id="addwindowbtn">윈도우 추가</button>

    <!-- 데이터 출력 영역 -->
    <fieldset>
        <legend>데이터 출력 영역</legend>
        <select id="list" size="10"></select>
    </fieldset>

    <script>
        let keyinput = document.getElementById("keyinput");
        let valueinput = document.getElementById("valueinput");
        let insertbtn = document.getElementById("insertbtn");
        let removebtn = document.getElementById("removebtn");
        let addawindowbtn = document.getElementById("addwindowbtn");
        let list = document.getElementById("list");

        // 세션 스토리지의 내용을 읽어서 list에 출력하는 함수
        // 처음 접속할 때 그리고 삽입이나 삭제를 할 때
        // 매번 데이터를 다시 출력할 생각으로 코드를 여러번 작성을 하지 않기 위함임.
        const showData = () => {
            // list의 내용 초기화
            list.innerHTML="";

            // sessionStorage 순회 하나씩 읽기
            for(let i=0; i<sessionStorage.length; i++){
                let temp = sessionStorage.key(i);
                // select 에 옵션을 추가
                list.options[list.options.length] = new Option(temp + ":" + sessionStorage[temp], temp);
            }
        }
        
        // 윈도우가 모든 데이터를 로드 한 후
        window.addEventListener("load", () => {
            // Live Server를 이용해서 실행하면 기본적으로 하나의 데이터가 저장되서 출력됨
            showData();
        })

        // Insert 삽입 버튼을 눌렀을 떄
        insertbtn.addEventListener("click", () => {
            // 세션 스토리지에 저장
            sessionStorage[keyinput.value] = valueinput.value;
            // 데이터를 다시 출력
            showData();
        })

        // list를 클릭했을 때 클릭한 데이터를 input에 출력
        list.addEventListener("click", () => {
            // 선택한 데이터 찾아오기
            let selecteddata = list.options[list.selectedIndex];
            keyinput.value = selecteddata.value;
            valueinput.value = sessionStorage[selecteddata.value];
        })

        // 삭제 버튼을 눌렀을 때 선택된 데이터 삭제
        removebtn.addEventListener("click", () => {
            delete sessionStorage[keyinput.value];
            showData();
        });

        // 윈도우 추가 버튼을 눌렀을 때 새창으로 열기
        addwindowbtn.addEventListener("click", () => {
            // 새창에서 열면 세션은 현재 내용을 복제해서 생성
            window.open(location.href);
        })
    </script>
    
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>local Storage ID 저장</title>
</head>
<body>
    <form method="post" action="login" id="loginform">
        ID<input type="text" id="id"/><br/>
        PW<input type="password" id="pw"/><br/>
        <input type="checkbox" id="idsave"/>아이디 기억하기<br/>
        <input type="submit" value="로그인"/>
    </form>
    <script>
        let loginform = document.getElementById("loginform");
        let userid = document.getElementById("id");
        let userpw = document.getElementById("pw");
        let idsave = document.getElementById("idsave");

        // form의 데이터를 전송 (submit)
        loginform.addEventListener("submit", () => {
            // check 여부 확인
            if(idsave.checked === true){
                // 로컬 스토리지에 저장
                localStorage.saveid = userid.value;
            }else{
                // 로컬 스토리지에서 삭제
                delete localStorage.saveid;
            }
        });

        // 메모리 로드가 끝나면 userid 저장되어 있으면 가져오기
        window.addEventListener("load", () => {
            if(typeof localStorage.userid != 'undefined'){
                userid.value = localStorage.saveid;
                idsave.checked = true;
            }
        })
    </script>
</body>
</html>
  • 로컬 스토리지는 보안이 중요하지 않은 많지 않은 양의 데이터를 저장하는데 용이
    • 장바구니 구현이나 저장에 유용하게 사용 가능
  • 동일한 패턴의 데이터가 많은 경우, 로컬 스토리지 보다는 Web SQL 이나 Indexed DB를 권장

■ Web Worker

  • Javascript를 이용한 백그라운드 처리
  • Javascript에서는 Thread 표현 대신에 Worker 라는 표현을 사용
  • HTML 과 함께 있는 Javascript 코드에서 긴 작업을 수행하게 되면 작업이 끝날때까지 다른 작업을 수행할 수 없음(UI는 아무것도 할 수 없는 상태)
  • Web Worker는 UI 변경을 하지 못하고 DOM 객체 제어를 할 수 없지만 localStorage와 XMLHttpRequest(ajax) 사용은 가능
  • Wev Worker 생성
    • let 변수 = new Worker("자바스크립트 파일 경로"); // 워커는 별도의 스크립트 파일에 만들어야함
  • 워커와 브라우저 사이의 메시지 전송
    • 워커변수.postMessage("메시지") => 워커에서는 message 이벤트가 발생함
    • 워커 file 에서는 postMessage("메시지")  => 워커 변수에 message가 발생함
  • sendMessage는 바로 처리해달라는 요청이고 postMessage는 다른 작업이 없으면 처리해달라고 하는 요청임
  • message 이벤트가 발생하면 매개변수에 data 와 error를 가진 객체가 전달됩니다
    • data는 data이고 error는 에러가 발생했을 때 에러에 대한 정보를 가진 객체임
  • 워커는 terminate()를 호출해서 중지가 가능

1. 계산 작업을 대신 수행해주는 워커 생성 - worker.js

// html에서 요청이 오면
onmessage = (event) => {
    // html에서 전송한 데이터 받기
    let num = event.data;
    // 1부터 num까지 합계 구하기
    let result = 0;
    for(let i=0; i<=num; i++){
        result += i;
    }
    // html 파일로 결과를 전송
    postMessage(result);
}

2. 워커를 호출하는 코드 작성 - html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>웹 워커</title>
</head>
<body>
    <h1>Web Worker</h1>
    숫자 입력<input type="number" id="num"/>
    <button id="start">합계 구하기</button>

    <script>
        let num = document.getElementById("num");
        let start = document.getElementById("start");

        let worker;
        start.addEventListener("click", () => {
            // 워커가 만들어져 있으면 중지
            if(worker){
                worker.terminate();
            }
            // 워커 생성
            worker = new Worker("worker.js");
            // 메시지 전송
            worker.postMessage(Number(num.value));
            // 워커가 결과를 전송했을 때
            worker.onmessage = (event) => {
                // 워커가 전송한 데이터 출력
                alert(event.data);
            }
        });
    </script>
</body>
</html>

■ Application Cache

  • 리소스의 일부분을 로컬에 저장하기 위한 기능
  • 오프라인 브라우징이 가능해지고 리소스를 빠르게 로드 할 수 있고 서버 부하를 감소시킬 수 있음.
    • css나 js 그리고 이미지 파일 등을 캐싱

  Web Push

  • Server Sent Events : 클라이언트의 요청 없이 서버가 클라이언트에게 메시지를 전송하는 것
  • 사용 이유 : 알림
  • Apple Server가 보내는 Push를 APNS(Apple Push Notification Service)
  • Google Server가 보내는 Push를 FCM(Firebase Cloud Message)라고 함.

  Web Socket

  • Web에서의 TCP 통신을 위한 API
  • 일반적인 Web 요청의 처리 방식은 Client가 Server에게 접속을 한 후 하나의 request 를 전송하고 그 request를 Server가 받으면 처리를 하고 response 를 Client에게 전송하고 접속이 끊김
  • 연속되는 작업을 처리하기 위해서 Cookie(클라이언트의 브라우저에 저장) 와 Session(서버에 저장) 이라는 개념을 도입
  • 일반적인 Web 요청(HTTP 나 HTTPS)은 본문 이외에 헤더 정보를 같이 전송해야 함.
  • 작은 사이즈의 데이터를 보내는 경우 오버헤드가 너무 큼
  • Web Socket을 이용하면 헤더가 거의 없기 때문에 이러한 오버헤드를 줄일 수 있음
    • 작은 양의 메시지를 자주 주고 받는 경우는 ajax 나 Fetch API 보다는 Web Socket을 사용하는 것을 권장

Node.js

1. 개요

  • 애플리케이션을 개발할 수 있는 자바스크립트 환경
  • 원래 자바스크립트는 브라우저 내에서 동적인 작업을 처리하기 위한 언어
  • 실제 내부 코드는 C++로 되어 있음
    1. 장점
      • 자바스크립트 엔진을 사용하기 때문에 접근이 쉬움 - Learning Curve가 짧다
      • 비동기 방식으로 리소스 사용량이 적음
      • 다양한 라이브러리 제공
    2. 단점
      • Native 언어로 만든 서버 환경보다는 느릴 수 있음.
      • 짧은 시간에 대량의 클라이언트 요청을 대응하는 웹 애플리케이션 개발에 적합하고 대량의 데이터를 조회하고 긴 처리 시간을 요구하는 작업에는 부적합
        • 이러한 단점의 대용량 연산 작업을 할 때는 직접 구현하지 않고 AWS의 Lambda나 Google Cloud Functions 같은 서비스를 이용하여 어느정도 해결 가능함
    3. 웹 서버 이외의 노드
      • SPA(Single Page Application) : Angular, React, Vue 등
      • 모바일 앱 프레임워크 : React Native
      • 데스크 탑 애플리케이션 : Eeletron(Atom, slack, VSCode, 블록체인 애플리케이션 등)
    4. 외부 라이브러리 활용
      • npm 이라는 프로그램을 이용
      • npm을 이용하면 기능을 확장한 수많은 모듈을 쉽게 다운로드 하고 설치할 수 있음
        • 최근에는 npm 대신 yarn을 사용하는 경우도 많음

2. Node 설치

  1. 버전
    • LTS : 안정화된 버전으로 짝수
    • Current : 현재 개발중인 버전
  2. 설치
    • Windows 는 https://nodejs.org에서 다운로드 받아서 설치
    • Mac은 다운로드 받아서 설치해도 되고 터미널 brew install node 로 설치 가능
  3. 설치 확인
    • 터미널
      • node -v : 노드 버전 확인
      • npm -v : npm 버전 확인
  4. IDE 설치
    • VSCode 사용

3. Node 프로젝트 만들기

  • 빈 디렉토리에서 npm init 이라는 명령어로 생성하고 옵션을 설정
  • 옵션 설정
    • pakage name : pakage를 배포할 때 사용할 이름이며 디렉토리 이름과 같으면 안됨.
    • version : 버전 (나온 버전 그대로 엔터를 쳐도 무방함)
    • description : 앱에 대한 설명
    • entry point : 시작하는 파일 이름 (앱의 출발점으로 index.js or App.js를 많이 사용
    • test command : 앱을 테스트할 때 사용할 명령어 이름
    • git repository : git 과 연동할 때 사용할 URL
    • keywords : 패키지가 배포된 경우 사용할 검색어
    • author : 제작자
    • license : ISC 나 MIT를 사용하는데 오픈 소스라는 의미
    • 생성에 성공하면 pakage.json이 생성
  • 프로젝트 실행
    • npm start 하게 되면 entry point로 지정한 파일이 실행
    • node 파일명 을 하게 되면 파일이 실행
  • cd 는 디렉토리를 변경하는 명령어
    • cd 디렉토리 이름을 입력하면 디렉토리로 프롬프트를 이동
    • cd .. 을 입력하면 상위 디렉토리로 이동