티스토리 뷰

 

 

 


목차

 

1. 무한 스크롤이란?

2. 구현 방식

3. 자바스크립트 fetch API

4. async / await

5. 구현 과정

6. 전체 코드


 

 

 

1. 무한 스크롤이란?


컨텐츠를 페이징하는 기법 중 하나로 스크롤을 이용해 맨 아래까지 도달할 때 새로운 컨텐츠를 불러오는 방식을 말한다.

 

 

2. 구현 방식


스크롤을 끝까지 내렸을 때 fetch된 새로운 데이터를 엘리먼트에 계속 추가(append)하는 방식으로 구현했다.

 

 

 

3. 자바스크립트 fetch API


자바스크립트에서는 fetch로 리소스를 비동기 요청을 할 수 있다. 주로 API를 호출하고 응답 데이터를 받아오는 데에 주로 사용한다.

 

fetch("https://jsonplaceholder.typicode.com/posts")
.then(function(res){
  return res.json();
})
.then(function(json){
  console.log(json);
});
  • fetch 에는 기본적으로 첫 번째 인자에 요청할 url이 들어간다. default로 http 메소드 중 GET으로 동작한다.
  • 호출 시 해당 주소에 요청을 보낸 다음, 응답 객체(object Response)를 받는다. 첫 번째 then에서 그 응답을 받고 .json() 메서드로 파싱한 json 값을 리턴한다.
  • 그러면 그 다음 then에서 리턴받은 json 값을 받고, 원하는 처리를 할 수 있다.

 

위 코드를 ES6 문법에서 도입된 화살표 함수로 간소화하면 다음과 같다.

fetch("https://jsonplaceholder.typicode.com/posts")
.then(res => res.json())
.then(json => console.log(json));

 

 

 

4. async / await


async는 function 앞에 위치하며 async 함수는 항상 promise를 반환한다.(아닌 것은 promise로 감싸서 반환)
await는 async 함수 안에서만 동작한다. 또한 await는 promise가 처리될 때까지 기다린다.

 

function getTitle(){
	const response = fetch("https://jsonplaceholder.typicode.com/posts");
    return response.then(res => res.json());
}

async function exec(){
	let text;
    try {
    	text = await getTitle();
        console.log(text[0].title;
    }
    catch(error){
    	console.log(error);
    }
}

exec();

 

위 코드에서 getTitle 함수는 fetch를 통해 호출한 API로 부터 응답 데이터를 받고 JSON으로 파싱 후 리턴하는 부분만 담당한다. 리턴한 데이터를 받아서 처리하는 함수는 exec이다.
따라서 await getTitle() 부분에서 getTitle 함수의 작업 결과값을 얻을 때가지 기다린다.

 

 

 

5. 구현 과정


 

JavaScript

const article = document.querySelector('article');

async function fetchLorem() {
  const response = await fetch("https://baconipsum.com/api/?type=meat-and-filler&paras=18");
  const data = await response.json();

  let addContent = document.createElement("div");
  addContent.innerHTML = `<div class="block"><p> + ${data} + </p></div>`;
    article.append(addContent);
};

fetchLorem();

window.onscroll = function(e) {
  if((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {

    fetchLorem();
  }
}

 

위 코드에서는 먼저 fetch로 api를 받아오고 페이지 전체 높이만큼 스크롤을 다 내리고 나면 요소가 하나 추가되게끔 만들었다. 추가되는 요소는 div 이고 여기에는 box라는 클래스를 지정했다.

 

새로운 콘텐츠를 추가되게 만들기 위해 다음과 같은 피연산자들을 사용했다.

  • window.innerHeight : 브라우저에서 실제로 표시되고 있는 영역의 높이이다. (사용자가 보고 있는 영역의 높이)
  • window.scrollY : 스크롤이 Y축으로 얼마만큼 이동했는지를 의미한다. 맨 처음에 0부터 시작해서 스크롤을 내릴수록 증가하는 값이다.
  • document.body.offsetHeight : offsetHeight는 요소의 실제 높이를 의미한다. 보여지고 있는 영역 외에 가려진 영역까지 더해진 콘텐츠의 실제 높이이다.(사실상 페이지 전체의 높이를 의미)

 

 

그림으로 표현하면 다음과 같다.

 

 

 

 

6. 전체 코드


HTML

<!DOCTYPE html>
<html lang="en">
<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">
    <link rel="stylesheet" href="2.css">
    <title>Document</title>
</head>
<body>
    <header>                
        <h1 class="pageTitle">Infinity scroll</h1>
    </header>
    <article>
        
    </article>
    <script src="app.js"></script>
</body>
</html>

 

CSS

.pageTitle {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 52px;
  line-height: 52px;
  color: #fff;
  text-align: center;
  background: #111;
}

article {
  padding: 52px 3% 0;
}

article .block {
  padding: 20px;
  min-height: 500px;
  background: #999;
}

article .block p {
  line-height: 22px;
  color: #fff;
  font-size: 16px;
  font-weight: 600;
}

 

JavaScript

const article = document.querySelector('article');

async function fetchLorem() {
  const response = await fetch("https://baconipsum.com/api/?type=meat-and-filler&paras=18");
  const data = await response.json();

  let addContent = document.createElement("div");
  addContent.innerHTML = `<div class="block"><p> + ${data} + </p></div>`;
    article.append(addContent);
};

fetchLorem();

window.onscroll = function(e) {
  if((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {

    fetchLorem();
  }
}