5.0 Setup
1) installing styled component, router-dom
npm install --save styled-components
npm i react-router-dom@5.3.0
npm i --save-dev @types/react-router-dom
여기서 실습을 하려면 router-dom 을 5.xx버전으로 입력해야 제대로 실행이 된다.
2) Router, separating pages
지금부터 만들 새로운 페이지들은 모두 src폴더 내에 만들 새로운 폴더 routes 에 저장할 것이다.
routes폴더 안에 Coins, Coin이라는 페이지를 만들 것이다.
//Coins.tsx
function Coins(){
return <h1>Coin</h1>
}
export default Coin
//Coin.tsx
function Coin(){
return <h1>Coin</h1>;
}
export default Coin;
보이는 것 처럼 페이지의 구성은 함수 → export로 나뉘어진다.
다음으로는 이 페이지들을 관리하는 파일에 대해 알아보자.
3) Router.tsx
(1) react-router-dom
우선 react-router-dom 에서 세 가지를 import 해준다.
import { BrowserRouter, Switch, Route } from "react-router-dom";
(2) Pages
아까 만들었던 Coins페이지랑, Coin페이지를 import해준다.
import Coin from "./routes/Coin";
import Coins from "./routes/Coins";
(3) return value
function Router(){
return<BrowserRouter>
<Switch>
</Switch>
</BrowserRouter>
}
- 우선 Browser Router를 최외각에 감싸고, 그 안에 switch를 작성한다.
function Router(){
return<BrowserRouter>
<Switch>
<Route path="/:coinId">
<Coin/>
</Route>
<Route path="/">
<Coins/>
</Route>
</Switch>
</BrowserRouter>
}
form:의 형식으로 쓸 것이다. 즉 현재 page라는 글자가 적힌 부분에 내가 만든 페이지들을 작성할 것이다.<Route path=””> <page> <Route/>path=”/”: Home Page라는 뜻이다.path=”/:coinId”- 기본 주소에 /:coinId 붙인 url을 가진 페이지다.
- :coinId : 동적으로 변하는 부분.(앞에 :붙여서) 사용자에게 값을 받아내는 부분이다.
- 여기서 변하는 값은 useParams를 이용하여 Coin페이지 안에서 받을 수 있다.
즉 Routes라는 파일은 url과 만들어둔 페이지를 쌍으로 관리하는 곳이다.
이렇게 받은 Router는 최종 출력을 담당하는 App.tsx에 적용을 해준다.
//App.tsx
import Router from "./Router"
function App() {
return (
<Router/>
);
}
export default App;
지금부터는 동적으로 받은 url을 처리하는 방법에 대해 알아보자.
(4) useParams
import { useParams } from "react-router-dom"
function Coin(){
const {coinId} = useParams();
return <h1>${coinId}Coin</h1>
}
export default Coin
useParams: 훅 중 하나로, 현재 내가 속해있는 페이지 url의 동적변수를 포함하는 객체를 반환한다.const {coinId}=useParams();: coinId라는 값을 받을 것이다.
그런데 Ts를 사용하는 경우 const{coinId} 라고 받으면 → coinId 가 어떤 값인지 알지 못해 문제가 생긴다.
이럴 땐 interface를 만들고 이를 적용해주면 된다 .
interface Params{
coinId: string;
}
function Coin(){
const {coinId} = useParams<Params>();
return <h1>${coinId}Coin</h1>
}
interface Params: useParams를 통해 받을 객체 속 프로퍼티 형식을 작성해준다.<Params>: 이처럼 훅의 () 앞에 형식을 작성해주면 훅에서 발생하는 값을 받는 변수(=coinId)의 형식을 명시할 수 있음
5.1 Styles
지금까지 styled components를 활용할 때는 ‘특정 요소’에만 적용을 했다면, 지금부터는 브라우저 전체에 이를 적용해보고 싶다.
1) GlobalStyle
브라우저 전체의 출력을 담당하는 파일은 app.tsx이니 코드를 수정해보자.
import { createGlobalStyle } from "styled-components";
import Router from "./Router"
const GlobalStyle=createGlobalStyle`
`
function App() {
return <>
<Router/><GlobalStyle/>
</>
}
export default App;
createGlobalStyle: import해준 이후, GlobalStyle이라는 변수에 다른 컴포넌트를 만들었던 것 처럼 생성해준다.<></>= fragment : 두 개의 값을 return하고 싶은데, 그러지 못하는 경우, 유령태그로 묶어서 낸다.
이렇게 작성하면, 브라우저 전체가 styled-component의 영향을 받게 된다.
2) Implementing font
- https://fonts.google.com 에서 원하는 글씨를 찾는다

- get imbeded code를 누른다

- import를 누르고, @뒤에 있는 부분을 복사한다

