기능
- https://openweathermap.org/api API 활용하여 날씨 페이지 구현
- 버튼 클릭시 해당 지역 날씨 표시 기능 구현
- 페이지네이션 기능 구현
- 오류 발견 시 화면단에 오류 내용 출력
- 날씨 온도에 따라 색 변경 기능 구현
- 반응형 홈페이지 구현
사용언어
- HTML
- CSS
- JavaScript
Demo App
API를 활용하여 날씨 페이지 구성하기
해당 API 페이지의 기본적인 날씨 데이터를 받아서 작업을 진행했다.
중심적으로 공부를 하려고 했던 목표는 axios로 API를 활용하는 부분이였다.
01. openweathermap.org/api 사용하기
https://openweathermap.org/current
해당 사이트에서 날씨 데이터를 받기위해 필요한건 회원가입후 생성하는 APIKEY , 원하는 위치의 자리의 좌표가 필요하다고 나온다.
해당 홈페이지는 친절하게도 좌표가 아닌 도시 이름 및 나라 코드 등으로도 검색을 할 수 있었고,
방대한 자료 속 에서 limit를 걸어 필요한 정보만 받을 수 있었다.
02. axios 란?
Ajax와 더불어 백엔드 프론트엔드와의 통신을 쉽게 하기 위에 사용하는 PromiseAPI를 활용하는
HTTP 비동기 통신 라이브러리이다.
fetch api 가 있지만, 굳이 axios 를 사용했던 이유는 , react vue 와 같은 프레임워크 에서
ajax를 구현할때 많이 사용 되기 때문에 바닐라 JS환경에서도 활용했다.
axios를 사용하려면, cdn이나 npm방식으로 파일을 불러와서 적용 시켜줘야한다.
//cdn 방식 (html파일에서)
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
//npm 방식 (터미널에서)
npm install axios
- 자세한 정보는 https://www.npmjs.com/package/axios 참조
API 통신하기
API로 불러온 데이터가 여러 부분으로 계속해서 사용 되기 때문에,
axios에서 async/await를 사용할 수 있는 방법을 사용하여 데이터를 받아 왔다.
const getData = async () => {
try {
const response = await axios.get(`${URL}`);
console.log(response);
} catch (error) {
console.error(error);
}
}
03. 리스트 불러오기
해당 기능구현에서의 가장 고민이었던 부분이 도시를 어떤식으로 다 불러와야 할까였다.
대량의 전세계 정보가 들어있는 JSON 파일
http://bulk.openweathermap.org/sample/
대량의 리스트에서 map핑을 통해 data 정보를 확인해봤더니
너무 너무 너무 방대한 정보들이 딸려오기에 필요한 정보만 추출하기 위해서
if문으로 노가다를 돌려, 정보를 받아왔다.
let data2 = response2.data;
data2.map((i)=>{
if(i.country == 'KR'){
console.log(i)
}
})
country 정보에서 KR로 된 API 데이터들을 if문으로 걸러서 추출을 했다.
04. 날짜 불러오기 (render)
받아온 데이터를 HTML 화면에 출력을 해주기 위해 render 라는 함수를 만들어
화면으로 보여질 부분들에 대한 부분을 다 넣어줬다.
const render = () => {
try {
let list = FilterList;
let createHTML = "";
createHTML = list.slice(((page-1) * limit), ((page-1) * limit) + limit).map((list, i) => {
let description = list.weather[0].description;
return `<article class="weather_item rounded drop-shadow overflow-hidden
${((list.main.temp - 273.15).toFixed(1) >= 20) ? "hot" : ((list.main.temp - 273.15).toFixed(1) <= 5) ? "cool" : 'soso'}">
<div class="main_info flex" >
<div class="weather_icon"><i class="fa-solid "></i></div>
<div class="weather_info flex gap-2">
<div class="flex centers gap-2"><i class="fa-solid fa-temperature-half"></i> <span>${(list.main.temp - 273.15).toFixed(1)}℃</span></div>
<p>${description}</p>
<p class="weatherCity"> ${list.name} , ${list.sys.country == "KR" ? "한국" : list.sys.country}</p>
</div>
</div>
<ul class="sub_info centers flex mx-auto p-5 bg-white">
<li><i class="fa-solid fa-temperature-arrow-up"><span>${(list.main.temp_max - 273.15).toFixed(1)}℃</span></i></li>
<li><i class="fa-solid fa-temperature-arrow-down"><span>${(list.main.temp_min - 273.15).toFixed(1)}℃</span></i></li>
</ul>
</article>
`
}).join('');
document.querySelector('.weather').innerHTML = createHTML;
changeWeatherIcon();
} catch (error) {
console.log(error.message);
errorRender(error.message)
}
}
05.날씨 아이콘 변경
api 자체에서도 icon이 있었지만 해당 icon들이 맘에 들지 않아서
fontawesome에서 아이콘을 가지고 와 사용하였다.
날씨들 정보에 따라서, 아이콘이 바뀌어야 하는데, fontawesome은 class로 아이콘들이 바뀌기때문에 if문으로 description 데이터 값에 따라서 class값을 바꿔주었다.
/* 날씨 아이콘 변경 */
const changeWeatherIcon = () => {
let list = FilterList;
let weather_icon = document.querySelectorAll('.weather_icon i');
weather_icon.forEach((icon, v) => {
for (let i = 0; i < list[v].weather.length; i++) {
let description = list[v].weather[i].description;
if (description == 'clear sky') {
icon.classList.add('fa-sun');
} else if (description == 'few clouds') {
icon.classList.add('fa-cloud-sun');
} else if (description.includes('clouds') || !(description == 'few clouds')) {
icon.classList.add('fa-cloud');
} else if (description.includes('rain')) {
icon.classList.add('fa-cloud-rain');
} else if (description == 'thunderstorm') {
icon.classList.add('fa-cloud-bolt');
} else if (description == 'snow') {
icon.classList.add('fa-snowflake');
} else if (description == 'mist') {
icon.classList.add('fa-water');
}
}
});
}
06. 버튼 클릭에 따라 날짜 나타나기
버튼 클릭에 따라 해당 지역의 현재온도를 가지고와 출력해줬다.
온도에 따라 글씨의 색상을 바꿔주어 더운지 추운지 괜찮은지를 표시해주었고,
API에서 받아오는 온도 정보는 화씨온도이기에 (화씨온도 - 273.15).toFixed(1) 를 하여 섭씨 온도로 변환해 출력해줘야 한다.
/* 버튼 */
const menuButton = async (event) => {
let CityName = CityArr;
let thisButton = event.target;
let ThisTemp = FilterList.map((v,i) => {
return thisButton.innerText == CityName[i].name ? (v.main.temp - 273.15).toFixed(1) : ""
}).join('');
document.querySelector('.weather_text').innerHTML =
` 오늘 ${thisButton.innerText}의 온도는?
<span class="font-bold ${ThisTemp >= 20 ? "text-red-400" : ThisTemp <= 5 ? "text-blue-700" : 'text-green-600' }">${ThisTemp}</span>
℃ 입니다. `
}
07. 페이지네이션 구현하기
JS로 페이지네이션 구현하려고 할때, 사용되는 공식이 있다.
totalPage = Math.ceil(데이터 전체 갯수 / 화면에 보일 페이지 갯수)
pageGroup = Math.ceil(현재페이지 / 화면에 보일 페이지 갯수)
last = pageGroup * 화면에 보일 페이지 갯수
first = last - (화면에 보일 페이지 갯수 -1)
로 값을 구할 수 있다.
/* pagelation */
const pagelation = () => {
let pageNationHTML = "";
let totalPage = Math.ceil(totalCount / pageCount) // 총 페이지네이션 / 한 페이지에 보여줄 글의 최대 갯수
let pageGroup = Math.ceil(page / pageCount) // 현재 페이지 / 보여질 페이지네이션 수
let last = pageGroup * pageCount; // 마지막 페이지
if (last > totalPage) {
// 마지막 그룹이 5개 이하이면
last = totalPage;
}
let first = last - (pageCount - 1); // 첫번째 페이지
pageNationHTML = page == 1 ? "" : `<li class=" bg-indigo-500 shadow-lg py-1 px-4 py-2 rounded hover:bg-white hover:text-indigo-500" onClick="moveTo(${page-1})"><</li>`
for (let i = first; i <= last; i++) {
pageNationHTML += `
<li class="${page == i ? 'active' : ""} bg-indigo-500 shadow-lg py-1 px-4 -2 py-2 rounded hover:bg-white hover:text-indigo-500" onClick="moveTo(${i})">${i}</li>
`
}
pageNationHTML += page == totalPage ? "" : page >= 1 ? `<li class=" bg-indigo-500 shadow-lg py-1 px-4 py-2 rounded hover:bg-white hover:text-indigo-500" onClick="moveTo(${page+1})">></li>` : ""
document.querySelector('.pagination').innerHTML = pageNationHTML;
}
07-1. 페이지네이션 구현에 대한 문제점
페이지네이션 구현을 할때 시간이 가장 오래 걸렸는데, 그 이유는
페이지네이션은 작동하지만 화면이 페이지 별로 변경되지 않았다.
받아오던 데이터를 render 화면에서 map으로 보여줄때에도 10개면 10개 5개면 5개를 전체적으로 데이터를 다 읽어오기때문에, 결국 화면에 출력이 되는건 끝에서 보여지게 했던 3개 뿐이였다.
그래서 이 부분을 해결하기 위해서
list.slice(((page-1) * limit), ((page-1) * limit) + limit).map((list) => {
map을 사용할때, 동적으로 현재 페이지 에서 부터 한번에 보여질 데이터의 값 만큼만 map으로 출력을 하게 되면 현재 페이지의 숫자 값에 따라 다른 인덱스 번호의 정보를 출력해주기때문에,
동적으로 페이지네이션 값에 따라 정보가 변하도록 만들 수 있었다.
'STUDY > JavaScript' 카테고리의 다른 글
[JavaScript] 상수(const) (0) | 2022.11.27 |
---|---|
[JavaScript] 변수(let , var) (0) | 2022.11.27 |
[JavaScript] JS 사용하기 (0) | 2022.11.27 |
[JavaScript] JS 알아보기 (0) | 2022.11.27 |
[Study] API를 활용하여 뉴스페이지 구성하기 (0) | 2022.11.26 |
댓글