본문 바로가기
Project/Toy Project

날씨 APP 만들기 (OpenWeather API 활용)

by joooing 2021. 1. 5.
반응형

HTML, CSS, Javascript와 OpenWeather API 이용해 날씨 APP을 만들어 보았다. 앱에 대해 먼저 소개를 해보자면, 사용자가 검색창에 도시명을 입력하면 해당 도시의 온도, 습도, 풍속 등의 날씨 정보와 현재날짜를 아이콘, 사진과 함께 알려주는 앱이다.

 

OpenWeather API는 날씨와 관련된 정보를 제공하는 API인데, fetch를 이용해 서버 요청을 하는 방식으로 데이터를 받아와 활용했다. 이번에도 HTML & CSS의 디자인적인 부분과 Javascript 부분으로 나누어 새로 알게 되었거나 중요한 부분들에 대해서만 간략히 소개해보려고 한다.

 

최종 완성본 


와이어프레임

 

1. HTML & CSS


✔️ input placeholder 색상 변경

검색창 부분을 input 태그로 만들어줬는데, placeholder로 'search'라는 문자열을 설정해 기본적인 텍스트로 뜨게 만들었다. 그런데 원래 색상이 어두워보여서 CSS에서 ::placeholder 선택자를 이용해 placeholder에 들어가는 텍스트 색상도 따로 지정해줬다.

<input id="search" placeholder="search"></input>
#search::placeholder {
  color : #eee;
}

 

 

✔️ 검색 아이콘에 transition 적용

이 부분도 정말 자세히 봐야 보이지만 검색 아이콘에 마우스를 대면 아이콘이 조금 커지도록 효과를 적용해봤다. 먼저 transition이라는 속성에 서서히 변화하길 원하는 속성이름과 변화가 진행될 시간을 값으로 지정해주고, 마우스를 올렸을 때를 의미하는 :hover 부분에 변화 후의 속성을 값으로 지정해주면 된다.

#search-icon {
    transition: font-size 0.3s;
}

#search-icon:hover {
    font-size: 17px;
}

 

 

✔️ 자간 설정

폰트 크기가 커질수록 글자 사이 간격도 넓어지는 것 같아 자간을 줄이는 설정을 추가해줬다. letter-spacing 속성 값을 음수로 설정해주면 간단히 해결할 수 있다!

#temp {
    font-size: 80px;
    letter-spacing: -7px;
}

 

 

✔️ datalist

사실 이 기능은 앱을 만들면서 계속 여러 도시 이름들을 번갈아 입력하며 날씨에 따라 사진이나 아이콘이 다르게 뜨는지 확인하는 과정이 귀찮아서.. 그냥 마우스로 선택하는 기능은 없나? 하고 찾아보다 알게되었다. HTML에서 해당 input태그에 list="list명" 속성을 추가해주고, 그 다음에 datalist태그를 만들고 id를 방금 전에 만든 input태그의 list명으로 설정해주면 된다. 그리고 datalist태그 안에 저장해두고자 하는 옵션들을 option태그로 쭉 작성해주면 된다. 아래 코드와 사진을 보면 쉽게 이해할 수 있을 것이다.

<input id="search" placeholder="search" list="city"></input>
      <datalist id="city">
        <option value="korea"></option>
        <option value="japan"></option>
        <option value="china"></option>
        <option value="london"></option>
        <option value="europe"></option>
      </datalist>

 

 

2. Javascript


✔️ fetch 함수로 날씨 데이터 받아오기

openweathermap.org 사이트에 접속해 회원가입을 하면 url과 API key를 발급해준다. 이 두가지를 이용하면 아래처럼 날씨 데이터에 접근할 수 있다. 중간에 ?q= 부분에는 도시명을 값으로 넣어주면 해당 도시의 날씨 정보를 얻어올 수 있다. ?id= 를 이용하면 도시의 id를 통해 정보를 얻어올 수도 있다. 이번에는 도시명 검색을 통해 데이터를 얻어오는 앱을 만드려고 했기 때문에 ?q= 형식을 사용했다.

 

브라우저에 API키를 포함한 URL을 입력한 모습

 

