본문 바로가기
javascript

2024-03-04

by rewind 2024. 3. 4.

직렬화 <-> 역직렬화 이유?

 

네트워크에서 객체를 보낼때 사용 , 편의성(객체를 다루기 편리)

객체자체를 보내면 꺼내서 해당타입으로 다시 변환해야하기 때문에 불편하다

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
// 제한사항 : Object를 직접 저장 할 수 없음 , 오직 string만 저장가능
// localStorage.setItem("check" , {name:"이렇게 쓰면", alias:"어떻게되나 확인"});
// alert(localStorage.getItem("check"));
// alert({name:"이렇게 쓰면", alias:"어떻게되나 확인"});

// 객체를 저장할 떄는 꼭 문자열로 변환(serialize)해서 저장해야한다
// JSON.stringify
localStorage.setItem("check" , JSON.stringify({name:"이렇게 쓰면", alias:"어떻게되나 확인"}));
localStorage.setItem("check2" ,["인","호","여","친","null"]);   // 문제점?

//alert(typeof(localStorage.getItem("check2")));  // 꺼내보면 string타입이다, 아래와같이 작성
localStorage.setItem("check2" ,JSON.stringify(["인","호","여","친","null"]));   // 이렇게 작성

// 객체가 문자열이 저장되어 있을 때 , 그 일부 속성만 변경하려 할 때
// 실제로는 그 객체를 전부 다시 문자열화해서 저장해야 한다(수정 -> 덮어쓰기)
let check2Arr = JSON.parse(localStorage.getItem("check2")); // 먼저 읽어와야 함 -> 읽어온 데이터의 타입은? string , 배열문자열
// 먼저 읽어서 -> JSON으로 변환(역직렬화)
check2Arr[3] = "사람";  // 메모리상의 수정
localStorage.setItem("check2" , JSON.stringify(check2Arr)); // 메모리상의 데이터를 localStorage(하드디스크)에 저장

</script>

 

//dummyData.html

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
// 객체지향 DB의 대표 MongoDB 저장방식 흉내내기

const tblName = "tb_member";    // key값으로 사용,(테이블명)

let tblRows = [];
for(let i = 0; i <= 108 ; i++){
    let member = {
        name : "이름 " + i,
        age : Math.round(Math.random() * 80) + 20,  // 20 ~ 100
        alias : "별명 " + i
    }
    tblRows.push(member);
}
localStorage.setItem(tblName , JSON.stringify(tblRows));    // 로컬스토리지에 저장
// 문법적으로 이상한 곳이 있나 없나? -> 없음
</script>

 

위와 같이 작성 후 실행

이런식으로 나오면 성공

 

localStroage를 어떻게 활용하는지가 중요(기능구현에 따라)

기본적으로 쿠키를 사용하는 것은 전부 로컬스토리지 사용가능

 

// list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>localStorage 간략 활용</title>
</head>
<body>
    <div id="disp">
        <table border="1">
            <thead>
                <tr><th>순번</th><th>이름</th><th>나이</th><th>별명</th></tr>
            </thead>
            <tbody id="tblBody"></tbody>
        </table>
    </div>
    <script>
        // 전역 변수 , 함수 설정 영역
        const tblBody = document.querySelector('#tblBody');;
        // 페이지 시작되자 마자 리스트 출력
        const tblName = "tb_member";    // key값
        let tblRows = JSON.parse(localStorage.getItem(tblName));
        let tbodyStr ="";
        
        // tr위에 마우스 올라왔을때 -> 그
        const fover = function(pThis){
            pThis.style.backgroundColor = "black";
            pTHis.style.color="white";
        }
        // tr위에서 마우스 벗어났을때
        const fout = function(pThis){
            pThis.style.backgroundColor = "white";
            pTHis.style.color="black";
        }
        for(let i = 0 ; i< tblRows.length ; i++){
            let row = tblRows[i];
            tbodyStr +=`
                        <tr onmouseover='fover(this)' onmouseout='fout(this)'>
                            <td>${i}</td>
                            <td>${row.name}</td>
                            <td>${row.age}</td>
                            <td>${row.alias}</td>
                        </tr>`;
        }
        tblBody.innerHTML = tbodyStr;   // 화면에 출력
    </script>
