웹/프론트엔드

JavaScript Ajax _ 생활코딩

csmoon1010 2020. 11. 11. 23:06

생활코딩의 강의를 통해 JavaScript Ajax를 공부해보자

opentutorials.org/course/3281

 

Ajax - 생활코딩

수업소개 웹페이지에서 일부 정보가 달라졌음에도 전체 페이지를 리로드하는 것은 효율적이지 않습니다. Ajax는 리로드 없이 웹서버에게 정보를 요청해서 부분적으로 정보를 갱신해주는 기술입

opentutorials.org

1. Ajax란?

- Ajax = Asynchronous Javascript And Xml

- 페이지 전체를 reload할 필요없이 웹 페이지의 정보를 부분적으로 변경하기 위해 서버와 통신하는 기술

 

2. 목적

- 페이지 전환 시 매번 모든 파일이 아니라 필요한 내용(파일)만 받아옴

- 변경부분만 집중 가능 → 사용성 증대

- 시간, 돈, 네트워크 자원의 절약이 가능

- 바뀔 수 있는 부분만 ajax로 동적으로 변경 가능 → 유지보수의 용이성 (single-page application의 구현이 가능)

 

 

3. fetch API

(1) 기본 사용법

<!DOCTYPE html>
<html>
    <body>
        <article>

        </article>
        <input type="button" value="fetch" onclick="
        fetch('html').then(function(response){
            response.text().then(function(text){
                //alert(text);
                document.querySelector('article').innerHTML = text;
            })
        })
        ">
    </body>
</html>

- 'html'파일을 요청 → 응답이 끝나면 response 부분이 실행 → server가 넘겨준 데이터가 text로 이동

 

(2) fetch, then

-fetch('파일명') : server에게 파일을 요청

-then : server가 응답할 때 까지 하는 일

ex> 응답이 끝나면 지정한 함수를 실행시켜달라고 fetch API에게 요청

Asyncronous (비동기적)

: then의 실행 중에 다른 코드 함께 실행됨 = 병렬적으로 수행될 수 있음

 

<!DOCTYPE html>
<html>
    <body>
        <article>

        </article>
        <input type="button" value="fetch" onclick="
        function callbackme(){
            console.log('response end');
        }
        fetch('html').then(callbackme); //'html'을 요청하고 응답이 끝나면 callbackme 실행
        console.log(1); //Asynchronous이므로 응답 끝날 때까지 기다리지 않고 병렬적 실행 가능
        console.log(2);
        ">
    </body>
</html>

 

→ console 결과 : 1 2 response end

 

(3) response 객체

: 요청 시 웹 서버가 응답한 결과를 담고 있는 객체 (여러가지 속성 포함)

- status : 웹 서버의 응답 상태( ex> 200 - 정상, 404 - file not found )

Response 예시(console 창)

<!DOCTYPE html>
<html>
    <body>
        <article>

        </article>
        <input type="button" value="fetch" onclick="
        fetch('js').then(function(response){  //response 객체를 넘겨주면서 호출
            console.log(response)
            console.log(response.status);
            if(response.status=='404'){ //404 메시지 띄울 수 있음
                alert('Not found')
            }
        });
        console.log(1);
        console.log(2);
        ">
    </body>
</html>

 

 

4. 초기 페이지 구현

(1) 한계

- single-page applicaition : 페이지별 내용 공유의 한계

- 페이지 링크의 밑줄 사라짐(물론, css로 할 수 있긴 함)

 

(2) Hash

: 북마크 기능 = fragment identifier

- 식별자 부여 (id) → url에 id를 추가하면 해당 부분(fragment)으로 scroll되어 보여줄 수 있음

- ex> localhost/study/example.html/#three → id=three인 fragment로 이동

 

▶ 해시값을 활용해 초기 페이지를 구현할 수 있음

<!DOCTYPE html>
<head>
</head>
<body>
    <a href="#!three">three</a>
    <p>
        lorem....
    </p>
    <p>
        lorem....
    </p>
    <p id = "three">
        lorem....
    </p>
    <script>
        if(location.hash){ //현재 페이지의 hash가 있다면
            console.log(location.hash.substr(1)); //fragment id를 console에 출력
        }else{

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

CF> HashBang(#!) : 북마크 기능을 위한 href를 "#!id" 형태로 줌

<li><a href="#!html" onclick="fetchPage('html')">HTML</a></li>

<script>
    if(location.hash){
        fetchPage(location.hash.substr(2))
    }else{
        fetchPage('welcome')
    }
</script>

 

(3) 문제점

- 검색엔진 최적화 문제 : 웹페이지 자체에 실제 내용이 없음(백엔드에서 동적으로 가져옴)

- navigation(뒤로 가기) : 내용이 변화하지 않음 → HashBang(#!) 대신 pjax를 이용해 해결

 

 

5. 글목록 구현

(1) 배경

- 데이터와 로직을 구분할 필요성

: 데이터는 계속해서 변화 → 분리를 통해 유지보수의 용이성을 더한다.

 

(2) 예시 코드

- list에 file 명칭의 이름 목록만 유지하여 분리

html, css, javascript

- fetch API를 통해 list를 읽어 중복을 제거 (단, tag의 작성을 주의)

<!doctype html>
<html>
<head>
  <title>WEB1-WEB</title>
  <meta charset = "utf-8">
  <link rel="stylesheet" href="style.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="colors.js"></script>
</head>

<body>
  <h1><a href="#!welcome" onclick="fetchPage('welcome')">WEB</a></h1>
  <input type="button" value = "night" onclick="
    nightDayHandler(this);
  ">
  <div>
    <ol id = "nav">

    </ol>
    <article>

    </article>
  </div>
  <script>
    function fetchPage(name){
      fetch(name).then(function(response){
        response.text().then(function(text){
          document.querySelector('article').innerHTML = text;
        })
      });
    }
    if(location.hash){
      fetchPage(location.hash.substr(2))
    }else{
      fetchPage('welcome')
    }
    fetch('list').then(function(response){
      response.text().then(function(text){
        var items = text.split(', ');
        var i = 0;
        var tags = '';
        while(i < items.length){
          var item = items[i];
          item = item.trim();
          var tag = '<li><a href="#!' + item +'" onclick="fetchPage(\''+item+'\')">'+item+'</a></li>'
          tags = tags+tag;
          i=i+1;
        }
        document.querySelector('#nav').innerHTML = tags;
      })
    })
  </script>
</body>
</html>

 

 

6. fetch API polyfill

(1) 문제점

- fetchAPI는 비교적 최신 기술이기 때문에 지원되지 않는 브라우저가 있을 수 있음

- 확인 방법 : caniuse.com/

 

Can I use... Support tables for HTML5, CSS3, etc

 

caniuse.com

(2) 해결 : polyfill

- 과거의 브라우저를 쓰는 사람들 : 라이브러리 솔루션을 fetch API로써 사용할 수 있도록

- 지원하는 경우 : 브라우저 고유의 기능을 쓸 수 있도록

▶ 포괄적으로 "polyfill"이라고 함

github.com/github/fetch

 

github/fetch

A window.fetch JavaScript polyfill. Contribute to github/fetch development by creating an account on GitHub.

github.com

//1. 파일로 추가
<script src="fetch-master/fetch.js"></script>

//2. CDN으로 추가
<script src="https://polyfill.io/v3/polyfill.js?features=fetch"></script>

 

(추가공부 사항) XML, JSON, Pjax, Progressive Web Apps(online + offline)