JS) Fetch함수와 NewsApi 사용하기

oching·2022년 5월 19일
0

JavaScript

목록 보기
11/11
post-thumbnail

이렇게 키워드를 검색하면 뉴스 끌고오는 사이트 만들어보자.
활용할 기능은
JS의 fetch함수와, NewsApi
NewsApi : https://newsapi.org/


NewsApi 사용법

1. api key를 얻는다.

우선 https://newsapi.org/ 사이트에 접속해Get API Key로 회원가입, api key를 얻는다.

2. Get started 기본 용법 체크.

GET https://newsapi.org/v2/everything?q=Apple&from=2022-05-19&sortBy=popularity&apiKey=API_KEY
  • Definition
    ?q=Apple&from=2022-05-19&sortBy=popularity
    GET방식을 통해 주소를 불러온다.
    여기서 q=이후의 키워드가 우리가 검색하려는 검색 키워드가 온다는 것과
    apiKey=API_KEY부분에는 우리가 좀 전에 발급받은 api key를 넣어줘야한다는 것을 알 수 있다.

  • Example request _ JS 이 방식으로 요청하면

var url = 'https://newsapi.org/v2/everything?' +
          'q=Apple&' +
          'from=2022-05-19&' +
          'sortBy=popularity&' +
          'apiKey=2721d1f0de38415b978ddeed5ff2291a';

var req = new Request(url);

