2021. 7. 23. 12:51ใ๐ React
| 1. React ์ค์น
ํ๋ก ํธ์ค๋ ํด๋๋ก ์ด๋ํด ํ์ฌ ํด๋ ๋ด๋ถ(.)์ react๋ฅผ ์ค์นํ๋ค.
cd frontend
npx create-react-app .
| 2. ํฐํธ ์ ํ
fonts.google.com
๋ฆฌ์กํธ ์ค์น๊ฐ ์งํ๋๋ ๋์ ๊ตฌ๊ธ ํฐํธ.com์ ์ ์ํ์ฌ ํ๋ก์ ํธ์ ์ฌ์ฉ๋ ํฐํธ๋ฅผ ๊ณจ๋ผ ํด๋น ์ฝ๋๋ฅผ ๋ณต์ฌํ๋ค.
[ ๋ณต์ฌํ ์ฝ๋ ]
// link ์ฝ๋
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,500;0,600;0,700;0,900;1,400;1,900&display=swap" rel="stylesheet">
// css ์ฝ๋
font-family: 'Playfair Display', serif;
ํด๋น ์ฝ๋๋ฅผ ํ๋ก ํธ์ publicํด๋ > index.html ํ์ผ ๋ด๋ถ์ ๋ถ์ฌ์ฃผ๋ฉด ํ๋ก์ ํธ ์ ๊ธ๊ผด ์ง์ ์ด ์๋ฃ๋๋ค.
index.html์ ์์ฑํ css ์คํ์ผ ์ฝ๋๊ฐ 2~3์ค๋ก ์งง๊ธฐ ๋๋ฌธ์ ๋ณ๋์ css ํ์ผ์ ์์ฑํ์ง ์๊ณ html ๋ฌธ์ ๋ด๋ถ์ style ์ฝ๋๋ฅผ ์์ฑํด ์ค๋ค. ( ์ฝ๋๊ฐ ๊ธธ์ด์ง๊ฒ ๋๋ค๋ฉด css ํ์ผ ์์ฑ์ ํ์! )
์ฐ์ ๊ธ๊ผด ์ง์ ์ , ์ค์น๋ ๋ฆฌ์กํธ ํ์ผ ์ ๋ถํ์ํ ํ์ผ๊ณผ ์ฌ์ฉํ์ง ์๋ ์ฝ๋๋ฅผ ์ ๋ฆฌํ๋ ์์ ์ ์งํํ๋ค.
| 3. React ํด๋ ์ต์ ํ ์์ - ๋ถํ์ ํ์ผ ๋ฐ ์ฝ๋ ์ ๊ฑฐ
1 ) public ํด๋
> index.html๋ฅผ ์ ์ธํ ํ์ผ์ ๋ชจ๋ ์ ๊ฑฐํ๊ณ , index.html ํ์ผ ์ ๋ถํ์ํ ์ฝ๋๋ฅผ ์ ๋ฆฌํ๋ค.
- index.html
์ฃผ์ ๋ฐ ๋ถํ์ํ ์ฝ๋๋ ์ ๊ฑฐํ๊ณ , ํ๋ก์ ํธ์ ๋ง๋ <title>์ ์์ฑํด์ค๋ค.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<title>Travel Map</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
- ๊ธ๊ผด ์ง์ ์ ์ํด html ๋ด๋ถ์ ์์ฑํ๋ค.
<link href="https://fonts.googleapis.com/css2?family=Zen+Loop&display=swap" rel="stylesheet">
<style>
*{
font-family: 'Zen Loop', cursive;
margin :0;
}
</style>
2 ) src ํด๋
> App.js ์ index.js ๋ง ๋จ๊ฒจ๋๊ณ ํ์ผ ์ ๊ฑฐํ๋ค.
- App.js - ํ์ผ ์ css import์ ๊ฐ์ ๋ถํ์ํ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๋ค.
function App() {
return (
<div> Travel Map</div>
);
}
export default App;
- index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
yarn start ๋ฅผ ํตํด ๊ธ๊ผด ์ ์ฉ๋ ํ๋ก์ ํธ๊ฐ ์ ์ ๋์ํ๋์ง ํ์ธํ๋ค ๐

