이렇게 키워드를 검색하면 뉴스 끌고오는 사이트 만들어보자.
활용할 기능은
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')
의 조건으로 제어해주었다.