
이렇게 키워드를 검색하면 뉴스 끌고오는 사이트 만들어보자.
활용할 기능은
JS의 fetch함수와, NewsApi
NewsApi : https://newsapi.org/
우선 https://newsapi.org/ 사이트에 접속해Get API Key로 회원가입, api key를 얻는다.


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());
})
{
"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를 사용하는 기본용법이다.
요청과 응답 등의 요소를 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()` 호출에 의해 파싱됨
});
다 이해안해도됨!!
선택적으로 사용가능한 옵션들이니 필요할 때
찾아서 지정해주면 된다.
fetch(주소)
.then((response) => response.json())
.then((data) => {
console.log('성공:', data);
})
.catch((error) => {
console.error('실패:', error);
});
<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의 자식으로 추가된다.
//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);
}
e.preventDefault();submit 기본 전송 기능 막고etch에서 쓸 url을 이 두개의 변수로 연결해 만들어준다.newsList.innerHTML="";result가 없다는 것은 어떻게 알 수 있을까?

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