๐Ÿ”ฎ ์†Œ๋งˆ๋ฒ• ํ”„๋กœ์ ํŠธ -8 (maskmap)

๋„ค์ด๋ฒ„ ์ง€๋„ API์™€ ๊ณต์  ๋งˆ์Šคํฌ ํŒ๋งค ํ˜„ํ™ฉ ์กฐํšŒ API๋ฅผ ์ด์šฉํ•ด์„œ ๋งŒ๋“  ์ฝ”๋กœ๋‚˜ ๋งˆ์Šคํฌ ํŒ๋งค์ฒ˜ ์ฐพ๊ธฐ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜


#. Project Map


์ œ์ž‘๋…ธํŠธ ํ•œ๋ˆˆ์—๋ณด๊ธฐ[์ ‘๊ธฐ/ํŽผ์น˜๊ธฐ]

1. ๋ ˆ์ด์•„์›ƒ

1-1. ๋ฉ”์ธํ™”๋ฉด

maskmap

์ „์ฒด ํ™”๋ฉดํฌ๊ธฐ์— ๋งž๊ฒŒ ๋„ค์ด๋ฒ„์ง€๋„๋กœ ์ฑ„์šฐ๊ณ , ํ™”๋ฉด ์ขŒ์ธก์—

  1. ๋‚ด ์œ„์น˜ ๋ฒ„ํŠผ
  2. ๋งˆ์Šคํฌ 5๋ถ€์ œ์— ํ•ด๋‹นํ•˜๋Š” ์˜ค๋Š˜ ์š”์ผ๊ณผ ๋งˆ์Šคํฌ ๊ตฌ์ž… ๋…„์ƒ ํ‘œ์‹œ์ฐฝ
  3. ๋งˆ์Šคํฌ ํŒ๋งค์ฒ˜์˜ ๋งˆ์Šคํฌ ๋ณด์œ ๊ฐœ์ˆ˜์— ๋Œ€ํ•œ ์ƒ‰์ƒ ์„ค๋ช…์ฐฝ์„ ๋‘์—ˆ๋‹ค.

1-2. ์ปดํฌ๋„ŒํŠธ

<BackgroundContainer>
  <ContentsMenubar name="maskmap" />
  <Description>
    <button onClick={mylocationHandler}>๋‚ด ์œ„์น˜</button>
    <div>
      <span
        style={{
          textAlign: 'center',
          color: 'black',
          background: 'rgba(255,255,255,0.7)',
        }}
      >
        <div style={{ fontSize: '20px', fontFamily: 'escore8' }}>
          {weekArr[week]}์š”์ผ
        </div>
        <div style={{ marginTop: '5px' }}>{weekMask[week]}</div>
      </span>
      <span style={{ background: 'green' }}>100๊ฐœ์ด์ƒ</span>
      <span style={{ background: 'orange' }}>30~100๊ฐœ</span>
      <span style={{ background: 'red' }}>2~30๊ฐœ</span>
      <span style={{ background: 'black' }}>์—†์Œ</span>
    </div>
  </Description>
  <MapContainer id="map"></MapContainer>
</BackgroundContainer>

์ปดํฌ๋„ŒํŠธ๋Š” ํฌ๊ฒŒ

  1. Description : ํ™”๋ฉด ์ขŒ์ธก ๋‚ด์œ„์น˜ ๋ฒ„ํŠผ๊ณผ ์„ค๋ช…์ฐฝ
  2. MapContainer : ์ง€๋„

๋‘ ๊ฐœ๋กœ ๊ตฌ์„ฑํ•˜์˜€๊ณ  ๋‘ ์ปดํฌ๋„ŒํŠธ ๋ชจ๋‘ styled-component ๋กœ ๊ตฌ์„ฑํ•˜์˜€๋‹ค.

2. ์ƒํƒœ๊ด€๋ฆฌ

let map = null
const week = new Date().getDay()
const weekArr = ['์ผ', '์›”', 'ํ™”', '์ˆ˜', '๋ชฉ', '๊ธˆ', 'ํ† ']
const weekMask = [
  '๋ˆ„๊ตฌ๋‚˜',
  '1,6๋…„์ƒ',
  '2,7๋…„์ƒ',
  '3,8๋…„์ƒ',
  '4,9๋…„์ƒ',
  '5,0๋…„์ƒ',
  '๋ˆ„๊ตฌ๋‚˜',
]
  1. map : ๋„ค์ด๋ฒ„ ์ง€๋„ API naver.maps.Map ๊ฐ์ฒด๊ฐ€ ๋‹ด๊ธธ ๋ณ€์ˆ˜
  1. week : ํ˜„์žฌ ์š”์ผ
  1. weekArr : ํ˜„์žฌ ์š”์ผ์— ๋Œ€ํ•œ ํ•œ๊ธ€์ถœ๋ ฅ
  1. weekMask : ์š”์ผ์— ๋Œ€ํ•œ ๋งˆ์Šคํฌ 5๋ถ€์ œ ์ •๋ณด