fetch(req)
    .then(function(response) {
        console.log(response.json());
    })
  • Example response 이런 객체형태로 값을 불러다 줄게
{
"status": "ok",
"totalResults": 186,
-"articles": [
-{
-"source": {
"id": "reuters",
"name": "Reuters"
},
"author": null,
"title": "Taiwan firms resuming production in China as COVID curbs ease -minister - Reuters",
"description": "Roughly half of Taiwanese companies that had previously suspended work in China due to COVID-19 control measures have resumed production as curbs ease, the island's economy minister said on Thursday.",
"url": "https://www.reuters.com/world/asia-pacific/taiwan-firms-resuming-production-china-covid-curbs-ease-minister-2022-05-19/",
"urlToImage": "https://www.reuters.com/resizer/R1IxOrQHSXQzR451lMrTcSvQDz8=/1200x628/smart/filters:quality(80)/cloudfront-us-east-2.images.arcpublishing.com/reuters/4URHC4KVEFM25HYLDCIDXT72HY.jpg",
"publishedAt": "2022-05-19T04:10:00Z",
"content": "Tourist electric cars are park in front of an Apple store at a main shopping area, during lockdown, amid the coronavirus disease (COVID-19) outbreak, in Shanghai, China, May 18, 2022. REUTERS/Aly Son… [+1200 chars]"
},

url 변수를 하나 생성해 Definition에 올 코드를 넣고,
이로 하나의 객체를 생성한다.
그리고 이렇게 만들어진 객체를 fetch함수에 넣어 json형태로 뿌려준다.
이것이 NewsApi를 사용하는 기본용법이다.


Fetch함수

요청과 응답 등의 요소를 JavaScript에서 접근하고 조작할 수 있는 인터페이스를 제공함. Fetch API의 네트워크의 리소스를 쉽게 비동기적으로 가져올 수 있음. 이전에는 이런 기능을 XMLHttpRequest를 사용해 할 수 있었으나 fetch가 나오면서 좀 더 쉽게 사용가능해짐.

기본 요청법

let 주소 = 'http://example.com/movies.json';
fetch(주소)
  .then((response) => response.json())
  .then((data) => console.log(data));

주소를 담아 fetch로 부름.
.then 주소에서 가져온 내용은 response인자에 담고 response.json()에 의해 json형태를 반환하는 콜백함수실행.
.then그 json형태를 다시 받아 data로 받아 console.log()하는 콜백함수 실행.

요청시 옵션 설정도 가능

두번째 인자로 옵션을 지정해 받아올 수도 있다.

// POST 메서드 구현 예제
async function postData(url = '', data = {}) {
  // 옵션 기본 값은 *로 강조
  const response = await fetch(url, {
    method: 'POST', // *GET, POST, PUT, DELETE 등
    mode: 'cors', // no-cors, *cors, same-origin
    cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'same-origin', // include, *same-origin, omit
    headers: {
      'Content-Type': 'application/json',
      // 'Content-Type': 'application/x-www-form-urlencoded',
    },
    redirect: 'follow', // manual, *follow, error
    referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
    body: JSON.stringify(data), // body의 데이터 유형은 반드시 "Content-Type" 헤더와 일치해야 함
  });
  return response.json(); // JSON 응답을 네이티브 JavaScript 객체로 파싱
}

postData('https://example.com/answer', { answer: 42 }).then((data) => {
  console.log(data); // JSON 데이터가 `data.json()` 호출에 의해 파싱됨
});

다 이해안해도됨!!
선택적으로 사용가능한 옵션들이니 필요할 때
찾아서 지정해주면 된다.

잘 가져올때 .then, 에러날 땐 .catch

fetch(주소)
.then((response) => response.json())
.then((data) => {
  console.log('성공:', data);
})
.catch((error) => {
  console.error('실패:', error);
});

그럼 한번 사용해봅시다!

html 중 주요 마크업

<main>
  <!-- 검색 영역 -->
  <section class="search-section">
    <form class="search-form" action="">
      <input type="text" class="search-input" placeholder="">
      <input type="submit" class="search-btn" value="검색">
    </form>
  </section>
  <!-- 뉴스 영역 -->
  <section class="news-section">
    <ul class="news-lists"></ul>
  </section>
</main>

search-input이라는 input에 특정 검색어를 입력하면,
newsapi에서 해당 키워드를 갖는 기사를 끌고올 예정.
끌고 온 기사는 news-lists의 자식으로 추가된다.

JS

//DOM 구조 생성
const searchForm = document.querySelector('.search-form');
const searchInput = document.querySelector('.search-input');
const newsList = document.querySelector('.news-lists');

//form 검색 인식하면 이벤트 실행
searchForm.addEventListener('submit', retrieve);
function retrieve(e){
    //form submit 기본 전송기능(action) 막기
    e.preventDefault();

    let topic = searchInput.value;
    const apiKey = "2721d1f0de38415b978ddeed5ff2291a";
    let url=`https://newsapi.org/v2/everything?q=${topic}&apiKey=${apiKey}`;
    
    //검색내용 없을 때는 alert창 띄우기
    if(topic == ""){
        alert('먼저 검색어를 입력해주시죨.');
        return;
    }

    //news-list의 내용값 비우기(기존 검색된 li 모두 제거)
    newsList.innerHTML="";

    //newsApi에서 가져온 정보로 DOM에 출력
    fetch(url).then((res)=>{
        return res.json()
    }).then((data)=>{
        console.log(data);
        data.articles.forEach(article=>{
            /* 각 뉴스 */
            //li.news
            let li = document.createElement('li');
            li.className = "news";
            //li.news>a
            let a = document.createElement('a');
            a.setAttribute('href',article.url);
            a.setAttribute('target','_blank');
            // a.textContent=article.title;

            /* 뉴스 썸네일 */
            //div.news-thumbnail
            let thumbnail = document.createElement('div');
            thumbnail.className = "news-thumbnail";
            //div.news-thumbnail>img
            let thumbnailImg = document.createElement('img');
            thumbnailImg.setAttribute('src', article.urlToImage)

            /* 뉴스 내용 */
            //div.news-contents
            let contents = document.createElement('div');
            contents.className = "news-contents";

            /* 뉴슥 내용 - 작가 , 날짜 */
            //div.news-info
            let newsInfo = document.createElement('div');
            newsInfo.className = "news-info";
            //span.news-author 작가
            let author = document.createElement('span');
            author.className = "news-author";
            author.textContent=article.author;
            //span.news-date 날짜
            let date = document.createElement('span');
            date.className = "news-date";
            date.textContent=article.publishedAt;

            /* 뉴슥 내용 - 제목 */
            //div.news-title
            let title = document.createElement('p');
            title.className = "news-title";
            title.textContent=article.title;

            /* 뉴슥 내용 - 설명글 */
            //div.news-description
            let description = document.createElement('p');
            description.className = "news-description";
            description.textContent=article.description;

            //만든 DOM요소들 부모에 넣기
            newsList.appendChild(li);
            li.appendChild(a);

            a.appendChild(thumbnail);
            thumbnail.append(thumbnailImg);

            a.appendChild(contents);
            contents.appendChild(newsInfo);
            newsInfo.appendChild(author);
            newsInfo.appendChild(date);
            contents.appendChild(title);
            contents.appendChild(description);
        })

        //관련 뉴스 없을 때 
        let totalResults = data.totalResults;
        console.log(totalResults);
        if(totalResults == '0'){
            console.log('없');
            let noResullt = document.createElement('strong');
            noResullt.className = "noResult";
            noResullt.textContent="아이쿠 아무런 기사가 없네요ㅠㅠ";
            newsList.appendChild(noResullt);
        }
    }).catch((error)=>{console.log('error')});
    
    console.log(topic);
  
}

걍 이거만 봐도 됨

//DOM 구조 생성
const searchForm = document.querySelector('.search-form');
const searchInput = document.querySelector('.search-input');
const newsList = document.querySelector('.news-lists');

//form 검색 인식하면 이벤트 실행
searchForm.addEventListener('submit', retrieve);

function retrieve(e){
    //form submit 기본 전송기능(action) 막기
    e.preventDefault();

    let topic = searchInput.value;
    const apiKey = "2721d1f0de38415b978ddeed5ff2291a";
    let url=`https://newsapi.org/v2/everything?q=${topic}&apiKey=${apiKey}`;
    
    //검색내용 없을 때는 alert창 띄우기
    if(topic == ""){
        alert('먼저 검색어를 입력해주시죨.');
        return;
    }

    //news-list의 내용값 비우기(기존 검색된 li 모두 제거)
    newsList.innerHTML="";

    //newsApi에서 가져온 정보로 DOM에 출력
    fetch(url).then((res)=>{
        return res.json()
    }).then((data)=>{
        console.log(data);
        data.articles.forEach(article=>{
       		//html요소들 추가하고 부모요소에 껴주는 구문
        })

        //관련 뉴스 없을 때 
        let totalResults = data.totalResults;
        console.log(totalResults);
        if(totalResults == '0'){
            console.log('없');
            let noResullt = document.createElement('strong');
            noResullt.className = "noResult";
            noResullt.textContent="아이쿠 아무런 기사가 없네요ㅠㅠ";
            newsList.appendChild(noResullt);
        }
    }).catch((error)=>{console.log('error')});
    
    console.log(topic);
  
}
  1. 접근해야하는 DOM요소들 예를들면 form, input, ul 애들 부터 변수로 만들고
  2. form에 이벤트 핸들러를 달아, 감지하면 retrieve라는 콜백함수실행.
  3. retrieve함수안에 e라는 현재 이벤트관련 내용 담아
    3.1) e.preventDefault();submit 기본 전송 기능 막고
    3.2) topic과 apikey 각각 변수로 지정. fetch에서 쓸 url을 이 두개의 변수로 연결해 만들어준다.
    3.3) topic이 없을 경우, 즉 사용자가 아무런 키워드를 넣지않고 검색을 눌렀을 때에는 if문으로 제어한 뒤 '먼저 검색어를 입력해주시죨.'이라는 alert창 띄움
    3.4) 이제 fetch로 정보 가져와 뿌려주기 전에 ul내의 요소들을 모두 지워서 초기화한다. newsList.innerHTML="";
    3.5) topic이 인식 됨, fetch함수에 전달해 값을 받아오고
    dom 구조를 생성하고 append해서 출력해준다.
    근데 만약, 값이 유의미하지않으면 즉 result가 없으면 '아이쿠 아무런 기사가 없네요ㅠㅠ'라는 dom을 출력해준다.

result가 없다는 것은 어떻게 알 수 있을까?

fetch에서 가공된 data를 보면 totalResult라는 총 관련 news의 개수를 출력해준다. 이를 활용해
let totalResults = data.totalResults;로 접근
if(totalResults == '0')의 조건으로 제어해주었다.


profile
FE Studying

0개의 댓글

관련 채용 정보