</body>
</html>

 

테이블 형식으로 출력, 동적 바인딩을 위한 onmouseover , onmouseout 함수 선언

이벤트 핸들러(함수)에서 특별히 넘길 파라미터가 없으면 this를 넘긴다.

이때 this가 가리키는 대상은 이벤트 객체 자기자신이고,

호출시에는 this를 쓸수있지만 선언시에는 작성할 수없다(키워드)

 

무한스크롤 -> 휴대폰에서 많이 사용(페이징 대신) , 이후 데스크탑에도 사용

 

처음부터 모든 데이터를 가져오는게 아니고 마지막즈음에 데이터를 전부 가져온다

원리? 브라우저의 크기보다 html문서의 크기가 크다

scroll top (윗부분 높이)

client height(사용자 눈에 보이는 화면높이)

scroll height(문서 전체 높이)

스크롤이 끝까지 올라가면

scroll Top + client height = scroll height 이면 끝이라 가정

 

documentElement -> 실시간으로 변하는 일부 정보를 저장(body태그가 무거워 짐에 따라 새로 생긴 함수)

documentElement은 일종의 버퍼로써 무한스크롤 외에 사용처가 드물다

 

// 무한스크롤.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<h1>무한스크롤 휴대폰에 많이 적용</h1>
<h1>스크롤바가 생길만큼 생성</h1>
...
...
...(알아서 추가)
<h1>스크롤바가 생길만큼 생성</h1>
<script>
    const fScroll = function(){
        let scrollTop = document.documentElement.scrollTop; // 위로 올라간 높이
        let clientHeight = document.documentElement.clientHeight;   // 사용자 눈에 보이는 화면 높이
        let scrollHeight = document.documentElement.scrollHeight;   // 문서 전체 높이

        const tunningVal = 50; // 약간의 튜닝값을 준다
        // 스크롤바를 끝까지 내렸을 때
        if((scrollTop + clientHeight) >= (scrollHeight -tunningVal) ){
            // alert("여기서 추가 데이터를 처리한다");
            // 일반적으로 여기서 Ajax를 이용해서 추가 데이터를 가져와서 , 화면에 추가해준다
            // 없으면 그것으로 끝 , 데이터가 추가되지 않으면 스크롤바도 확장안됨
            let addHtml = "";
            for(let i=1 ; i<= 10; i++){
                addHtml += `<h1>스크롤바가 생길만큼 생성${i}</h1>`;
            }
            document.body.innerHTML += addHtml; // 내용 추가 , 계속 추가된다
        }
        /* scrollTop + clientHeight >= scrollHeight 스크롤바를 끝까지 내렸을때
        console.log("구분선","===============================================================")
        console.log("scrollTop" , scrollTop );
        console.log("clientHeight" , clientHeight );
        console.log("scrollHeight" , scrollHeight );
        */
    }
    window.addEventListener("scroll" , fScroll)
</script>
</body>
</html>

 

실행후 console.log확인해보면 실시간으로 scroll 길이가 변하는걸 확인가능

 

무한스크롤2.html

// 무한스크롤2.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
<style>
    #muScroll {
        width:70%;
        height: 300px;
        border: 1px solid black;
        overflow: scroll; 
        /* */
    }
</style>
</head>
<body>
<h1>무한스크롤을 특정 DIV(곧 특정영역)에 적용</h1>
<div id="muScroll">
    <h1>스크롤바가 생길만큼 생성</h1>
   ...
   ...
   ...
    <h1>스크롤바가 생길만큼 생성</h1>