그리고 서버로 요청(request)을 보내고 응답(response)을 받을 수 있게 도와주는 메서드인 fetch() 를 사용해 데이터를 요청하고 받아왔다. fetch는 Promise<Response>를 반환하는데 콘솔창에 입력해보면 알겠지만(아래사진 참고), 이 상태로는 바로 데이터를 사용할 수가 없다. 이 중 Response를 꺼내고, 서버에서 주는 json데이터를 쓸 수 있게 해주는 json()메서드를 이용해 사용 가능한 데이터 형태로 만들어준다. 여기서 then()은 통신에 성공하는 경우에 콜백함수를 실행시켜주는 역할을 한다. 이렇게 getData() 함수를 통해 데이터를 서버로 부터 받아오고, 받아온 데이터를 renderWeatherData()라는 함수에 넘겨줌으로써 날씨 데이터를 활용할 수 있었다.

 

(왼) Promise<Response>의 모습  ->  (오) json()을 적용한 모습     

let API_URL_OpenWeatherMap = `http://api.openweathermap.org/data/2.5/weather?q=seoul&appid=${API_KEY}`;

function getData() {
  fetch(API_URL_OpenWeatherMap)     	// Promise<Response>반환  -> res로 전달
  .then(function(res) {       
    return res.json()			// json() 메서드 적용  -> json으로 전달
  })
  .then(function(json) {
    renderWeatherData(json);		// json형태의 데이터를 다른함수로 넘겨줌
  });
}

function renderWeatherData(data) {
  let now = new Date(); 
  date.textContent = `${moment(now).format(`dddd, Do MM YYYY`)}`;
  temp.textContent = `${Math.round(Number(data.main.temp) - 273.15)}°C`;
  // ...생략
  changeIcon(data);  
}

 

 

✔️ 날씨에 따라 아이콘, 배경 변경하기

먼저 CSS에 날씨별로 class를 만들고 각각에 다른 배경이미지를 지정해두었다. 배경 이미지는 unsplash라는 사이트에서 url을 통해 가져왔고, 아이콘은 font awesome이라는 사이트에서 가져오는 방식을 사용했다. (이 부분은 지난번 글에 소개해두었다)

 

아이콘이나 이미지 둘 다 특정한 클래스를 지정하기만 하면 리소스를 가져올 수 있기 때문에, 아래처럼 classList.remove와 classList.add만을 사용해 조건에 따라 추가/삭제하는 함수(changeIcon)를 작성했다. 조건문은 가져온 날씨 데이터 중 'Clear', 'Clouds', 'Snow'... 등 날씨에 대한 간략한 설명을 value로 가지는 key가 있어서 이 부분을 이용해 작성했다.

 

추가로, 처음에는 classList.add로 클래스를 계속 추가해주는 식으로만 코드를 작성했었는데, 여러번 검색을 하면 한 태그에만 몇개의 클래스가 추가되어버리는 문제가 있었다. 그래서 이전까지의 모든 클래스를 지우려고 spread operator(...)와 함께 classList.remove를 사용했다.

(왼) CSS,  (오) Javascript

 

 

✔️ 현재 날짜 표시

트위틀러 때도 사용했던 moment.js 라이브러리를 이용해 현재 시간을 표시했다. 아래와 같이 HTML에서 import를하고, Javascript에서 Date()로 현재시간을 가져오도록 한 후 moment js의 format() 메서드를 사용해 형식을 지정해주었다. moment.js 홈페이지에 다양한 형식들이 있어서 필요에 따라 참고하면 좋을 것 같다.

 

 <script src="https://momentjs.com/downloads/moment-with-locales.js"></script>

 

  let now = new Date(); 
  date.textContent = `${moment(now).format(`dddd, Do MM YYYY`)}`

 

 

✔️ 키보드로 입력받기

이 부분도 전에 계산기를 만들 때 알게 되었던 addEventListener의 'keydown'이벤트를 활용해 구현했다. keyCode 중 13은 엔터를 의미하고(각 키의 keyCode는 여기서 확인 가능하다), 입력창 중 input태그(여기서는 search라고 지정)에 엔터를 누르는 이벤트가 발생했을 때 데이터를 받아오고, 출력하는 함수들을 실행시키도록 했다.

 

search.addEventListener('keydown', function(e){
    if(e.keyCode === 13) {
      // 함수실행
    }
}

 


다른 부분들은 트위틀러나 회원가입 페이지를 만들 때 썼던 방식을 조금씩 응용해서 구현할 수 있었는데, 서버로부터 데이터를 받아와 활용하는 건 처음이라 재밌기도 하고 새로운 개념들도 많이 접하게 된 것 같다. API를 활용할 줄 알게 됨으로써 내가 할 수 있는 일의 범위도 훨씬 넓어진 듯한 느낌도 든다 😀 새로 알게된 fetch, Promise나 서버와 클라이언트, JSON에 대해서는 좀 더 확실히 이해하도록 더 알아봐야겠다. 

반응형

댓글