- 아까 만든 Global style 안에 추가한다.복붙한 링크를 저 안에 적어준다.
body{ font-family:'Source Code Pro', san-serif; }//Source Code Pro를 쓰고, 안되면 san-serif *{ box-sizing: border-box; } a{ text-decoration: none; }//링크에 밑줄 없애는 코드- 이후 global Style안 body에 코드를 추가해준다.
import { createGlobalStyle } from "styled-components"; import Router from "./Router" const GlobalStyle=createGlobalStyle` @import url('https://...'); . . . ` function App() { return <> <Router/><GlobalStyle/> </> } export default App;
즉 폰트를 찾고, 이를 implement하는 방법에 대해 설명하고 있다.
3) Theme
현재까지 배운 내용으로 테마를 적용하려면, 테마 파일을 만들어서, 매번 Theme을 import해와야 한다.
지금부터는 styled-components를 import하면 내가 만들려는 테마의 ‘형식’을 다운받을 수 있도록 코드를 짜보려고 한다.
여기서 짚고 넘어가야 할 부분은 내가 install 한 파일에도 원하는 값을 넣어 커스텀할 수 있다는 것이다.
//styled.d.ts
declare module "styled-componets"{
export interface DefaultTheme{
textColor : string;
bgColor : string;
btnColor :string;
accentColor:string;
}
}
declare module: module을 선언할 것임"styled-componets": styled components를 import한 사람들이 접근 가능한 module을 만들 것임export Interface: DefaultTheme : 디폴트 테마라는 인터페이스 모듈이다.
이런식으로 ‘전체 접근’가능하도록 만든 테마는 어떻게 사용할까?
import { DefaultTheme } from "styled-components";
export const theme:DefaultTheme={
}
이런식으로 ‘형식’을 부여해줄 수 있다. (interface를 export했기 때문에!!)
즉 Theme 단원에서 얻어가야 할 내용은
(…).d.ts: module의 ‘형식’을 선언할 수 있음declare module: 모듈을 선언할 수 있음 → 외부에서도 더 쉽게 접근 가능
4) Sum
이 단원에서는 우선 styled-component를 전체적으로 적용할 수 있는 방법에 대해 설명하고 있다.
이후 이렇게 global 하게 적용된 styled-component로 사용할 수 있는 가장 대표적인 기능인 ‘폰트’를 적용하는 방법에 대해 배웠고
이후 Theme을 전체적으로 적용할 수 있는 방법에 대해 배웠다
따라서 style 강좌에서는 styled component를 일부의 요소에만 적용하는 것에서 더 나아가 global 하게 적용하도록 배웠다. 초기 세팅에서 부터, 글로벌하게 적용할만한 기능까지(=폰트, 테마) 배웠다.
5.2 Home part One
지금부터는 api로 대량의 data를 받아오기 전에 임의로 data를 만들어서 홈페이지에서 리스트가 출력되도록 한 후, 리스트의 각 요소를 누르면 링크를 타고 넘어가도록 코드를 만들어보려고 한다.
1) List of Coins
function Coins() {
return <Container>
<Header>
<Title> 코인 </Title>
</Header>
<CoinList>
<Coin></Coin>
</CoinList>
</Container>
}
export default Coins;
이렇게 만든 CoinList안에 Coin을 여러개 입력해보려고 한다. 그렇다면 CoinList안에 어떤 코드를 입력해야 하는 것인가
현재 세 개의 코인 정보를 coins라는 변수에 배열 형태로 넣어둔 상태다.
<CoinList>
{coins.map(coin=><Coin key={coin.id}>{coin.name}</Coin>)}
</CoinList>
coins.map:coins라는 배열에 map이라는 함수를 달아서, 배열의 요소 하나하나마다 실행하도록 할 것임coin ⇒: coins배열 안의 하나하나의 요소가 coin으로 call back 될 것이다.key={coin.id}: map 의 각 요소는 반드시 key를 가져야 한다. 또한, 이 key의 값은 배열의 요소(=객체)의 프로퍼티인 id값을 이용한다.

