
• 동기
-작업(task)들이 순차적으로 이루어 지는 것
-다른 작업들을 blocking
• 비동기
-작업(task)들이 순차적으로 이루어지지 않음
-다른 작업들은 non-blocking
-Javascript를 사용한 비동기 통신 방식을 Ajax(Asynchronous Javascript and XML)
-Http요청(GET, POST), 이벤트 핸들러(click, over …), setTimeout, setInterval
Callback
-콜백 함수란 인자로 들어오는 함수를 칭함
-콜백은 비동기 통신을 할 수 있는 한 패턴
-문제점: 콜백 헬로 인한 에러처리 불가, 가독성 hell
Promise
-ES6에서 나온 비동기 패턴
-비동기 통신 결과와 상태를 저장하는 객체
-후속처리 매서드로 then(성공), catch(에러), finally(무조건)가 있다
async/await
-Promise의 복잡성으로 인해 ES8에서 나온 비동기 패턴
-Promise를 기반으로 하며 완전히 같지는 않으나 사용하기 편하다
stateful, stateless
-컴포넌트를 나누는 또 다른 방식
-stateful 컴포넌트 : 모든 state를 들고있는 컴포넌트
-stateless 컴포넌트: state를 안들고 있고 props 와 같이 받은 데이터만 보여주는 컴포넌트
-리액트는 단방향 통신이다 즉 부모에서 자식으로만 데이터를 전달 할 수 있다
이를통해 데이터 흐름을 추적하기는 더 쉽지만, 같은 형제끼리 데이터를 주고받기는 힘들다. 그래서 데이터는 주로 부모가 들고있고 자식에게 전달해주는 형식이 된다. state를 들고있는 부모 컴포넌트는 stateful 컴포넌트, 부모가주는 데이터만 받는 컴포넌트를 stateless 컴포넌트라고 한다
-이렇게 컴포넌트를 구성하면 장점은 state가 없는 stateless컴포넌트는 재사용이 쉽고 데이터를 걱정하지 않아도 된다
-모든 중요한 데이터들은 stateful컴포넌트에 있기 때문에 유지보수가 쉽다 (stateful컴포넌트 하나만 주시하고 관리해주면 되니까)
-그래서 최대한 모든 컴포넌트를 stateless로 만들고 몇개의 stateful컴포넌트에서 데이터를 관리하는 구조가 이상적이라고 리액트는 말하고 있다
App.js
import React, { useState, useEffect } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import { Container } from 'react-bootstrap';
import WeatherButton from './components/WeatherButton';
import WeatherBox from './components/WeatherBox';
import { ClipLoader } from 'react-spinners';
const API_KEY = 'ecfc1cc396fcde85c6e3516f792af3e1';
const cities = ['paris', 'new york', 'tokyo', 'seoul'];
const App = () => {
const [loading, setLoading] = useState(false);
const [city, setCity] = useState(null);
const [weather, setWeather] = useState(null);
const [apiError, setAPIError] = useState('');
const getWeatherByCurrentLocation = async (lat, lon) => {
try {
let url =
`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}`;
// `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}`;
//'http://api.openweathermap.org/data/2.5/weather?lat=35.87222&lon=128.60250&appid=ecfc1cc396fcde85c6e3516f792af3e1';
const res = await fetch(url);
const data = await res.json();
setWeather(data);
setLoading(false);
} catch (err) {
setAPIError(err.message);
setLoading(false);
}
};
const getCurrentLocation = () => {
navigator.geolocation.getCurrentPosition((position) => {
const { latitude, longitude } = position.coords;
getWeatherByCurrentLocation(latitude, longitude);
//console.log('현재위치?', latitude, longitude);
});
};
const getWeatherByCity = async () => {
try {
let url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}`;
const res = await fetch(url);
const data = await res.json();
setWeather(data);
setLoading(false);
} catch (err) {
console.log(err);
setAPIError(err.message);
setLoading(false);
}
};
useEffect(() => {
if (city == null) {
setLoading(true);
getCurrentLocation();
} else {
setLoading(true);
getWeatherByCity();
}
}, [city]);
const handleCityChange = (city) => {
if (city === 'current') {
setCity(null);
} else {
setCity(city);
}
};
return (
<Container className="vh-100">
{loading ? (
<div className="w-100 vh-100 d-flex justify-content-center align-items-center">
<ClipLoader color="#f86c6b" size={150} loading={loading} />
</div>
) : !apiError ? (
<div class="main-container">
<WeatherBox weather={weather} />
<WeatherButton
cities={cities}
handleCityChange={handleCityChange}
selectedCity={city}
/>
</div>
) : (
apiError
)}
</Container>
);
};
export default App;
import React from 'react';
import { Card } from 'react-bootstrap';
const WeatherBox = ({ weather }) => {
const temperatureC =
weather && weather.main ? (weather.main.temp - 273.15).toFixed(2) : '';
const temperatureF =
weather && weather.main
? (((weather.main.temp - 273.15) * 9) / 5 + 32).toFixed(2)
: '';
return (
<Card className="weather-card">
<Card.ImgOverlay className="d-flex flex-column justify-content-center text-center">
<Card.Title>{weather?.name}</Card.Title>
<Card.Text className="text-success h1">
{`${temperatureC} °C / ${temperatureF} °F`}
</Card.Text>
<Card.Text className="text-info text-uppercase h2">
{weather && weather.weather[0]?.description}
</Card.Text>
</Card.ImgOverlay>
</Card>
);
};
export default WeatherBox;
import React from 'react';
import { Button } from 'react-bootstrap';
const WeatherButton = ({ cities, selectedCity, handleCityChange }) => {
return (
<div class="menu-container">
<Button
variant={`${selectedCity === null ? 'outline-warning' : 'warning'}`}
onClick={() => handleCityChange('current')}
>
Current Location
</Button>
{cities.map((city) => (
<Button
variant={`${selectedCity === city ? 'outline-warning' : 'warning'}`}
onClick={() => handleCityChange(city)}
>
{city}
</Button>
))}
</div>
);
};
export default WeatherButton;
import React from 'react';
import { Navbar, Nav } from 'react-bootstrap';
const PublicNavbar = () => {
return (
<Navbar bg="light" expand="lg" className="position-fixed navbar-fixed">
<Navbar.Brand></Navbar.Brand>
<Nav className="mr-auto"></Nav>
<Nav>
<a
href="https://github.com/dhminh1024/cs_weather_app"
target="_blank"
rel="noreferrer"
></a>
</Nav>
</Navbar>
);
};
export default PublicNavbar;
body{
background: url(https://images.unsplash.com/photo-1522441815192-d9f04eb0615c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2127&q=80);
height: 100vh;
background-repeat: no-repeat;
background-size: cover;
}
.weather-card{
background-color: rgba(52,52,52,.2);
padding: 50px;
border: 2px solid #fff;
border-radius: 20px;
max-width: 700px;
width:100%;
height: 300px;
}
.main-container{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.menu-container{
display: flex;
justify-content: center;
background-color: #000;
border-radius: 60px;
max-width: 700px;
width:100%;
padding: 30px;
margin-top: 30px;
}
.menu-container Button{
margin-right:30px;
}
.menu-container Button:hover{
background-color: #ffc107;
}
처음엔 같이 작성을 해보다가 문법적인 부분이 많아지고 여기 저기 코딩을 넣고 빼고 하다보니 따라가기가 정말 어려웠던 것 같다. 그러다보니 이 후엔 만들어 놓으신 코드들을 받아서 작동 원리들을 보고 자기 환경에 맞게 구동할 수 있게 바꾸는 것을 했는데 그 조차도 쉽지 않았다.
최근에 가장 유용하게 사용되는 리액트에 대해서 문법적인 부분을 많이 찾아보고 할 수 있어야겠다. 문법적인 부분이 어려운 만큼 많이 사용해봐야겠다. 간단한 앱이라도 문법적인 부분에서 거의 다 막히는만큼 예제들을 찾아봐야겠다.
파이썬이나 리액트, 파이스크립트 등 많은 기술들이 나오고 바뀌는만큼 기본적으로 접근할 수 있는 바탕을 최대한 깔아놓을 수 있게 할 수 있는 부분은 최대한 해봐야겠다.