</div>
<script>
    const fScroll = function(){
        let scrollTop = document.documentElement.scrollTop; // 위로 올라간 높이
        let clientHeight = document.documentElement.clientHeight;   // 사용자 눈에 보이는 화면 높이
        let scrollHeight = document.documentElement.scrollHeight;   // 문서 전체 높이

        const tunningVal = 50; // 약간의 튜닝값을 준다
        // 스크롤바를 끝까지 내렸을 때
        if((scrollTop + clientHeight) >= (scrollHeight -tunningVal) ){
            // alert("여기서 추가 데이터를 처리한다");
            // 일반적으로 여기서 Ajax를 이용해서 추가 데이터를 가져와서 , 화면에 추가해준다
            // 없으면 그것으로 끝 , 데이터가 추가되지 않으면 스크롤바도 확장안됨
            let addHtml = "";
            for(let i=1 ; i<= 10; i++){
                addHtml += `<h1>스크롤바가 생길만큼 생성${i}</h1>`;
            }
            document.body.innerHTML += addHtml; // 내용 추가 , 계속 추가된다
        }
        /* scrollTop + clientHeight >= scrollHeight 스크롤바를 끝까지 내렸을때
        console.log("구분선","===============================================================")
        console.log("scrollTop" , scrollTop );
        console.log("clientHeight" , clientHeight );
        console.log("scrollHeight" , scrollHeight );
        */
    }
    window.addEventListener("scroll" , fScroll)
</script>
</body>
</html>

 

overflow -> 요소내의 컨텐츠가 너무 커서 보여줄 방식을 선택해야 할때

 

스크롤바에 이벤트를 건다 

특정 영역에 스크롤바 -> 데스크탑에서 주로 사용

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
<style>
    #muScroll {
        width:70%;
        height: 300px;
        border: 1px solid black;
        overflow: scroll; 
        /* */
    }
</style>
</head>
<body>
<h1>무한스크롤을 특정 DIV(곧 특정영역)에 적용</h1>
<div id="muScroll">
    <h1>스크롤바가 생길만큼 생성</h1>
    ...
    적당히 채운다
    ...
    <h1>스크롤바가 생길만큼 생성</h1>
</div>
<script>

    const muScroll = document.querySelector("#muScroll");

    const fScroll = function(){
        let scrollTop = muScroll.scrollTop; // 위로 올라간 높이
        let clientHeight = muScroll.clientHeight;   // 사용자 눈에 보이는 화면 높이
        let scrollHeight = muScroll.scrollHeight;   // 문서 전체 높이

        const tunningVal = 50; // 약간의 튜닝값을 준다
        // 스크롤바를 끝까지 내렸을 때
        if((scrollTop + clientHeight) >= (scrollHeight -tunningVal) ){
            // alert("여기서 추가 데이터를 처리한다");
            // 일반적으로 여기서 Ajax를 이용해서 추가 데이터를 가져와서 , 화면에 추가해준다
            // 없으면 그것으로 끝 , 데이터가 추가되지 않으면 스크롤바도 확장안됨
            let addHtml = "";
            for(let i=1 ; i<= 5; i++){
                addHtml += `<h1>스크롤바가 생길만큼 생성${i}</h1>`;
            }
            muScroll.innerHTML += addHtml; // 내용 추가 , 계속 추가된다
        }
        /* scrollTop + clientHeight >= scrollHeight 스크롤바를 끝까지 내렸을때
        console.log("구분선","===============================================================")
        console.log("scrollTop" , scrollTop );
        console.log("clientHeight" , clientHeight );
        console.log("scrollHeight" , scrollHeight );
        */
    }
    muScroll.addEventListener("scroll" , fScroll)
</script>
</body>
</html>

 

데이터가 없는 지점에서 끝이 난다. 무한스크롤 , 무한스크롤2 의 차이점?

무한스크롤2.html에서는 새로고침시 스크롤바도 초기화되고 무한스크롤.html에서는

새로고침해도 그지점에 스크롤바가 위치한다 -> 페이지 시작시 스크롤바를 가장 위에 올려놓으려면?

 