이렇게 못생긴 리스트가 만들어지는데, 우선 이 리스트 요소들을 수정해서 각 버튼을 누르면 → 링크를 타고 넘어가는 페이지를 만들어보려고 한다.
2) Following the link
<CoinList>
{coins.map(coin=>
<Coin key={coin.id}>
<Link to={`/${coin.id}`}>{coin.name}</Link>
</Coin>)}
</CoinList>
아까 우린 라우터 파일에서 coinId를 동적으로 받을 것임을 명시하였다.
<Link to={/${coin.id}}>Link to: to 뒤에 있는 링크 타고 갈 것임{/${coin.id}}:따라서/${coin.id}라고 작성하면 coin의 id 프로퍼티에 해당하는 값을 동적으로 받아 따라갈 링크를 만드는 상황임을 알 수 있다.- 아까 router.tsx에서 코인 페이지 링크가 /:coinId 임을 명시했다.
결국 정리하면 동적으로 링크를 설정하는 상황에서는
- 동적으로 링크 설정 (in Router)
- Link to
/{value}라고 하며 따라갈 링크를 생성
3) Mouse Hover Event
지금부터는 마우스를 가져다 올렸을 때 색이 바뀌도록 해보자.
const Coin=styled.li`
&:hover{
a{
color: ${(props)=>props.theme.accentColor};
display: block;
}
}
`
내가 만들었던 Coin 컴포넌트에 이벤트를 추가할 것이다.
&: 지금 현재 대상 (=li)를 가리킨다.:hover: 이벤트 이름원래는 useClick이나, useHover에 변화 함수를 부여하는 방식으로 진행했었는데, styled component를 활용하면 더 간단하게 작성할 수 있다.- 결국 hover라는 이벤트가 발생한 경우 어떤 함수를 실행할지 {} 안에 적고 있다.
5.3 Home part Two
지금까지는 내가 직접 data를 만들어서 이를 출력했다면, 이제부터는 api에서 data를 받아와서 이를 출력해보려고 한다.
1) Setting + form of data
우선 내가 받아올 api의 각 요소를 구성하는 형태를 Ts에 interface 로 설명해주려 한다.
interface CoinInterface{
id: string,
name: string,
symbol: string,
rank: number,
is_new: boolean,
is_active: boolean,
type: string,
}
이후 useState를 활용하여 coins라는 배열과, setCoins라는 함수를 사용해보고자 한다.
const [coins, setCoins]=useState<CoinInterface[]>([]);
그냥 부여하면 Ts가 coins의 형식을 알 수 없기 때문에, 훅을 사용해 변수를 받는 경우에는 → 훅 뒤에 Interface를 작성해주며 형태를 명시해줄 수 있다.
2) fetching Api
(1) default setting
기본적으로 fetch 는 useEffect안에서 진행된다.
useEffect(()=>{
()();
},[])
useEffect(()⇒{},[]): useEffect는 (function, array)의 형식으로 진행된다.- 이 때 function은 array안에 있는 요소가 바뀔 때 마다 실행이 된다
- 함수를 표현할 때는 ()()의 형태로 표현한 후 앞의 괄호 안에 적어줄 수도 있다.
(2) async, await
useEffect안에 들어갈 async함수에 대해 알아보자.
async()=>{
const response = await fetch("https://api.coinpaprika.com/v1/coins");
const json = await response.json();
}
async:async함수await: 기다려야 할 동작 앞에 붙여준다.(변수 앞에 붙이는 거 아님)- 즉, 저 동작을 기다렸다가 변수 안에 값을 넣어주라는 뜻임
response→json
(3) slice method
data가 너무 길어서 slice를 사용하여 배열을 줄이려고 한다. slice 기능은 어떻게 사용하는 건지 정리해보자
const a=[1,2,3,4,5]
a.slice(0,3)=[1,2,3,4]
slice(a,b)→ 배열의 순번 a~b까지 잘라서 새로운 배열을 반환
slice method를 활용해보면
async()=>{
const response = await fetch("https://api.coinpaprika.com/v1/coins");
const json = await response.json();
setCoins(json.slice(0,100));
}
받아온 json을 잘라 저장하는 것을 확인해볼 수 있다.
3) Loading
지금부터는 로딩중임을 알려주는 기능을 담아보려고 한다. 이는 마찬가지로 useState를 활용하여 변수를 만들어준다.
이후, 아까 만들었던 fetch함수에서 fetching이 끝나면 loading의 값을 바꿀 수 있도록 코드를 추가하자
const [loading, setLoading]=useState(true);
useEffect(()=>{
(async()=>{
.
.
.
setLoading(false);
})();
loading,useState:useState를 활용하여 loading이라는 변수에true값을 할당해준다.setLoading(false): 아까 만들었던 fetching함수가 끝이 나면 →loading의 값을 바꿔준다.
이후, 이 기능이 화면에도 보일 수 있도록 return값을 수정해보자
{loading?"Loading...":<CoinList>
{coins.map(coin=>
<Coin key={coin.id}>
<Link to={`/${coin.id}`}>{coin.name}</Link>
</Coin>)}
</CoinList>}
loading?true: “Loading…”false: (=after fetching all the data) show the list of the coins
'프로그래밍 > React' 카테고리의 다른 글
| # React-Js Master Class #5-3 Crypto Tracker (0) | 2025.02.17 |
|---|---|
| # React-Js Master Class #5-2 Crypto Tracker (0) | 2025.02.11 |
| ReactJS 영화 웹 서비스 만들기 #3(useTitle) (0) | 2025.01.12 |
| ReactJS 영화 웹 서비스 만들기 #0(Intro) (0) | 2025.01.12 |
| ReactJS 영화 웹 서비스 만들기 #2(useTab) (0) | 2025.01.12 |