| 4. Mapbox์ ์ ์ํด ์ง๋ ์ฌ์ฉ์ ์ํ ํ ํฐ ํค๋ฅผ ๋ฐ์์จ๋ค.
Maps, geocoding, and navigation APIs & SDKs | Mapbox
Integrate custom live maps, location search, and turn-by-turn navigation into any mobile or web app with Mapbox APIs & SDKs. Get started for free.
www.mapbox.com
์ ์ฌ์ดํธ์ ์ ์ํด navbar ์๋จ์ Products > Maps๋ฅผ ํ ์ ์ ์ํ๋ฉด ํ๋ฆฌํฐ ์ข์ ๋ค์ํ ์ง๋ ํ๋ฉด์ ํ์ธํ ์ ์๋ค.
์ฐ์ ํ์๊ฐ์ ํ ์์ ์ Account ํ์ด์ง๋ก ์ ์ํ๋ฉด ํ๋จ์ ํ๋ก์ ํธ์ ์ฌ์ฉํ ์ ์๋ token ํค๊ฐ ์ฃผ์ด์ง๋๋ค ๐
ํด๋น token ๊ฐ์ ๋ณต์ฌํ์ฌ front ์ .env ํ์ผ์ ์์ฑํด ์ ์ฅํด์ค๋๋ค.
REACT ์ ํ๋ฆฌ์ผ์ด์ ์ ํ๊ฒฝ ๋ณ์๋ ๋ณ์๋ช ์์ REACT_APP_ ๋ฅผ ์ถ๊ฐํด ์์ฑํด์ฃผ๋ฉด ๋ฉ๋๋ค.
REACT_APP_MAP_TOKEN = Mapbox ํ ํฐ๊ฐ
| 5. react-map-gl ์ค์น ๋ฐ ํ ํฐํค ์ฐ๊ฒฐ
์ด์ ๋ฐ์์จ ํ ํฐํค๋ฅผ ํ์ฉํด ๋ค์ํ ์ง๋๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ๋ณธ๊ฒฉ ์ ํ ํ๋ฌ ์ถ๋ฐ~ ๐ฐ
4-1) 'react-map-gl' ๋งต ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํด์ค๋๋ค.
yarn add react-map-gl
Vis.gl
Frameworks for WebGL-powered large-scale data visualization - Vis.gl
github.com
์ค์น ์งํ๋๋ ๋์ ์ Document ์ฌ์ดํธ์ ์ ์ํด get staeted๋ฅผ ํด๋ฆญํ๋ฉด ์ฝ๋ ์์ฑ์ ํ์ํ ๋ค์ํ ๋ฌธ์๋ค์ ํ์ธํ ์ ์๋ค.
import ๋ฅผ ํตํด ํ๋ก์ ํธ ์ฝ๋ ๋ด๋ถ์์ ๋งต ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, userState hook ๋ด๋ถ์ ๋๋น, ๋์ด ๋ฑ์ ๊ดํ ์ฝ๋๊ฐ ์์ฑ๋์ด์์ต๋๋ค. ์ ์ฝ๋๋ฅผ ํ ๋๋ก App.js๋ฅผ ์๋์ ๊ฐ์ด ์์ฑํ๋ค.
import { useState } from 'react';
import ReactMapGL from 'react-map-gl';
function App() {
const [viewport, setViewport] = useState({
width: 400,
height: 400,
latitude: 37.7577,
longitude: -122.4376,
zoom: 8
});
return (
<div>
<ReactMapGL
{...viewport}
mapboxApiAccessToken = {process.env.REACT_APP_MAP_TOKEN} // mapboxApiAccessToken ๋ณ์์ ํ ํฐ๊ฐ์ ์ ๋ฌํด์ค๋๋ค.
onViewportChange={nextViewport => setViewport(nextViewport)}
/>
</div>
);
}
export default App;
<ReactMapGL> ํ๊ทธ ์ฌ์ด mapboxApiAccessToken ๋ณ์๋ฅผ ์ถ๊ฐํด์ฃผ๋ฉด localhost:3000์ ๋ค์ํ๋ฉด์ด ์ ์ ์๋๋๋ค.
์คํํ๋ฉด์ด ๋จ์ง ์๋๋ค๋ฉด ์ข ๋ฃ ํ yarn start๋ฅผ ํตํด ๋ฆฌ์กํธ๋ฅผ ์ฌ์คํ ์์ผ์ค๋ค.
์ง๋๋ฅผ ์ ์ฒด ํ๋ฉด์ผ๋ก ํํํ๊ณ ์ถ๋ค๋ฉด useState ์ width: "100vw"์ height: "100vh" ๋ก ์กฐ์ ํด ์ฃผ๋ฉด ๋๋ค.
๋ํ ํ์ฌ ์์น ์ํ๋์์ค์์ ์ํ๋ ์๋ ๊ฒฝ๋ ์์ ์ ํตํด ์ฅ์๋ฅผ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ค.
์๋ ๊ฒฝ๋ ๊ฐ์ ์์ธ ๋ถ๊ทผ์ผ๋ก ๋ณ๊ฒฝํ๊ณ , ํ๋๋ ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ์ถ์ผ๋ฉด zoom ๋ณ์์ ์ซ์๋ฅผ ๋ฎ์ถฐ์ฃผ๋ฉด ๋๋ค.
const [viewport, setViewport] = useState({
width: "100vw", // ์ง๋ ๋๋น
height: "100vh", // ๋์ด
latitude: 37.562003, // ๊ฒฝ๋
longitude: 127, // ์๋
zoom: 4 // ํ๋ ์์น ๐
});
| 6. ๋งต ์์ Marker ํ๊ธฐ ์ฝ๋ ์์ฑ
API Reference > Marker ๋ฌธ์๋ฅผ ํ์ฉํด ์ง๋ ์์ Marker๋ฅผ ์์ฑํ๋ค.
react-map-gl | Marker
React wrapper for Mapbox GL JS
visgl.github.io
'react-map-gl' ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋ถํฐ Marker๋ฅผ import ํ ๋ค์ <ReactMapGL> ํ๊ทธ ๋ด๋ถ์ Marker ์ฝ๋๋ฅผ ์์ฑํด์ค๋ค.
๋กฏ๋ฐํ์์ ์๋ ๊ฒฝ๋ ์์น์ Marker๋ฅผ ํ์ํด ๋ณด๊น์ ?
[ ์ถ๊ฐ๋ ์ฝ๋ ]
import { Marker } from 'react-map-gl';
<Marker latitude={37.5125} longitude={127.102778} offsetLeft={-20} offsetTop={-10}>
<h1> Lotte Towel is here </h1>
</Marker>
[ ์ ์ฒด index.js ์ฝ๋ ]
import { useState } from 'react';
import ReactMapGL, { Marker } from 'react-map-gl';
function App() {
const [viewport, setViewport] = useState({
width: "100vw",
height: "100vh",
latitude: 37.562003,
longitude: 127,
zoom: 8
});
return (
<div>
<ReactMapGL
{...viewport}
mapboxApiAccessToken={process.env.REACT_APP_MAP_TOKEN}
onViewportChange={nextViewport => setViewport(nextViewport)}
>
<Marker latitude={37.5125} longitude={127.102778} offsetLeft={-20} offsetTop={-10}>
<h1>Lotte Towel is here</h1>
</Marker>
</ReactMapGL>
</div>
);
}
export default App;
์ด์ css๋ฅผ ํ์ฉํด ๋ง์ปค๋ฅผ ์ด์๊ฒ ๊พธ๋ฉฐ์ฃผ๋๋ก ํ๋ค.
yarn add @material-ui/core @material-ui/icons
Material Icons - Material-UI
1,100+ React Material icons ready to use from the official website.
material-ui.com
material-icons๋ก๋ถํฐ ์ ์์ด์ฝ์ importํด์ <Marker> ํ๊ทธ ์ฌ์ด์ ์์ฑํด์ค๋ค.
import { Room } from '@material-ui/icons' ;
<Marker> <Room> <Marker/>
;
์ด๋ ์ง๋๋ฅผ ํ๋ํ ๊ฒฝ์ฐ ์์น๊ฐ ๊ณ ์ ๋์ฑ ์ํ๋ ์์น๋ก ์ด๋๋์ง ์๋๋ฐ, ์์ด์ฝ์ fontsize๋ฅผ viewport.zoom * 5๋ก ์ง์ ํด์ฃผ๋ฉด ์ง๋ ์ฌ์ด์ฆ์ ๋ง๋ ์ ๋นํ ํฌ๊ธฐ๋ก ์ ๋ณ๋๋๋๊ฒ์ ํ์ธ ํ ์ ์๋ค.
<Marker latitude={37.5125} longitude={127.102778} offsetLeft={-20} offsetTop={-10}>
<Room style={{ fontSize: viewport.zoom * 5, color: "slateblue" }} />
</Marker>
| 7. ์ง๋ ๋์์ธ ๋ณ๊ฒฝ
Gallery
Browse our collection of maps to see what's possible with Studio
www.mapbox.com
๋ค์ Mapbox์ account ํ์ด์ง๋ก ์ ์ํด Mapbox ์คํ๋์ค ๋์์ธ์ ํด๋ฆญํ๋ค
์ทจํฅ์ ๋ง๊ฒ ์ง๋ ๋์์ธ ์ปค์คํฐ๋ง์ด์ง์ ์๋ฃํ๋ค๋ฉด ๋ค์ styles๋ก ๋์์ ํด๋น ์ง๋์ Style URL์ ๋ณต์ฌํด <ReactMapGL> ํ๊ทธ ์์ mapStyle๋ก ์์ฑํด์ค๋ค.
<ReactMapGL
{...viewport}
mapboxApiAccessToken={process.env.REACT_APP_MAP_TOKEN}
onViewportChange={nextViewport => setViewport(nextViewport)}
// ์์ ์ด ์ปค์คํฐ๋ง์ด์งํ ์คํ์ผ url ์ฝ์
mapStyle = "mapbox://styles/angluvpeng/ckrfpsp1f4o3417mxdnu564cw"
>
| 8. ์ง๋ ํ์ ํ์ ์ฐฝ ์ค์
Posted by Ang