list.html에 무한스크롤 적용하기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>localStorage 간략 활용</title>
</head>
<body>
    <div id="disp">
        <table border="1">
            <thead>
                <tr><th>순번</th><th>이름</th><th>나이</th><th>별명</th></tr>
            </thead>
            <tbody id="tblBody"></tbody>
        </table>
    </div>
    <script>
        // 전역 변수 , 함수 설정 영역
        const tblBody = document.querySelector('#tblBody');;
        // 페이지 시작되자 마자 리스트 출력
        const tblName = "tb_member";    // key값
        let tblRows = JSON.parse(localStorage.getItem(tblName));
        let tbodyStr ="";
        
        // tr위에 마우스 올라왔을때 -> 그
        const fover = function(pThis){
            pThis.style.backgroundColor = "black";
            pTHis.style.color="white";
        }
        // tr위에서 마우스 벗어났을때
        const fout = function(pThis){
            pThis.style.backgroundColor = "white";
            pTHis.style.color="black";
        }
        // 리스트 출력 함수
        let pageNum = 1;    // default value
        let pageSize = 20;  // 페이지당 10개
        let startNum = (pageNum - 1) * pageSize;
        let endNum = startNum + pageSize;

        setTimeout( () => {
            window.scriollTo(0,0);
        })
//        let endNum = startNum + pageSize; 부등호 처리를 어떻게 하는지에 따라서 아래위 둘다 가능
        const flist = function(pStartNum , pEndNum){
            tbodyStr = "";
            for(let i = pStartNum ; i < pEndNum ; i++){
                console.log("체크 : " , i);
                let row = tblRows[i];
                tbodyStr +=`
                <tr onmouseover='fover(this)' onmouseout='fout(this)'>
                    <td>${i}</td>
                    <td>${row.name}</td>
                    <td>${row.age}</td>
                    <td>${row.alias}</td>
                </tr>`;
                }
                tblBody.innerHTML += tbodyStr;   // 화면에 출력
            }
            flist(startNum , endNum);
            // 무한 스크롤 적용
        const fScroll = function(){
            let scrollTop = document.documentElement.scrollTop; 
            let clientHeight = document.documentElement.clientHeight;   
            let scrollHeight = document.documentElement.scrollHeight;   
            const tunningVal = 50;
            if((scrollTop + clientHeight) >= (scrollHeight -tunningVal) ){
                pageNum++;
                startNum = (pageNum - 1) * pageSize;
                endNum = startNum + pageSize;
                
                // 마지막 index번호 체크 필요! -> 데이터가 108까지 밖에 없는데 어떻게 처리해야하는지?! 120일 경우!
                if(endNum >= tblRows.length){
                    endNum = tblRows.length;
                }
                // 
                flist(startNum , endNum);   // 리스트 함수 호출
            }
    }
    window.addEventListener("scroll", fScroll);
    </script>
</body>
</html>

 

localStorage

쿠키대신 사용가능 , 문자열만 저장가능(제약사항) , 서버에 저장할 필요가 없는 데이터를 저장시 사용

상황에 따라서 버퍼로 사용해서 성능 향상을 시킬 수 있다 -> 최프에 적용할 곳?

 

화살표함수 -> window객체

제약조건 외우지 말고 this사용해야할시 function 사용

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
// 화살표 함수에서 this에 대한 제약
// 제약조건을 외우지 말고 , this제어가 필요하면 function키워드를
// 그냥 쓰는것이 편하다

// function 키워드로 만들어진 함수는 prototype(function에만 있음 , 생성자) 속성을 가지는데
// () => 로 만들어진 함수는 prototype속성을 가지지 않는다(window객체를 가리킨다)

const yyj = {name:"양손연주"};

yyj.msg1 = () =>{
    console.log("msg1", this);  // 이렇게 function 키워드 사용을 권장
}
yyj.msg2 = function(){
    console.log("msg2", this);
}
yyj.msg1.call({name:"성우신"}); // 화살표함수 적용 안됨 , call , apply , bind도 적용 안됨
yyj.msg2.call({name:"민준정"});

</script>

 

화살표함수에서 this사용하려면 스코프의 이해가 필요하다? -> 가성비 떨어짐