3. ๋„ค์ด๋ฒ„์ง€๋„ API

3-1. ์ง€๋„๊ฐ€ ๋“ค์–ด๊ฐˆ ์—˜๋ฆฌ๋จผํŠธ ์ง€์ •

<MapContainer id="map"></MapContainer>

๋จผ์ € ์ง€๋„๊ฐ€ ๋“ค์–ด๊ฐˆ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ง€์ •ํ•˜๊ณ  id ๊ฐ’์„ ๋ถ™์—ฌ, DOM์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ์—ˆ๋‹ค.

3-2. ์ง€๋„ ์ƒ์„ฑ

useEffect(() => {
    map = new naver.maps.Map('map', {
      center: new naver.maps.LatLng(37.5666805, 126.9784147),
      zoom: 10,
      mapTypeId: naver.maps.MapTypeId.NORMAL
    })

์ง€๋„๋Š” ๋งˆ์šดํŠธ๋œ ํ›„์— ์‹คํ–‰๋˜๋Š” useEffect ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ƒ์„ฑํ•ด์ฃผ์—ˆ๋‹ค.

๊ธฐ๋ณธ์ ์ธ ์ •๋ณด(์ง€๋„ํ˜„์žฌ์œ„์น˜, ์คŒ, ํƒ€์ž…)์€ ๋„ค์ด๋ฒ„์ง€๋„์—์„œ ์ œ๊ณตํ•œ ๊ธฐ๋ณธ์ ์ธ ์ •๋ณด๋กœ ์‚ฌ์šฉํ•˜์˜€๋‹ค. (์„œ์šธ์‹œ์ฒญ)

3-3. ๋‚ด ์œ„์น˜ ์ฐพ๊ธฐ

<button onClick={mylocationHandler}>๋‚ด ์œ„์น˜</button>

์šฐ์„  button ํด๋ฆญ ์ด๋ฒคํŠธํ•ธ๋“ค๋Ÿฌ์— mylocationHandler ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•˜๊ณ ,

const onSuccessGeolocation = position => {
  var location = new naver.maps.LatLng(
    position.coords.latitude,
    position.coords.longitude
  )

  map.setCenter(location)
  map.setZoom(16)
}

const onErrorGeolocation = () => {
  // ์—๋Ÿฌ!!
}

const mylocationHandler = () => {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(
      onSuccessGeolocation,
      onErrorGeolocation
    )
  } else {
    // ์—๋Ÿฌ
  }
}

์œ ์ €๊ฐ€ ์œ„์น˜๊ถŒํ•œ์„ ํ—ˆ์šฉํ–ˆ๋‹ค๋ฉด getCurrentPosition ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•˜์—ฌ ํ˜„์žฌ ์œ„์น˜์ •๋ณด๋ฅผ map ๊ฐ์ฒด๋ณ€์ˆ˜์— ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.

4. ๋งˆ์Šคํฌ ํŒ๋งคํ˜„ํ™ฉ API

4-1. addListener

naver.maps.Event.addListener(map, 'dragend', function(e) {
  // ...
})

๋จผ์ € API ํ†ต์‹ ์€ ์œ ์ €๊ฐ€ ์ง€๋„๋ฅผ ๋“œ๋ž˜๊ทธํ•  ๋•Œ๋งˆ๋‹ค ์š”์ฒญํ•˜๊ฒŒ๋” ๊ตฌํ˜„ํ•ด๋ณด์•˜๋Š”๋ฐ

maps.Event์˜ addListener ๋ฉ”์†Œ๋“œ parameter ์•ˆ์— ํ˜„์žฌ์ง€๋„ map, dragend ์ด๋ฒคํŠธ, ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.

4-2. fetch (AJAX)

const url =
  'https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/storesByGeo/json'
const query = `?lat=${map.getCenter().y}&lng=${map.getCenter().x}`
fetch(url + query)
  .then(res => {
    return res.json()
  })
  .then(json => {
    // ...
  })

API ํ†ต์‹ ์€ fetch๋ฅผ ์ด์šฉํ–ˆ๊ณ  then ๋ฉ”์†Œ๋“œ ์ฒด์ด๋‹์„ ํ†ตํ•ด ์š”์ฒญ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•ด์ฃผ์—ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ณต์  ๋งˆ์Šคํฌ ํŒ๋งค ํ˜„ํ™ฉ ์กฐํšŒ API ์— ํ•„์š”ํ•œ parameter๋‚˜ ์ „๋‹ฌ๋ฐ›์„ JSON ๋ฐ์ดํ„ฐ ํ˜•์‹์ด ์ž˜ ๋‚˜์™€์žˆ์–ด์„œ ์ฐธ๊ณ ํ•˜๋ฉฐ url์„ ๊ตฌ์„ฑํ•˜์˜€๋‹ค.

4-3. ๋งˆ์ŠคํฌํŒ๋งคํ˜„ํ™ฉ marker

const remain_stat = {
  plenty: 'green',
  some: 'orange',
  few: 'red',
  empty: 'black',
  break: 'black',
}
for (let i = 0; i < json.count; i++) {
  var marker = new naver.maps.Marker({
    icon: {
      content: `<div style="font-size:10px; font-family:escore6; border:1px solid lightgrey; color:white; background:${
        remain_stat[json.stores[i].remain_stat]
      }; border-radius:5px; padding:4px;">${json.stores[i].name}</div>`,
    },
    position: new naver.maps.LatLng(json.stores[i].lat, json.stores[i].lng),
    map: map,
  })
}

๋งˆ์ง€๋ง‰์œผ๋กœ ๋งˆ์ŠคํฌํŒ๋งคํ•˜๋Š” ๊ณณ์˜ ํŒ๋งคํ˜„ํ™ฉ์„ ํ‘œ์‹œํ•˜๋Š” ๋งˆ์ปค๋ฅผ ๋„ฃ์–ด์ฃผ์—ˆ๋Š”๋ฐ ๊ณต์  ๋งˆ์Šคํฌ ํŒ๋งค ํ˜„ํ™ฉ ์กฐํšŒ API ์—์„œ๋Š” ๋งˆ์Šคํฌ๊ฐฏ์ˆ˜์— ๋”ฐ๋ฅธ ์ƒ‰๊น”์„ ํ†ต์ผํ•ด์ฃผ๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•˜์—ฌ์„œ ๊ทธ์— ๋งž๊ฒŒ ์ƒ‰๊น”์„ ์ง€์ •ํ•ด์ฃผ์—ˆ๋‹ค.

๋…น์ƒ‰(100๊ฐœ ์ด์ƒ)/๋…ธ๋ž‘์ƒ‰(30~99๊ฐœ)/๋นจ๊ฐ•์ƒ‰(2~29๊ฐœ)/ํšŒ์ƒ‰(0~1๊ฐœ)

5. ๊ฐœ์ธ์ ์ธ ํ”ผ๋“œ๋ฐฑ

5-1. ๋งˆ์ปคํ‘œ์‹œ ์ด๋ฒคํŠธ

ํ•ด๋‹น ์•ฑ์—์„œ ์ง€๋„์— ๋งˆ์Šคํฌ ํ˜„ํ™ฉ ๋งˆ์ปค๋ฅผ ํ‘œ์‹œํ•˜๋ ค๋ฉด ์šฐ์„  ์‚ฌ์šฉ์ž๋Š” ์ง€๋„๋ฅผ ๋“œ๋ž˜๊ทธํ•ด์•ผํ•œ๋‹ค.

dragend ์ด๋ฒคํŠธ๋ผ ๋“œ๋ž˜๊ทธ๊ฐ€ ์™„๋ฃŒ๋œ ์‹œ์ ์— ํ•œ๋ฒˆ๋งŒ api๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๋Š” ์ ์—์„œ ํšจ์œจ์ ์ด์ง€๋งŒ ux์ ์œผ๋กœ๋Š” ๋ณ„๋กœ ์ข‹์ง€ ๋ชปํ•œ ๊ฒƒ ๊ฐ™๋‹ค.

์ดˆ๊ธฐ ์ง€๋„ ๊ตฌ์„ฑ์‹œ (ํ˜น์€, ํ˜„์žฌ์œ„์น˜ ๋ฒ„ํŠผ์„ ์ฒ˜์Œ ํด๋ฆญํ•œ ์‹œ์ )์—๋„ ๋งˆ์ปค๋ฅผ ํ‘œ์‹œํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ๋„ฃ์œผ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

5-2. ์ง€๋„์˜ ๋ถ€์ •ํ™•ํ•จ

์ด๊ฑฐ๋Š” ์ง€๋„ API์˜ ๋ฌธ์  ์ง€ ๋‚ด ์ฝ”๋“œ์˜ ๋ฌธ์  ์ง€ ์•„์ง ํŒŒ์•…์„ ๋ชปํ–ˆ์ง€๋งŒ ๋‚ด ์œ„์น˜๊ฐ€ ์ •ํ™•ํžˆ ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

๊ทธ๋ž˜๋„ ๋‚ด ์œ„์น˜ ๊ทผ๋ฐฉ๊นŒ์ง€๋Š” ์ž˜ ํ‘œ์‹œํ•ด์ฃผ๋Š” ๊ฒƒ ๊ฐ™์•„์„œ ์œ ์ €๊ฐ€ ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๊ฒŒ ๊ทธ๋ƒฅ๋‚ด์œ„์น˜ ๋งˆ์ปค๋ฅผ ๋นผ๋ฒ„๋ ธ๋‹ค!


Written by@taenyKim
๋ฐฐ์šฐ๋ฉฐ ์„ฑ์žฅํ•˜๊ณ  ๊ธฐ๋กํ•˜๊ธฐ #FE #UI #๊ฐœ๋ฐœ #life

GitHubFacebook