function increase(number,callback){
const promise = new Promise(
(resolve,reject) => {
// Promise는 아래 동작을 1초 보장
setTimeout(
() => {
resolve(number);
},1000
);
}
);
return promise;
}
increase(1)
.then(
(result) => {
console.log(result);
//increase 호출시 promise가 온다
return increase(2);
}
).then(
(result) => {
console.log(result);
}
);
// increase(1,(result)=>{
// console.log(result);
// increase(2,(result) => {
// console.log(result);
// increase(3,(result) => {
// console.log(result);
// })
// });
// });
비동기 방식으로 호출할때, 언제 응답이 올지 모르므로 기다리는 것을 보장해야한다.
function increase(number,callback){
const promise = new Promise(
(resolve,reject) => {
// Promise는 아래 동작을 1초 보장
setTimeout(
() => {
resolve(number);
},1000
);
}
);
return promise;
}
async function runTask(){
let result = await increase(1);
console.log(result);
result = await increase(2);
console.log(result);
}
runTask();
https://newsapi.org/s/south-korea-news-api
import React, { useState } from 'react';
import axios from '../node_modules/axios/index';
const App = () => {
const [data,setData] = useState(null);
const onClick = async() => {
const response = await axios.get('https://newsapi.org/v2/top-headlines?country=kr&apiKey=')
setData(response);
};
return (
<div>
<button onClick={onClick}>불러오기</button>
{data && <textarea value={JSON.stringify(data)} /> }
</div>
);
};
export default App;
head 태그 부분을 index.html 파일에 넣기
css는 따로 분리할 필요없다. 번들러가 어차피 마지막에 하나로 합치므로
https://transform.tools/html-to-jsx
html
<div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom box-shadow">
<h5 class="my-0 mr-md-auto font-weight-bold">News API</h5>
<nav class="my-2 my-md-0 mr-md-3">
<a class="p-2 text-dark active" href="#">HOME</a>
<a class="p-2 text-dark" href="#">뉴스</a>
</nav>
</div>
jsx
src 내 컴포넌트 폴더 생성, Header.js, Footer.js, Home.js파일로 분리
import React from 'react';
const Header = () => {
return (
<div className="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom box-shadow">
<h5 className="my-0 mr-md-auto font-weight-bold">News API</h5>
<nav className="my-2 my-md-0 mr-md-3">
<a className="p-2 text-dark active" href="#">
HOME
</a>
<a className="p-2 text-dark" href="#">
뉴스
</a>
</nav>
</div>
);
};
export default Header;
import React from 'react';
const Home = () => {
return (
<section className="jumbotron text-center">
<div className="container">
<h1 className="jumbotron-heading">코드로 전세계 뉴스 검색</h1>
<p className="lead text-muted">
JSON API를 사용하여 웹 전반의 뉴스 소스와 블로그에서 기사와 속보
헤드라인을 찾아보세요.
</p>
<p>
<a href="#" className="btn btn-primary my-2">
메뉴 이동
</a>
</p>
</div>
</section>
);
};
export default Home;
import React from 'react';
import Header from './Header';
import Footer from './Footer';
import Home from './Home';
const Layout = () => {
return (
<>
<Header />
<div className="container">
<main role="main">
<Home />
</main>
<Footer />
</div>
</>
);
};
export default Layout;
app.js에서 Layout 컴포넌트 랜더링
import React from 'react';
import Layout from './components/Layout';
const App = () => {
return (
<Layout />
);
};
export default App;
app.js에 News 컴포넌트 추가, 해당 컴포넌트는 Layout.js의 을 타게된다.
import React from 'react';
import Layout from './components/Layout';
import { Route, Routes } from '../node_modules/react-router-dom/dist/index';
import Home from './components/Home';
import News from './components/News';
const App = () => {
return (
<Routes>
<Route element={<Layout />}>
<Route path='/' element={<Home />} />
<Route path='/news' element={<News />} />
</Route>
</Routes>
);
};
export default App;
import React from 'react';
import NewsList from './NewsList';
const News = () => {
return (
<section>
<ul className="nav nav-tabs">
<li className="nav-item">
<a className="nav-link active" aria-current="page" href="#">
전체보기
</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">
비즈니스
</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">
엔터테인먼트
</a>
</li>
</ul>
<div className="album py-5 bg-light">
<div className="container">
<div className="row">
<NewsList />
</div>
</div>
</div>
</section>
);
};
export default News;
import React from 'react';
const NewsItem = () => {
return (
<div className="col-md-6">
<div className="card mb-4 box-shadow">
<img
className="card-img-top"
src="https://placehold.co/160X80"
alt="Card image cap"
/>
<div className="card-body">
<h4>title</h4>
<p className="card-text">
This is a wider card with supporting text below as a natural
lead-in to additional content. This content is a little bit
longer.
</p>
<div className="d-flex justify-content-between align-items-center">
<div className="btn-group">
<a href="#" className="btn btn-sm btn-outline-secondary">
View
</a>
</div>
<small className="text-muted">NAVER</small>
</div>
</div>
</div>
</div>
);
};
export default NewsItem;
기본 지정 사이즈, 텍스트 포함한 이미지
https://placehold.co/
import React from 'react';
import { NavLink } from '../../node_modules/react-router-dom/dist/index';
const Header = () => {
return (
<div className="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom box-shadow">
<h5 className="my-0 mr-md-auto font-weight-bold">News API</h5>
<nav className="my-2 my-md-0 mr-md-3">
<NavLink className={({isActive}) => (isActive ? "p-2 text-dark active" : "p-2 text-dark")} to="/">
HOME
</NavLink>
<NavLink className={({isActive}) => (isActive ? "p-2 text-dark active" : "p-2 text-dark")} to="/news">
뉴스
</NavLink>
</nav>
</div>
);
};
export default Header;
리액트 파일 빌드
npm run build
nginx 다운로드, c폴더에서 압축해제
https://nginx.org/en/download.html
빌드 경로복사
ngnix.config 루트 경로 수정
서버 실행
nginx.exe
ngnix.config 에 직접 uri 입력시 추가설정
직접 입력시, html 경로를 찾으므로 내부적으로 오류발생
이순서로 페이지에 접근설정($uri => $uri/ => /index.html
)
uri/ : uri의 루트를 찾아라
/index.html : 루트 아래 index.html를 찾아라
web server : apache , 프론트가 주로 관여. 정적리소스
application server(WAS) : tomcat , 백엔드가 주로 관여. 동적리소스
위 개념은 옛날 개념이긴하다. 요즘은 apache tomcat 하나로 묶어 생각하곤 한다.