Google Cloud Platform(GCP)
Google Maps Platform
Platform Pricing & API Costs
Styling Wizard: Google Maps
Google Maps Platform - Documentation
์ด๋ฒ๊ธ์์๋ Google Maps๋ฅผ ์ฌ์ฉํ์ฌ Flutter์์ ์ง๋๋ฅผ ๋์ฐ๊ณ ํ์ฉํ ์ ์๋ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด๋๋ก ํ๊ฒ ๋ค.
Flutter์์ ์ง๋๋ฅผ ๋์ฐ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ๋ค์ด ์๋ค.
๊ตญ๋ด ์๋น์ค๋ง์ ์ง์ํ๋ค๋ฉด Naver, Kakao ๋ฑ์ ์ง๋๋ฅผ SDK๋ก ์ฌ์ฉํ ์๋ ์๊ณ , ๊ธ๋ก๋ฒ ์๋น์ค๋ฅผ ์ง์ํ๋ ๊ฒฝ์ฐ์๋ Google, OSM(Open Street Map) ์ง๋๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค.
์ฌ๋ฌ ๋ฐฉ๋ฒ ์ค Google ์ง๋๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ๋ค๋ค๋ณผ ์์ ์ด๊ณ , ๋ค๋ฅธ ๊ธ์์ OSM, Naver, Kakao ์ง๋๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ๊ณต์ ํ ์์ ์ด๋ค.
Google Maps๋ Google์ด ์ ๊ณตํ๋ ์ ์ธ๊ณ ์ง๋ ๋ฐ ๋ค๋น๊ฒ์ด์ ์๋น์ค๋ก, ์ผ๋ฐ/์์ฑ/์งํ/์ค์๊ฐ ๊ตํต ๋ฑ์ ๋ค์ํ ๋ทฐ๋ฅผ ์ ๊ณตํ๊ณ ์๊ณ ๊ธธ์ฐพ๊ธฐ, ์คํธ๋ฆฌํธ ๋ทฐ, ์์น ๊ฒ์, ๋งค์ฅ ๋ฐ ์ ์ฒด ๊ฒ์, ์ฅ์ ๋ฆฌ๋ทฐ/๋ณ์ ๋ฑ์ ์์น์ ๊ด๋ จ๋ ๊ธฐ๋ฅ๋ค์ API๋ฅผ ํตํด ๋ฌด๋ฃ ๋๋ ์ ๋ฃ๋ก ์ ๊ณตํด์ฃผ๊ณ ์๋ค.
์์ ๊ธฐ๋ฅ๋ค์ ๋ชจ๋ฐ์ผ์ธ์ง ์น์ธ์ง์ ๋ฐ๋ผ ์ ๊ณต ๋ฒ์๊ฐ ๋ฌ๋ผ์ง๊ฒ ๋๊ณ ๊ธฐ๋ฅ๋ณ API ๋น์ฉ๋ ์ผ๋ถ ์ฐจ์ด๊ฐ ์์ ์ ์์ผ๋ ๋ฐ๋์ ์๋น์ค์ ์ฌ์ฉํ๊ณ ์ถ์ ๊ธฐ๋ฅ์ ๋น์ฉ์ ํ์ธํ์์ด ๊ฐ๋ฐ์ ์งํํ์ฌ์ผ ํ๋ค.
Google Maps๋ ๊ตฌ๊ธ์ ๋ค์ํ Platform์ ์ง์ํ๋ GCP(Google Cloud Platform)์์ ์ ๊ณตํ๋ฉฐ, Maps Platform์ ๊ฒฝ์ฐ ๋ชจ๋ ๊ณ์ ์ ์ $200 ๋ฌด๋ฃ ํฌ๋ ๋ง์ ์ง์ํด์ฃผ๊ธฐ ๋๋ฌธ์ ๋ฒ์๋ด์์๋ ๋ฌด๋ฃ ์ฌ์ฉ๋ ๊ฐ๋ฅํ๋ค.
Flutter๋ก ๋ชจ๋ฐ์ผ ๊ฐ๋ฐ์ ํ๋ ๊ฒฝ์ฐ์๋ Maps SDK๋ก ๋จ์ํ ์ง๋๋ฅผ ๋ ธ์ถํ๊ณ ๋๋ฐ์ด์ค์ GPS๋ฅผ ํตํด ์ค์๊ฐ ์์น๋ฅผ ๊ฐ์ ธ์ค๋ ์ ๋์ ๊ธฐ๋ฅ์ ๊ณผ๊ธ ์์ด ์ฌ์ฉ์ด ๊ฐ๋ฅํ์ง๋ง, ์ฃผ์๋ฅผ ์ขํ๋ก ๋ณํํ๋ Geocoding API๋ ์ขํ๋ฅผ ์ฃผ์๋ก ๋ณํํ๋ Reverse Geocoding API, ๊ฒฝ๋ก๋ฅผ ๊ฒ์ํ๋ Directions API, ์ฅ์ ๋ฐ ๋งค์ฅ ์ ๋ณด๋ฅผ ๊ฒ์ํ๋ Places API๋ ๊ณผ๊ธ ๋์์ด๋ GCP ๊ฐ๊ฒฉ ์ ์ฑ ์์ ์ ํํ ๋น์ฉ์ ํ์ธํ์๋ฉด ๋๋ค.
์ด ๊ธ์์๋ Google Maps์ ๋ค์ํ ๊ธฐ๋ฅ๋ค์ ์ต๋ํ ๋ค๋ค๋ณผ ์์ ์ด๋ฉฐ, ๋น์ฉ์ ๋ํ ๋ถ๋ถ์ ๊ณ ๋ คํ์ง ์์ ๊ฒ์ด๋ ์ฐธ๊ณ ํ์๊ธธ ๋ฐ๋๋ค.
Google Maps ์ฌ์ฉ์ ์ํ API ํ์ฑํ ๋ฐ ์ฝ์ ์ธํ ์ ์งํํด ๋ณด์.
Google Cloud Platform(GCP)์ ์ ์ํ์ฌ, ์ํ๋ ํ๋ก์ ํธ๋ฅผ ์ ํํด ์ฃผ๋๋ก ํ์.
GCP์ ์ ์ ํ ์ฝ์์ ํด๋ฆญํ์ฌ ์ด๋ํด ์ฃผ์.
์ข์ธก ์๋จ์ ํ๋ก์ ํธ๋ฅผ ๋๋ฌ์ ์ํ๋ ํ๋ก์ ํธ๋ฅผ ์ ํํด ์ฃผ์๋ฉด ๋๋ค. ๋ง์ผ ํ๋ก์ ํธ๊ฐ ์์ง ์์ฑํ์ง ์์๋ค๋ฉด "์ ํ๋ก์ ํธ"๋ฅผ ์ ํํด์ ํ๋ก์ ํธ๋ฅผ ์์ฑํด์ฃผ์๋ฉด ๋๋ค.
์ฌ๊ธฐ์ GCP๋ฅผ ํ ๋ฒ๋ ์ฌ์ฉํ์ง ์์๋ค๋ฉด ๋ฌด๋ฃ๋ก ์์ํ๊ธฐ๋ฅผ ํตํด ๊ณ์ ์ ๋ฑ๋กํด ์ฃผ๊ณ ์งํํด์ฃผ์๋ฉด ๋๋ค.
GCP์ API๋ ์ ๋ฃ๊ฐ ํฌํจ๋์ด ์์ด ์ฌ์ฉํ ๋งํผ ๊ณผ๊ธ๋๋ ๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์, ๊ณ์ ์ต์ด ๋ฑ๋ก์์๋ ์นด๋ ์ ๋ณด๋ฅผ ๋ฐ๋์ ์ ๋ ฅํด์ผ ํ๋ค. ํ ์คํธ ์ฉ๋๋ผ๋ฉด ํ๋๋ฅผ 100์์ผ๋ก ๋ฎ๊ฒ ์ค์ ํด ์ฃผ์๋ฉด ๋๋ค.
ํ๋ก์ ํธ๋ก ์ด๋์ ์๋ฃ ํ์๋ค๋ฉด, ์๋จ์ ๊ฒ์๋ฐ๋ฅผ ํตํด Google Maps Platform์ผ๋ก ์ด๋ํด ์ฃผ์.
์ด์ Google Maps Platform์ผ๋ก ์ด๋ํด๋ณด๋ฉด, ์๋์ ๊ฐ์ด Google Maps Platform ์์ํ๊ธฐ๊ฐ ๋ ธ์ถ ๋๋ฉด์ ๋ฐ๋ก API ํค๋ฅผ ์์ฑํ๋๋ก ๋์ค๊ฒ ๋๋๋ฐ, "Google Maps Platform์ผ๋ก ์ด๋" ๋ฒํผ์ ํด๋ฆญํด ์ฃผ๊ณ ์ฐ์ API ํค ๋ณดํธ๋ ๋์ค์๋ฅผ ์ ํํด์ ๋์ด๊ฐ ์ฃผ๋๋ก ํ์.
![]() |
![]() |
์์ API ํค ์๋ ์์ฑ ์ฐฝ์ด ๋ ธ์ถ๋์ง ์์๋ ์๋ฌด ๋ฌธ์ ์๋ค.
๋์๋ณด๋ ์ข์ธก์ "ํค ๋ฐ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด"๋ก ์ด๋ํด ๋ณด๋ฉด, ๋ฐฉ๊ธ ์์ฑํ ํค๋ฅผ ํ์ธํ ์ ์๋ค.
![]() |
![]() |
์์ฑ๋ ํค๋ฅผ ๋๋ฌ์ ๋ค์ด๊ฐ ๋ณด๋ฉด ์์ธํ ์ ๋ณด๋ฅผ ๋ณผ ์ ์๋๋ฐ, ์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ํ๋ ์๊ธฐ๊ฒ ๋๋ค.
ํค ์ ํ์ฌํญ ํญ์์ ์ ์ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ฌํญ์ด ์๋๋ฐ, ํด๋น API ํค๋ก๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ ์ญ์ 1๊ฐ๋ง ๋ฑ๋ก์ด ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
Flutter๋ Android, iOS๋ฅผ ๋ชจ๋ ์ปค๋ฒํ๋ ํฌ๋ก์ค ํ๋ซํผ์ด๊ธฐ ๋๋ฌธ์, ํ๋์ ์ ํ๋ฆฌ์ผ์ด์ ๋ง ๊ฐ๋ฐํ์ง ์๋ค๋ณด๋ API ํค๋ฅผ ์์ ํ๊ฒ ๋ณดํธํ์ง ๋ชปํ๊ฒ ๋๋ค.
๋ณธ์ธ์ ์๋น์ค์์ ๋ณ๋๋ก API ํค๋ฅผ ๋ณดํธํ์ง ์์๋ ๋๋ค๊ณ ํ๋จํ์๋ฉด, ๊ทธ๋ฅ ์ ํ ์์ด ํ๋์ ์์ฑ๋ API๋ก Android, iOS๋ฅผ ๋ชจ๋ ์ฌ์ฉํ์ฌ๋ ์๊ด์ ์๋ค. ๋ค๋ง API ํค์ ์ ํ์ด ์๊ธฐ ๋๋ฌธ์ API ํค ์ ์ถ๋ก ์ธํ ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ํ์ด ๋ถ๊ฐ๋ฅํ๋ค.
Android, iOS ์ค ๋จ์ผ ํ๋ซํผ๋ง ์๋น์ค๋ฅผ ์ ๊ณตํ ๊ฒฝ์ฐ๋ผ๋ฉด ํ๋์ ํค๋ง ์ ํ์ฌํญ์ ์ค์ ํ์ฌ ์ฌ์ฉํ์๋ฉด ๋๋ค.
์๋จ์ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด ๋ง๋ค๊ธฐ๋ฅผ ํด๋ฆญํ์ฌ API ํค๋ฅผ ์ ํํด ์ฃผ๋ฉด ์ฆ์ ์์ฑ์ด ์๋ฃ๋๋ค.
![]() |
![]() |
์์ฑ๋ API ํค๋ฅผ ํด๋ฆญํ์ฌ ์์ ์ ํด๋ณด๋๋ก ํ์.
์ฐ์ Android ์ ์ฉ API๋ฅผ ์์ฑํ๋๋ก ํ๊ฒ ๋ค. ํค ๊ตฌ๋ถ์ ์ํด ์ด๋ฆ์ ์์ ๋กญ๊ฒ ์์ ํด ์ฃผ์๋ฉด ๋๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ฌํญ์ Android ์ฑ์ ์ ํํ๋ฉด ์๋์ ์ถ๊ฐํ ์ ์๋ ๋ฒํผ์ด ๋์จ๋ค.
ํ์ฌ ํด๋น API ํค๋ฅผ ์ฌ์ฉํ๋ ค๋ ์ฑ์ ํจํค์ง ์ด๋ฆ์ ๋ฃ์ด์ฃผ๊ณ , SHA-1 ์ธ์ฆํค๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.
์ฐ์ ํจํค์ง ๋ค์์ ํ๋ก์ ํธ์ Android > app > build.gradle ํ์ผ์์ android ํ๊ทธ์ namespace์์ ํ์ธํ๋ฉด ๋๋ค.
SHA-1 ๋๋ฒ๊ทธ ์ธ์ฆํค ์ถ์ถ์ Mac ๊ธฐ์ค์ผ๋ก ํ๋ก์ ํธ ์์ค์์ ํฐ๋ฏธ๋์ ์ด์ด ์๋ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํด์ฃผ๋ฉด ์ถ๋ ฅ๋๋ ์ธ์ฆ์ ์ง๋ฌธ์ SHA1์ ๋ณต์ฌํด์ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.
keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore -storepass android -keypass android
์๋์ฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ์๋ ๊ธ์์ ์ถ์ถ ๋ฐฉ๋ฒ์ ํ์ธํ ์ ์๋ค.
์ฐธ๊ณ ๋ก SHA1 ๋๋ฒ๊ทธ ์ธ์ฆํค๋ ๊ฐ PC๋ง๋ค ๊ณ ์ ํ ์ธ์ฆ์์ด๋ฏ๋ก, ์ฌ๋ฌ ํ์๊ณผ ํ์ ํ๋ ๊ฒฝ์ฐ์๋ ๊ฐ ํ์์ PC์ ์ธ์ฆํค๋ฅผ ๋ชจ๋ ์ถ๊ฐํด ์ฃผ๋ฉด ๋๋ค. ์ถ๊ฐ๋ฅผ ํด์ฃผ์ง ์์ผ๋ฉด API ํค ๋ณดํธ์ ๋ฐ๋ผ API ์์ฒญ์ด ๊ฑฐ๋ถ๋๊ฒ ๋๋ค.
SHA-1 ํค์ ํจํค์ง ๋ค์์ ์ถ๊ฐํ๊ณ ํ๋จ์ ์ ์ฅ์ ๋๋ฌ ๋ณ๊ฒฝ์ฌํญ์ ์ ์ฅํด์ฃผ๋ฉด ์๋์ ๊ฐ์ด ์ ์์ ์ผ๋ก ์ถ๊ฐ๊ฐ ๋๋ค.
์ถ๊ฐ๊ฐ ๋ ํ์ํ๋ค๋ฉด Add๋ฅผ ๋๋ฌ ์ฌ๋ฌ ๊ฐ์ ์ธ์ฆ์๋ฅผ ์ถ๊ฐํ ์ ์๋ค.
์ ์ด์ ๋ฐฐํฌ๋ฅผ ์ผ๋ํ ์ํ์ด๊ฑฐ๋ ์ด๋ฏธ ๋ฐฐํฌ๋ ์๋น์ค์ ๊ฒฝ์ฐ ์คํ ์ด ์ธ์ฆ์์ SHA-1 ํค๋ ๋ฑ๋ก์ ํด์ฃผ์ด์ผ ์ ์์ ์ผ๋ก ์ฌ์ฉ์๋ค์ด ์๋น์ค ์ด์ฉ์ด ๊ฐ๋ฅํ๋ค.
Play Console๋ก ์ด๋ํ์ฌ ์ฑ ๋ฌด๊ฒฐ์ฑ > ์ฑ ์๋ช ํญ์ผ๋ก ์ด๋ํ๋ฉด ๋ฐฐํฌ๋ ์๋น์ค์ ์ฑ ์๋ช SHA1 ํค ๊ฐ์ ํ์ธํ ์ ์๋ค.
ํด๋น ํค๊ฐ ๋ฑ๋ก๋์ง ์์ผ๋ฉด ์คํ ์ด์์ ๋ค์ด๋ก๋ ๋ฐ์ ์ฑ์ API ์ ๊ทผ์ด ๊ฑฐ์ ๋๊ธฐ ๋๋ฌธ์, ๋ฐฐํฌ๋ ์๋น์ค๋ผ๋ฉด ๋ฐ๋์ ์ถ๊ฐํด์ผ ํ๊ณ ์์ง ๋ฐฐํฌ ์ ์ด๋ผ๋ฉด ๋ฐฐํฌ์ ๊ตฌ๊ธ์์ ์๋ช ํ๋ ์ฑ ์๋ช ํค๋ฅผ ๋์น์ง ๋ง๊ณ ํด๋น APIํค์ ๋ฑ๋ก์ ํด์ฃผ์ด์ผ ํ๋ค.
์ด๋ฒ์๋ iOS API ์ ์ฉ ํค๋ฅผ ๋ฐ๊ธํด ๋ณด๋๋ก ํ์.
์์์ ์ํํ ์ ์ฐจ๋๋ก ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด ๋ง๋ค๊ธฐ > API ํค๋ฅผ ์ ํํ์ฌ ์๋ก์ด ํค๋ฅผ ์์ฑํ ๋ค์ ์ ์ ํ ๋ค์์ ๋ง๋ค์ด์ฃผ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ฌํญ์ iOS ์ฑ์ ์ ํํด ์ฃผ๋๋ก ํ์.
iOS๋ ์ฑ์ Bundle ID๋ฅผ ์ถ๊ฐ๋ง ํด์ฃผ๋ฉด ๋๋ค. ์ด์ ํด๋น ์๋น์ค์ Bundle ID์ ๋ฑ๋ก๋ ์ฑ๋ง API ์ ๊ทผ์ด ๊ฐ๋ฅํด ์ง๋ค.
Bundle ID๋ ํ๋ก์ ํธ์ iOS ํด๋๋ฅผ ์ฐํด๋ฆญํ์ฌ XCode("Open In Xcode")๋ฅผ ์ด์ด์ค ๋ค Signing & Capablities ํญ์ Bundle Identifier ๊ฐ์์ ํ์ธํ ์ ์๋ค.
![]() |
![]() |
์ด์ API ํค ์์ฑ ๋ฐ ๋ณดํธํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์ดํด๋ดค์ง๋ง, ์์ง ์ค์ํ ๋จ๊ณ๊ฐ ๋จ์์๋ค.
์์ฑํ API ํค๋ก ์ด๋ค GCP์ API๋ค์ ์ฌ์ฉํ ์ง๋ฅผ ์ ํํ์ฌ ํ์ฑํ ํด์ค์ผ ํ๋ค. ํ์ฌ๋ API ์ ํ์ฌํญ์ ์ค์ ํ์ง ์์๊ธฐ ๋๋ฌธ์, ๋ชจ๋ ์ ํ์ API๊ฐ ํ์ฑ๋์ด ์๋ ์ํ์ด๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก Google Maps Platform์ ํตํด ์๋์ผ๋ก API๊ฐ ์์ฑ๋๋ฉด ๊ตฌ๊ธ์ด ์ถ์ฒํ๋ Maps์ ๊ด๋ จ๋ API 31๊ฐ๋ง ์๋์ผ๋ก ํ์ฑํ ๋์ด ์๋๊ฒ ๊ธฐ๋ณธ ์ํ์ธ๋ฐ, ์ฌ์ค ์ด ์ ๋ API ๊ธฐ๋ฅ๋ ๋๋ถ๋ถ ๊ฑฐ์ ์ฌ์ฉํ์ง ์์๊ฑฐ๋ค.
ํ์ํ API๋ง ํ์ฑํ ํ๋ฉด์ ์ด๋ค ๊ธฐ๋ฅ์ ์ฌ์ฉํ ๋์ ์ด๋ค API๊ฐ ํ์ํ์ง๋ฅผ ์์๋ณด๋ฉด์ ์งํํด ๋ณด๋๋ก ํ๊ฒ ๋ค.
์์ฑ๋ ํค๋ฅผ ๋๋ฌ ์ด๋ฒ์๋ ํ๋จ์ API ์ ํ์ฌํญ ์น์ ์ผ๋ก ๋ด๋ ค๊ฐ์ "ํค ์ ํ"์ ์ ํํด ์ฃผ๋๋ก ํ์.
Select APIs๋ก ๋ฉ๋ด๋ฅผ ์ด์ด์ค ๋ค ํํฐ์ฐฝ์ maps๋ผ๊ณ ์น๋ฉด ์ง๋ ์ฌ์ฉ์ ์ํ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ SDK๊ฐ ๋์ค๊ฒ ๋๋ค.
์ฌ๊ธฐ์ ํด๋นํ๋ SDK๋ฅผ ์ ํํด ์ฃผ๋ฉด ๋๋๋ฐ, ๊ฐ ํค์ ํด๋นํ๋ Maps SDK๋ฅผ ์ ํํด์ฃผ๋ฉด ๋๋ค.
ํ๋์ ํค๋ก ์ฌ์ฉ์ ํ๋ค๋ฉด, Android, iOS๋ฅผ ๋ชจ๋ ์ ํํด ์ฃผ๋ฉด ๋๋ค.
์ ์ฅ์ ๊ผญ ๋๋ฌ์ฃผ์. ์ด์ Flutter์์ Maps SDK๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ธฐ๋ณธ ์ธํ ์ ์๋ฃ๊ฐ ๋์๋ค.
์ฐธ๊ณ ๋ก API ํค ๊ด๋ จํด์ ํท๊ฐ๋ ค ํ์๋ ๋ถ๋ค์ด ์๋๋ฐ, ํด๋น ํค์ ๋ณดํธ์กฐ์น์ Google Platform์ API ์ ํ์ ์๋ก ๋ค๋ฅธ ๊ฐ๋
์ด๋ค.
ํค๋ฅผ ๋ณดํธ ํ๋๊ฑด ํ ์ฑ ๋๋ ํ ์๋น์ค์์์ ์ ๊ทผ์ ์ ํ ํ๊ณ ์ ํ๋ ๋ณดํธ ๋ชฉ์ ์ด๊ณ , Google Platform์ API๋ฅผ ์ ํ ํ๋๊ฑด ํด๋น ํค๋ก ์ด๋ค ์๋น์ค๊ฐ ๊น์ง ํ์ฑํ ํ ์ง๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์, Maps API๋ง ์ ์ฉ์ผ๋ก ํค๋ฅผ ์ฌ์ฉ ํ์ฌ๋ ๋๊ณ ๋ค๋ฅธ Google์ ์๋น์ค๋ฅผ ํ๋์ ํค๋ก๋ง ํ๋ก์ ํธ์ ์ ์ฉํด์ ์ฌ์ฉํด๋ ๋๋ค. ์ด๊ฑด ๊ด๋ฆฌ์ ์์ญ์ด๊ธฐ ๋๋ฌธ์ ์๋น์ค, ํ ์ฑํฅ์ ๋ง๊ฒ ๊ด๋ฆฌ ๊ธฐ์ค์ ์ ์ฉํด ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ๋ฉด ๋๋ค.
google_maps_flutter | Flutter Packages
GCP์์ Google Maps ํ์ฑํ๋ฅผ ์๋ฃ ํ์ผ๋, ์ด์ Flutter์์ ๊ตฌ๊ธ ์ง๋๋ฅผ ๋์ฐ๋๋ก ํด๋ณด์.
Google Maps SDK๋ฅผ Flutter์์ ์ฝ๊ฒ ์ฌ์ฉํ๋๋ก ๋์์ฃผ๋ ํจํค์ง๋ฅผ ๋จผ์ ์ถ๊ฐํด์ฃผ์.
- ์ด ๊ธ์์๋ 2.10.1 ๋ฒ์ ์ ๊ธฐ์ค์ผ๋ก ์์ฑ๋จ
dependencies:
google_maps_flutter: <latest_version>
์ด์ Google Map์ ํธ์ถํ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ ๋ค ์ฑ์ ์คํํด๋ณด์.
GoogleMap(
initialCameraPosition: CameraPosition(
zoom: 6,
target: LatLng(37.5642135, 127.0016985),
),
),
Android, iOS ๋ชจ๋ ์๋ฌ๊ฐ ๋๋ฉด์ ์ง๋๊ฐ ๋ ธ์ถ๋์ง ์์์ ๊ฒ์ด๋ค. ์ด์ ๋ GCP์์ ์์ฑํ API ํค๋ฅผ ๋ฑ๋กํด ์ฃผ์ง ์์์์ด๋ค.
Xcode๋ฅผ ์ด๊ณ AppDelegate.swift ํ์ผ๋ก ์ด๋ํ์ฌ GoogleMaps๋ฅผ ์ํฌํธํ ๋ค ๋ค์ดํฐ๋ธ์ GMSService์ API ํค๋ฅผ ์ ๊ณตํด ์ฃผ๋ฉด ๋๋ค.
GMSServices.provideAPIKey("your_api_key")
AppDelegate ์์ ์ถ๊ฐํด์ฃผ๋๋ก ํ์.
import Flutter
import UIKit
import GoogleMaps
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("AIzaSyDFYC6Nfif0GgcvPqalITn_twppssvSu3I")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Android ํด๋์ app > src > main์ AndroidManifest.xml ํ์ผ์ ์ด์ด์ค ๋ค application ํ๊ทธ ์๋์ geo.API_KEY ๊ด๋ จ meta-data๋ฅผ ์ถ๊ฐํด ์ฃผ๋ฉด ๋๋ค.
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="your_api_key"/>
ํด๋น ํ๊ทธ๋ค ์ฌ์ด์ ์ ํํ ์ถ๊ฐํด์ผ ํ๋ค.
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="map_playground"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
...
</activity>
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyDRQ763aWsmva0QMQ-___VNeQvjwcm__b8"/>
...
</application>
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
์ด์ ๋ค์ ์คํํด๋ณด๋ฉด, Android, iOS ๋ชจ๋ ์ ์์ ์ผ๋ก ๊ตฌ๊ธ ์ง๋๊ฐ ๋ ธ์ถ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์์ฑํ API ํค๋ APIํค์ ์ ์ํด ๋ณด๋ฉด "ํค ํ์" ๋ฒํผ์ ํด๋ฆญํ์ฌ ํ์ธํ ์ ์๋ค.
๋ค์ ์ฑ์ ์คํํด๋ณด๋ฉด ์ ํํ ์์ธ์ ๊ธฐ์ค์ผ๋ก Google ์ง๋๊ฐ ์ ์์ ์ผ๋ก ์คํ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค !
iOS | Android |
---|---|
|
![]() |
๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ์ ์ํ ์ค์ ์ ์๋ฃ ๋์์ผ๋, google_maps_flutter ํจํค์ง์ ์ฌ๋ฌ ๊ธฐ๋ฅ๋ค์ ๋ํด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ๋ค๋ค๋ณด๋๋ก ํ์.
๐ฅ google_maps_flutter ๋ฒ์ ์ ๋ฐ๋ผ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ์ฐจ์ด๊ฐ ์์ ์ ์์ !
๊ฐ์ฅ ๊ธฐ๋ณธ์ธ ์ง๋๋ฅผ ๋์ด์ฃผ๋ ๊ฒ ๋ถํฐ ์์ํด๋ณด์.
GoogleMap ๊ฐ์ฒด๋ฅผ ํตํด UI์ ์ง๋๋ฅผ ๋ ธ์ถํ๊ฒ ๋๋ฉฐ, ํ์ ๊ฐ์ผ๋ก ์ด๊ธฐ ์นด๋ฉ๋ผ ํฌ์ง์ ์ ์ง์ ํด ์ฃผ์ด์ผ ํ๋ค.
CameraPosition ๊ฐ์ฒด์ ์๋/๊ฒฝ๋๋ฅผ ์์ฑํด target์ ์ง์ ํ๋ฉด ๋๋ค.
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(37.5642135, 127.0016985),
),
),
CameraPosition ๊ฐ์ฒด๋ target ์ธ์๋ zoom, tilt(๊ธฐ์ธ๊ธฐ), bearing(๋ฐฉ์๊ฐ) ํ๋๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ ์นด๋ฉ๋ผ์ ์์น ๋ฐ ๋ทฐ๋ฅผ ์กฐ์ ํ ์ ์๋ค.
zoom: 6 tilt: 0 bearing: 0 |
zoom: 6 tilt: 0 bearing: 140 |
zoom: 6 tilt: 0 bearing: 90 |
zoom: 20 tilt: 0 bearing: 0 |
zoom: 20 tilt: 45 bearing: 0 |
zoom: 20 tilt: 90 bearing: 30 |
---|---|---|---|---|---|
|
|
|
|
|
|
mapType ํ๋๋ฅผ ์ฌ์ฉํ์ฌ ์ง๋ ์ข ๋ฅ๋ฅผ ์ง์ ํ ์ ์๋ค
GoogleMap(
mapType: MapType.none,
...
),
none ํ์ ์ ์ ์ธํ๊ณ ๋ ๊ตฌ๊ธ์์ ์ ๊ณตํ๋ ์ง๋ ํ์ ์ผ๋ก ๋งต์ ์ฌ์ฉํ ์ ์๊ณ , none ํ์ ์ผ๋ก ์ง์ ์ ์ง๋๋ฅผ ๋ ธ์ถ ์ํค์ง ์์ผ๋ฉด์, tileOverlays ํ๋์ ์ปค์คํ ๋๋ ์ฌ์ฉ์ ์ ์ ํ์ผ์ ์ ๊ณตํ์ฌ ์ํ๋ ๋ทฐ๋ UI ๋ฑ์ ์ฌ์ฉํ๊ณ ์ถ์ ๋ ํ์ฉํ ์ ์๋ค.
normal - ๊ธฐ๋ณธ ์ง๋ (๋๋ก, ๊ฑด๋ฌผ, ์งํ ๋ฑ)
satellite - ์์ฑ ์ด๋ฏธ์ง ์ง๋ (๊ฑด๋ฌผ ์ค๊ณฝ ์๋ ์ค์ฌ ์ด๋ฏธ์ง)
terrain - ์งํ ์ง๋ (์ฐ, ์ธ๋ ๋ฑ ๊ณ ๋ ์ ๋ณด ํ์)
hybrid - ์์ฑ ์ง๋ + ๋๋ก ๋ฐ ์ง๋ช ์ ๋ณด
none - ์๋ฌด๊ฒ๋ ํ์ํ์ง ์์
normal | hybrid | satellite | terrain |
---|---|---|---|
|
|
|
|
์์์ ์ดํด๋ณธ tileOverlays๋ ๊ณต๊ฐ์์ ์ฌ๋ฌ ๋ ์ด์ด๋ฅผ ๊ฒน์ณ์ UI์ ์ ์ฉํ๋ ๊ธฐ๋ฅ์ธ๋ฐ, ๊ฒ์ ์ง๋๋ ๊ณ ๋ ์ง๋์ ๊ฐ์ ๋๋ง์ ์ง๋๋ฅผ ๋ณด์ฌ์ค ์๋ ์๊ณ ๊ธฐ๋ณธ ์ง๋์์ ๋ ์จ๋ ํ์ ๊ตฌ์ญ๋ฑ์ ์ ๋ณด๋ฅผ ํํํ ๋์๋ ๋ ์ด์ด๋ฅผ ๊ฒน์น๊ฒ ํด์ ๋ณด์ฌ์ค ์๋ ์๋ ๊ธฐ๋ฅ์ด๋ค. ์ฆ ๋ฐ์์ ๋ค๋ค๋ณผ style ํ๋์ฒ๋ผ UI ์ ์ธ ์์ ์ธ์๋ ์ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ๊ณ ์ ํ ๋์๋ ๋๋ฆฌ ์ฌ์ฉ๋๋ ๊ธฐ๋ฅ์ด๋ค.
์ง๋์ ์คํ์ผ์ ๋ง๋๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ style ํ๋๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ UI ์คํ์ผ์ JSON ํ์ ์ผ๋ก ์ ๊ณตํ๋ ๋ฐฉ๋ฒ์ด๋ค.
์๋ ์์๋ ๊ฐ๋จํ๊ฒ POI(Point of Interest)๋ฅผ ์ ๊ฑฐํ๋ ์คํ์ผ์ด๋ค.
GoogleMap(
...
style: '''
[
{
"featureType": "poi",
"elementType": "labels",
"stylers": [
{ "visibility": "off" }
]
}
]
''',
),
JSON์๋ featureType, elementType, stylers๋ฅผ ์ฌ์ฉํ์ฌ UI์ ์ปค์คํ ๋ช ๋ น์ ์คํํ๊ฒ ํ๋๋ฐ, ๊ตฌ๊ธ์์ ์ ๊ณตํ๋ ์คํ์ผ ๊ฐ์ด๋๋ฅผ ํตํด ํ์ธํ ์ ์๊ณ ๊ณต์ ํด์ ํตํด ์ปค์คํ ๋ฐ ์ฝ๋๋ฅผ ํ์ธํ ์ ์๋ค.
๊ฐํธํ๊ฒ ๋๋ก ์์, poi, ๋ฌผ ์์, ๊ณต์ ์จ๊ธฐ๊ธฐ, ์งํ ๊ฐ์กฐ ๋ฑ์ UI๋ฅผ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค.
style ๊ด๋ จ๋ ๋ถ๋ถ์ ๋ค๋ฅธ ๊ธ์์ ๋ ์์ธํ ๋ค๋ค๋ณด๋๋ก ํ๊ฒ ๋ค.
๊ตฌ๊ธ ์ง๋์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ UI ์์๋ค์ ๋ํด์๋ ์ดํด๋ณด๋๋ก ํ์.
myLocationButton | compass | zoomControls | mapToolbar |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |
padding ํ๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ง๋์ ๊ฐ์ฅ์๋ฆฌ ์ฌ๋ฐฑ์ ์ถ๊ฐํ์ฌ ๊ธฐ๋ณธ UI ์ปดํฌ๋ํธ๋ค์ ์ ์ฒด ์์ญ ๋ฒ์๋ฅผ ์กฐ์ ํ ์ ์์ด UI ๊ฒน์นจ์ ๋ฐฉ์งํ๊ณ ์ถ์ ๋์ ์ฌ์ฉํ ์ ์๋ค.
์ง๋์์ ์ ๊ณต๋๋ ์ ์ค์ณ ๊ธฐ๋ฅ ์ญ์ ํ์ฑํ/๋นํ์ฑํ ์ฌ๋ถ๋ฅผ ์ง์ ํ ์ ์๋ค.
fortyFiveDegreeImageryEnabled ํ๋๋ 45๋ ํญ๊ณต๋ทฐ ํ์ ์ฌ๋ถ์ธ๋ฐ, ์ด๊ฑด WEB ์ ์ฉ์ด๋ผ ๋ชจ๋ฐ์ผ์์๋ ํ์ฑํ๊ฐ ๋ถ๊ฐ๋ฅ ํ๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก 3D๋ก ๋ณด์ด๋ ๊ฑด๋ฌผ์ ํ์ ์ฌ๋ถ๋ buildingsEnabled ํ๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๊ณ , ์ค์๊ฐ ๊ตํต ์ํฉ์ ์ง๋์ ์ค๋ฒ๋ ์ด ํ๊ณ ์ถ์ ๋๋ trafficEnabled๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
indoorViewEnabled๋ผ๋ ํ๋๊ฐ ์๋๋ฐ, ์ด๊ฑด ๋ด๋ถ ์ง๋ ํ์ฑํ ์ฌ๋ถ๋ฅผ ์๋ฏธํ๋ค. ๋ชจ๋ ๊ฑด๋ฌผ์ ์ง์๋๋ ๊ฒ์ด ์๋๊ณ ํ์ฑํ์ ๋ด๋ถ ์ง๋๋ฅผ ์ ๊ณตํ ์ ์๋ ๊ฑด๋ฌผ๋ก ์ด๋ ํ๊ฒ๋๋ฉด ์์ ์ธต ์ ํ์๊ฐ ๋์ค๋ฉด์ ๋ด๋ถ๋ฅผ ์ง๋์์ ํ์ธํ ์ ์๋ค.
buildingsEnabled | indoorViewEnabled | trafficEnabled | |||
---|---|---|---|---|---|
true | false | true | false | true | false |
Android ์ ์ฉ์ผ๋ก liteModeEnabled ํ๋๋ฅผ ์ฌ์ฉํ๋ฉด, Google Maps์์ ์ํธ์์ฉ์ ์ต์ํ๋ก ํ๋ฉด์ ์ง๋๋ฅผ ์ต๋ํ ๊ฐ๋ณ๊ฒ ์ฌ์ฉํ๊ณ ์ถ์ ๋ ํ์ฉํ ์ ์๋ค.
cameraTargetBounds์ minMaxZoomPreference๋ฅผ ํ์ฉํ๋ฉด ์ง๋์ ์คํฌ๋กค ํ์ฉ ๋ฒ์์ ์ต์/์ต๋ ์ค ํ์น๋ฅผ ์กฐ์ ํ ์ ์๋ค.
CameraTargetBounds ๊ฐ์ฒด์ ๋จ์์ชฝ(southwest), ๋ถ๋์ชฝ(northeast) ์ขํ๋ฅผ ์ง์ ํ๋ฉด ํด๋น ๋ฐ์ค ์์์๋ง ์คํฌ๋กค์ด ๊ฐ๋ฅํ๋ค.
ํน์ ๊ตญ๊ฐ๋ง์ ์ ํํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ ์ ์๋ค.
cameraTargetBounds: CameraTargetBounds(
LatLngBounds(
southwest: LatLng(33.0, 124.0),
northeast: LatLng(39.5, 131.0),
),
),
MinMaxZoomPreference์ ์ต์์ ์ต๋ ์ค ๋ ๋ฒจ์ ์ง์ ํ๋ฉด ์ฌ์ฉ์์ ์ง๋๋ด ํ์น ๋ฒ์๋ฅผ ์ ํํ ์ ์๋ค.
minMaxZoomPreference: MinMaxZoomPreference(10, 16),
GoogleMap ์์ ฏ์ ๋ค์ํ ์ฌ์ฉ์ ์ํธ์์ฉ์ ๋ํ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ ๊ณตํ๋ค.
๊ทธ์ค onTap๊ณผ onLongPress๋ ์ฌ์ฉ์๊ฐ ํ๋ฉด์ ์งง๊ฒ ๋๋ ๊ธธ๊ฒ ํฐ์นํ์ ๋ ํธ์ถ๋๋ฉฐ, ํฐ์น๋ ์ง์ ์ ์์น๋ฅผ ๋ํ๋ด๋ LatLng ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
LatLng์ ์ง๋์์ ์๋(latitude)์ ๊ฒฝ๋(longitude)๋ฅผ ํฌํจํ ์ขํ ์ ๋ณด๋ก, ์ดํ ๋ง์ปค ์ถ๊ฐ, ๊ฒฝ๋ก ์์ฑ ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ์ ํ์ฉ๋ ์ ์๋ค.
GoogleMap(
onTap: (LatLng latLng) {
print("Tapped at: $latLng");
},
onLongPress: (LatLng latLng) {
print("Long pressed at: $latLng");
...
},
์ง๋ ์ด๋๊ณผ ๊ด๋ จ๋ onCameraMoveStarted, onCameraMove, onCameraIdle์ ๋ํด์ ์์๋ณด์.
์ง๋ ์ด๋(์คํฌ๋กค)์ ์์ -> ์ด๋ ์ค -> ์ข ๋ฃ๋ผ๋ ์ฐ์์ ์ธ ํ๋ฆ์ ํธ์ถํด์ฃผ๋ ์ฝ๋ฐฑ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.
onCameraMoveStarted, onCameraIdel์ ๊ฐ๊ฐ ์ด๋(์คํฌ๋กค)์ด ๋ฐ์ํ ์์๊ณผ ๋ ์ง์ ์ ํ ๋ฒ์ฉ๋ง ํธ์ถ๋๋ ์ฝ๋ฐฑ์ด๋ค.
onCameraMove๋ ์์๊ณผ ๋์ ์ฌ์ด์ธ ์ด๋ ์ค์ผ ๋์ ํธ์ถ๋๋ฉฐ, CameraPosition ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
์ฐธ๊ณ ๋ก CameraPosition์๋ bearing, tilt, zoom, target ์ ๋ณด๋ฅผ ํฌํจํ๊ณ ์๋ค.
GoogleMap(
onCameraMoveStarted: () {
print("Camera move started");
},
onCameraMove: (CameraPosition position) {
print("Camera moving to: ${position.target}");
},
onCameraIdle: () {
print("Camera idle");
},
...
),
gestureRecognizers๋ฅผ ํ์ฉํ๋ฉด ์ง๋์ ์ ์ค์ณ(ํฐ์น) ๊ฐ์ ์ํธ์์ฉ์ ์ ์ดํ ์ ์์ผ๋ฉฐ, ์น์ ์ ๊ณตํ๋ ๊ฒฝ์ฐ์๋ webGestureHandling์ด๋ผ๋ Web ์ ์ฉ ํธ๋๋ฌ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ ๋ฐฉ๋ฒ๊ณผ Google ์ง๋ ์ฌ์ฉ์ ์ํ ํ๋๋ค์ ๋ํด์ ์ดํด ๋ดค์ผ๋, ์ด์ ์ง๋๋ฅผ ํ์ฉํ์ฌ ๋ค์ํ ๊ธฐ๋ฅ๋ค์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์์๋ณด์.
์ฌ๋ฌ ์ง๋ ์ฑ์ ์ฌ์ฉํด ๋ณด๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ๋ด ์์น๋ฅผ ์ง๋์์ ํ์ํด ์ฃผ๋๋ฐ, ํ์ฌ ์ฐ๋ฆฌ๊ฐ ๋์ด ๊ตฌ๊ธ ๋งต ์์๋ ๋ด ์์น๊ฐ ํ์๋์ง ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๊ทธ๊ฑด ๋ฐ๋ก ์์น ๊ถํ์ ๋ถ์ฌ ๋ฐ์ง ๋ชปํ์๊ธฐ ๋๋ฌธ์ Google Map SDK๊ฐ ์๋์ผ๋ก GPS ์์น ์ ๋ณด๋ฅผ ๋๋ฐ์ด์ค์์ ๋ฐ์์ค์ง ๋ชปํ๊ณ ์์ด์๋ค.
์์น ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ๋๋ GCP์ Geolocation API๋ฅผ ์ฌ์ฉํด์ผ ํ๋๋ฐ, ๋คํํ ๋ชจ๋ฐ์ผ์์๋ ๋ด์ฅ GPS๋ก ์์น ์ ๋ณด๋ฅผ ์ป์ ์ ์์ด ๋น์ฉ ์์ด ๋ด ์์น๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
Dependencies
๊ถํ ๊ด๋ จ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ์ํด permission_handler๋ฅผ ์ถ๊ฐํด ์ฃผ์.
permission_handler: <latest_version>
Android
- Android > app > src > main > AndroidMenifest.xml
์์น ๊ถํ์ ์์ฒญํ๊ธฐ ์ํด AndroidMenifest ํ์ผ์ ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION ํผ๋ฏธ์ ํ๊ทธ๋ฅผ ์ถ๊ฐํ์.
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
...
/>
</manifest>
iOS
- iOS > Runner > Info.plist
์์น ๊ถํ ๋ฉ์์ง์ ์ ์ ํ ๋ด์ฉ์ ์ถ๊ฐํด์ Info.plist ํ์ผ์ ํค๋ฅผ ๋ฑ๋กํด์ฃผ์.
<key>NSLocationWhenInUseUsageDescription</key>
<string>your_request_message</string>
- iOS > Podfile
Podfile ํ๋จ์ ์๋์ ๊ฐ์ด ์์ฒญ ๊ถํ์ ์ฌ์ฉํ๋๋ก PERMISSION_LOCATION_WHENINUSE ๊ถํ์ ๋ฑ๋กํด ์ฃผ์
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
# Permission settings
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_LOCATION_WHENINUSE=1',
]
end
end
end
ํด๋น ๊ธ์ Google ์ง๋๋ฅผ ๋ค๋ฃจ๋ ๊ธ์ด๊ธฐ ๋๋ฌธ์, ํผ๋ฏธ์ ์ ๋ํ ์ค๋ช ์ ์งํํ์ง ์๊ฒ ๋ค.
๊ตฌ๊ธ ์ง๋๋ฅผ ๋ ธ์ถํ๊ธฐ ์ ์ ์ ์ ํ ๋จ๊ณ์์ ๊ถํ์ ์์ฒญํ์.
await Permission.locationWhenInUse.request();
// status.isGranted (ํ์ฉ)
์ฑ์ ๋ค์ ์คํํด ๋ณด๋ฉด, ์ ์์ ์ผ๋ก ๊ถํ์ ์์ฒญํ๊ณ ๊ตฌ๊ธ ์ง๋์ ๋ด ์์น๊ฐ ํ์๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค !
๊ตฌ๊ธ ์ง๋์์ ์ ๊ณตํ๋ ๋ด ์์น๋ ๊ถํ์ด ์์ผ๋ฉด ์๋์ผ๋ก Maps SDK๊ฐ ์์น๋ฅผ ์ง๋์ ํ์ํด์ฃผ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์, ์ขํ๋ฅผ ํ์ธํ ์๊ฐ ์๋ค.
๊ตฌ๊ธ ์ง๋๋ฅผ ์ฌ์ฉํ๋ฉด์ ๋ด ์์น ์ขํ ์ ๋ณด๊ฐ ํ์ํ๊ฑฐ๋ ๋๋ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ ๋ด ์์น ํ์ UI๊ฐ ๋ง์์ ๋ค์ง ์๋๋ค๋ฉด, ๊ฒฐ๊ตญ ๋ด ์์น๋ฅผ ์์์ผ ํ๋ค.
Flutter์์ ์์น ์ ๋ณด๋ฅผ ๋ค๋ฃจ๋ location ํจํค์ง๋ก ์ขํ ๊ฐ์ ํ์ธํด๋ณด์.
location: <latest_version>
Location์ ๋ด์ฅ ํจ์์ธ getLocation๋ง ํธ์ถํด์ฃผ๋ฉด ๋ด ํ์ฌ ์์น ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
final Location location = Location();
await location.getLocation();
location ํจํค์ง ์ธ์๋ geolocator ํจํค์ง๋ฅผ ์ฌ์ฉํด์๋ ๋ด ์์น ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
์ง๋๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ์์ ๋ฐ์์ ๋ฐ๋ผ ์ ๋ณด๋ฅผ ์ ๊ณตํ๊ฑฐ๋ ๊ธฐ๋ฅ์ ์ํํด์ผ ํ๋ค. ์ด๋ฒ์๋ ๋์์ ํ๋ก๊ทธ๋๋ฐ์ ์ผ๋ก ์ ์ดํ ์ ์๋๋ก, GoogleMapController๋ฅผ ํ์ฉํด ์ง๋๋ฅผ ์ ์ดํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด๋๋ก ํ์.
GoogleMapController๋ฅผ ์์ฑํด์ฃผ์.
onMapCreated๋ GoogleMap์ด ์ฒ์ ๋ ๋๋ง๋๊ณ ์ด๊ธฐํ๋ ๋ ํธ์ถ๋๋ ์ฝ๋ฐฑ ํจ์๋ค. ์ด ์์ ์ ์ ๊ณต๋๋ GoogleMapController ์ธ์คํด์ค๋ฅผ, ์์์ ์ ์ธํ ์ปจํธ๋กค๋ฌ ๋ณ์์ ๋๊ฒจ์ฃผ๋ฉด ์ง๋๋ฅผ ํ๋ก๊ทธ๋๋ฐ์ ์ผ๋ก ์ ์ดํ ์ ์๋ค.
GoogleMapController? _controller;
GoogleMap(
onMapCreated: (GoogleMapController controller) async {
_controller = controller;
},
...
),
Flutter์ ์กด์ฌํ๋ ๋ค์ํ ์ปจํธ๋กค๋ฌ๋ค๊ณผ ์ด๊ธฐํ ๊ณผ์ ์ ๊ฑฐ์ ์ ์ฌํ๊ธฐ ๋๋ฌธ์, ์ฌ์ฉํ๊ณ ์ดํดํ๋๋ฐ ์ด๋ ค์์ ์์ ๊ฒ์ด๋ผ ์๊ฐํ๋ค.
MapController๋ฅผ ์ฌ์ฉํ์ฌ ์ง๋๋ฅผ ์ด๋์์ผ ๋ณด์.
์ง๋๋ฅผ ์ด๋ ์ํค๋ ๋ฐฉ๋ฒ์๋ ํ ๋ฒ์ ์ฆ์ ์ด๋ํ๋ ๋ฐฉ์๊ณผ ์ ๋๋ฉ์ด์ ํจ๊ณผ๋ฅผ ์ฃผ๋ฉฐ ๋ถ๋๋ฝ๊ฒ ์ด๋ํ๋ ๋ฐฉ์์ด ์๋ค.
์ด๋ ๋ง์น ScrollController์์ jumpTo์ animateTo๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์๊ณผ ์ ์ฌํ๋ค. ์ฆ, ์ ๋๋ฉ์ด์ ์ ๋ฌด์ ์ฐจ์ด์ผ ๋ฟ ๊ธฐ๋ฅ์ ๋์ผํ๋ค.
MapController์์๋ moveCamera, animateCamera๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
_controller?.moveCamera(cameraUpdate);
_controller?.animateCamera(cameraUpdate);
๊ณตํต์ ์ผ๋ก CameraUpdate๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ํ ์์น, ์ค ๋ ๋ฒจ ๋๋ ๋ณด์ฌ์ค ๋ฒ์(LatLngBounds) ๋ฑ์ ์ง์ ํ ์ ์๋ค.
CameraUpdate์ newLatLng ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ์ํ๋ ์ขํ๋ก ์ด๋ํ๋ฉด์ ์ค ๋ ๋ฒจ์ ํ์ฌ ์์ค์ ์ ์งํ๋ฉด์ ์ด๋์ํค๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ฉด ๋๋ค.
CameraUpdate.newLatLng(LatLng(latitude, longitude)),
์ด๋ฒ์๋ ์ขํ ์ด๋์ ํ์ง ์๊ณ , ์ค ๋ ๋ฒจ๋ง ์กฐ์ ํ๊ณ ์ถ๋ค๋ฉด zoomBy, zoomTo, zoomIn, zoomOut์ ํ์ฉํ๋ฉด ๋๋๋ฐ, ๊ฐ๊ฐ์ ๊ธฐ๋ฅ์๋ ๋ฏธ๋ฌํ ์ฐจ์ด๊ฐ ์์ผ๋ ์ ์ ํ๊ฒ ์ฌ์ฉํ์ ์ผ ํ๋ค.
๊ธฐ๋ณธ์ ์ธ ๋ด์ฅ ํจ์๋ฅผ ์ฌ์ฉํด์ ๊ฐํธํ๊ฒ ๊ตฌํํ๋ ค๋ฉด zoomIn, zoomOut์ ํธ์ถํด์ ์ฌ์ฉํ ์ ์๋ค. ์ด๋ ํจํค์ง ์์ฒด์์ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ๋ผ๊ณ ๋ง๋ค์ด ๋์ ํจ์์ด๊ณ , ์ค๋ช ์ ๋ณด๋ฉด zoomBy(ยฑ1)์ ๋์ผํ ๊ธฐ๋ฅ์ด๋ผ๊ณ ์๋ดํ๊ณ ์๋ค.
๊ทธ๋ ๋ค๋ฉด zoomBy๋ ์ด๋ค ๊ธฐ๋ฅ์ธ๊ฑธ๊น? ๋ฐ๋ก zoom์ ์๋์ ์ผ๋ก ์ฆ๊ฐ ๋๋ ๊ฐ์์ํค๋ ๊ฒ์ผ๋ก ํ์ฌ ์ค ๋ ๋ฒจ์ ๋น๋กํด์ ์๋ํ๊ฒ ๋๋ค.
zoomBy(3) ์ด๋ผ๋ฉด ํ์ฌ ์ค ๋ ๋ฒจ์ 3๋งํผ ํ๋๋๋ค๋ ์๋ฏธ์ด๋ค. ๋ฐ๋๋ก zoomBy(-1)์ ํธ์ถํ๊ฒ ๋๋ฉด ํ์ฌ ์ค ๋ ๋ฒจ์์ -1๋งํผ๋ง ์ถ์๋๋ค๋ ์๋ฏธ๊ฐ ๋๋ค.
๊ฒฐ๊ตญ zoomIn, zoomOut์ ํ์ฌ ์ค์์ ยฑ1๋งํผ ํ๋/์ถ์ํ๋ ๋ด์ฅ ํจ์์ธ ๊ฒ์ด๋ค.
zoomTo๋ ์ ๋์ ์ค ๋ ๋ฒจ์ ์ง์ ํ๋ ๊ฒ์ผ๋ก, ํ์ฌ ์ค ๋ ๋ฒจ๊ณผ ์๊ด์์ด ํน์ ์ค ๋ ๋ฒจ๋ก ๋ฐ๋ก ํ๋/์ถ์๋๋ค.
In & Out | zoomBy(+2/-4) | zoomTo(+20/-2) | |||
---|---|---|---|---|---|
jumpTo | animateTo | jumpTo | animateTo | jumpTo | animateTo |
- zoomIn & zoomOut
controller?.moveCamera(CameraUpdate.zoomIn());
controller?.animateCamera(CameraUpdate.zoomIn());
controller?.moveCamera(CameraUpdate.zoomOut());
controller?.animateCamera(CameraUpdate.zoomOut());
- zoomBy(by: number)
controller?.moveCamera(CameraUpdate.zoomBy(by));
controller?.animateCamera(CameraUpdate.zoomBy(by));
- zoomTo(to: number)
controller?.moveCamera(CameraUpdate.zoomTo(to));
controller?.animateCamera(CameraUpdate.zoomTo(to));
์ค ๋ ๋ฒจ์ ์ ์งํ๋ฉด์ ํฌ์ง์ ์ ์ด๋์ํฌ ๋์ CameraUpdate.newLatLng(position: LatLng) ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ๋๋ค๊ณ ํ๋๋ฐ, ๊ทธ๋ ๋ค๋ฉด ์ค ๋ ๋ฒจ์ ์ง์ ํ๋ฉด์ ํฌ์ง์ ์ ์ด๋์ํค๊ณ ์ถ๋ค๋ฉด ์ด๋ค ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์์๊น ?
CameraUpdate.newLatLngZoom ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ค ๋ ๋ฒจ๊ณผ ํฌ์ง์ ์ ๋ ๋ค ์ง์ ํ ์ ์๋ค. ์ด ๊ฒฝ์ฐ ํฌ์ง์ ๊ณผ ์ค ๋ชจ๋ ํ์์ ์ผ๋ก ์ง์ ํด์ผ ํ๋ค.
_controller?.moveCamera(CameraUpdate.newLatLngZoom(position, zoom));
_controller?.animateCamera(CameraUpdate.newLatLngZoom(position, zoom));
์ถ๊ฐ๋ก newCameraPosition์ด๋ผ๋ ํจ์๊ฐ ์กด์ฌํ๋๋ฐ, ์ผํ๋ณด๋ฉด newLatLngZoom๊ณผ ๋น์ทํด ๋ณด์ด์ง๋ง, ํฌ์ง์ ์ ์ขํ ๊ฐ์ ์ ๋ฌํ๋ ๊ฒ์ด ์๋ CameraPosition ์์ฒด๋ฅผ ์๋กญ๊ฒ ์์ฑํด์ ์ ์ฉํ ์ ์๊ฒ ํด์ค๋ค. ์ฆ, ์ด๊ธฐ GoogleMap ๊ฐ์ฒด์ ์ง์ ํ initialCameraPosition ํ๋์ ๊ฐ์ ์๋กญ๊ฒ ๋ง๋ค ์ ์์ผ๋ฏ๋ก bearing, tilt, zoom, target์ ๋ชจ๋ ์ปจํธ๋กค์ด ๊ฐ๋ฅํ๋ค.
CameraUpdate.newCameraPosition(CameraPosition(
target: position,
zoom: zoom,
bearing: bearing,
tilt: tilt
),
);
ํฌ์ง์ ๊ณผ ์ค ๋ ๋ฒจ์ ์ปจํธ๋กคํ ์ ์์ง๋ง, ์ง๋๋ฅผ ์ฌ์ฉํ๋ ํน์ ์ฑ๋ค์ ๊ฒฝ์ฐ ๋จ์ํ ํฌ์ง์ , ์ค์ ์ปจํธ๋กค ํด์ฃผ๋ ๊ฒ์ด ์๋ ์ ํํ ๋ฒ์ ๋ด์ ๋ทฐ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค. ์ด๋ฐ ๊ธฐ๋ฅ์ newLatLngBounds ํจ์๋ฅผ ์ฌ์ฉํด ๋จ์์ชฝ, ๋ถ๋์ชฝ ์ขํ์ ๋ฒ์ ๋ด์ ์๋์ผ๋ก ํฌ์ง์ ์ ์ด๋์์ผ ์ ํํ ๋ฒ์๋ฅผ ๋ณด์ฌ์ค ์ ์๊ฒ ๋๋ค.
final LatLngBounds bounds = LatLngBounds(
southwest: const LatLng(34.0, 126.0),
northeast: const LatLng(38.0, 130.0),
);
controller?.moveCamera(CameraUpdate.newLatLngBounds(bounds, zoom));
controller?.animateCamera(CameraUpdate.newLatLngBounds(bounds, zoom));
LatLng | LatLngZoom | ||
---|---|---|---|
jumpTo | animateTo | jumpTo | animateTo |
![]() |
![]() |
![]() |
![]() |
LatLngBounds | newCameraPosition | ||
---|---|---|---|
jumpTo | animateTo | jumpTo | animateTo |
![]() |
![]() |
![]() |
![]() |
์ง๊ธ๊น์ง๋ ํฌ์ง์ ์ ์ด๋์ํฌ ๋์ ์ง๋์ ์ขํ๋ฅผ ์ฌ์ฉํด ์ง๋๋ฅผ ์์ง์ด๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ดค๋๋ฐ, ๋๋ฐ์ด์ค์ ๋ฌผ๋ฆฌ์ ์์น๋ก ์ง๋๋ฅผ ์ด๋์์ผ์ผ ํ๋ ๊ฒฝ์ฐ๋ ๋ฐ์ํ๋ค.
๋คํํ CameraUpdate์ scrollBy ํจ์๋ง ์ฌ์ฉํ๋ฉด ์์ฝ๊ฒ ๋ฌผ๋ฆฌ์ ์์น๋ก์ ์ด๋์ด ๊ฐ๋ฅํ๋ค.
scrollBy๋ฅผ ์ฌ์ฉํด x์ถ, y์ถ์ ์ด๋ํ๊ณ ์ ํ๋ ๋ฒ์๋ฅผ ์ง์ ํ๋ฉด ๋๋๋ฐ, ์ฌ๊ธฐ์ x์ถ๊ณผ y์ถ์ ํ์ฌ ์์น์์ ์ผ๋งํผ์ ํฝ์ ์ ์์ง์ผ์ง๋ฅผ ๊ฒฐ์ ํด์ฃผ๋ฉด ๋๋ค.
๋๋ฐ์ด์ค์ ๊ฐ๋ก์ฌ์ด์ฆ๊ฐ 400์ธ ๊ฒฝ์ฐ x์ 200์ ๋ฃ์ด์ฃผ๊ฒ ๋๋ฉด, ์ ํํ ํ์ฌ ๋ณด๊ณ ์๋ ๋ฌผ๋ฆฌ์ ๋ทฐ์ 200 ํฝ์ ๋งํผ ์์ง์ด๊ฒ ๋๋ค.
controller?.moveCamera(CameraUpdate.scrollBy(x, y));
controller?.animateCamera(CameraUpdate.scrollBy(x, y));
jumpTo | animateTo |
---|---|
![]() |
![]() |
MapController์ moveCamera, animateCamera๋ก ํฌ์ง์ ์ ์ด๋ํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ๋ชจ๋ ์์๋ดค๋ค. ์๊ฐ๋ณด๋ค ์ฝ๊ฒ ์ง๋๋ฅผ ์ปจํธ๋กคํ ์ ์๊ฒ ๋์๋ค !
์ถ๊ฐ๋ก MapController์๋ ์ด๋ค ๊ธฐ๋ฅ๋ค์ด ์๋์ง ๊ณ์ํด์ ์์๋ณด๋๋ก ํ์.
MapController๋ GoogleMap์ ์ฐ๊ฒฐ๋ ์ปจํธ๋กค๋ฌ๊ธฐ ๋๋ฌธ์ ๋น์ฐํ ๋ค์ํ ์ ๋ณด๋ค๋ ์ ๊ณต ๋ฐ์ ์ ์๋ค.
๋ํ์ ์ผ๋ก getLatLng, getScreenCoordinate, getVisibleResion์ ๋ํด์ ์ดํด๋ณด๋๋ก ํ์.
์ ํจ์๋ ๋ชจ๋ ๋น๋๊ธฐ์ ์ผ๋ก ์๋๋๋ฉฐ, ์ฐ๋ฆฌ๊ฐ ์์ ๋ค๋ค๋ ์ปจํธ๋กค๋ฌ ๋ฉ์๋๋ค๊ณผ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ง๋์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค.
getLatLng์๋ ํ๋ฉด ์ขํ๊ณ(ScreenCoordinate)๋ฅผ ์ง๋ ์ขํ๊ณ(LatLng)๋ก ๋ณํํด์ฃผ๋ ๊ธฐ๋ฅ์ผ๋ก ๋๋ฐ์ด์ค์ ๋ฌผ๋ฆฌ์ x, y์์น๊ฐ ์ง๋์์ ์ด๋ ์๋/๊ฒฝ๋์ธ์ง๋ฅผ ์๋ ค์ค๋ค.
getScreenCoordinate๋ getLatLng์๋ ๋ฐ๋๋ก ์๋/๊ฒฝ๋ ์ขํ๋ฅผ ๋๋ฐ์ด์ค์ ๋ฌผ๋ฆฌ์ ํฝ์ ๋ก ๋ณํํ์ฌ ๋ง์ปค๋ ์ปค์คํ ์์ ฏ์ ์ ํํ ํ๋ฉด ์์น์ Overlay ํ๊ณ ์ถ์ ๋ ์ ์ฉํ๊ฒ ํ์ฉํ ์ ์๋ค.
getVisibleResion์ ํ์ฌ ๋๋ฐ์ด์ค ํ๋ฉด์์ ๋ณด์ฌ์ง๊ณ ์๋ ์ง๋์ ๋จ์/๋ถ๋ ์ขํ ์ ๋ณด์ธ LatLngBounds ํํ๋ก ์ค์ ๋ ๋๋ง ๋์ด์ง๊ณ ์๋ ์ง๋ ์ขํ๋ฅผ ์๋ ค์ฃผ๋ฏ๋ก, ๋ถํ์ํ ๋ ๋๋ง์ด๋ UI ์ ์ด ๋ฑ ์ต์ ํ๊ฐ ํ์ํ ์์ ์ ํ์ฉํ๊ธฐ์ ์ ์ฉํ ๊ธฐ๋ฅ์ด๋ค.
await controller?.getLatLng(ScreenCoordinate(x: x, y: y))
await controller?.getScreenCoordinate(LatLng(latitude, longitude))
await controller?.getVisibleRegion();
์ง๋์ ์ค ๋ ๋ฒจ์ ์๊ณ ์ถ๋ค๋ฉด, getZoomLevel์ ํธ์ถํ์ฌ ํ์ธํ ์ ์๋ค.
await controller?.getZoomLevel();
์ปค์คํ ํ์ผ๋ก ์ง๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํ์ผ์ ๋ณ๊ฒฝ ์ฌํญ์ ์ ์ฉํ๊ธฐ ์ํด ์บ์ฑ์ ์ง์์ฃผ์ด์ผ ๋ณ๊ฒฝ๋ ํ์ผ์ ์ ์ฉํ ์ ์๋๋ฐ, clearTileCache(tileOverlayId)๋ฅผ ํธ์ถํ์ฌ ์ด์ ํ์ผ์ ํด๋ฆฌ์ดํ ์ ์๋ค.
๋ง์ปค๋ฅผ ์ ์ดํ ์ ์๋ ๊ธฐ๋ฅ๋ค๋ ์ ๊ณตํ๋๋ฐ, ์์ง ๋ง์ปค์ ๋ํด์ ์ ๋๋ก ๋ฐฐ์ฐ์ง ์์์ผ๋ ์ด ๋ถ๋ถ์ ๋ง์ปค ์ฌ์ฉ๋ฒ์ ์์๋ณด๋ฉด์ ๋ค๋ค๋ณด๋๋ก ํ์.
๋จ์ํ ์ง๋๋ง ๋ณด์ฌ์ฃผ๋ ์๋น์ค๋ผ๋ฉด ์ง๊ธ๊น์ง ์์๋ณธ ์ฌ์ฉ๋ฒ์ผ๋ก๋ ์ถฉ๋ถํ ์๋น์ค๋ฅผ ๊ฐ๋ฐํ๊ณ ์ด์ํ ์ ์์ ๊ฒ์ด๋ค.
ํ์ง๋ง ์ฌ์ฉ์๊ฐ ์ํ๋ ์์น์ Marker(๋ง์ปค)๋ฅผ ๋ฐฐ์นํ๊ณ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ธฐ๋ฅ์ ํ์ฅํ๊ณ ์ ํ๋ค๋ฉด, ๋ง์ปค๋ฅผ ๋์ ์ผ๋ก ์ถ๊ฐํ๊ณ ์ ์ดํ๋ ๋ฐฉ๋ฒ์ ์์์ผ ํ๋ค.
์์ ์ง๋์ ํ์๋ ๊ฒ์ด ๋ฐ๋ก Google Map์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํด์ฃผ๋ ๋ง์ปค์ด๋ค. ์ผ๋ถ UI ์์ ์ ๊ฐ๋ฅํ์ง๋ง ๊ธฐ๋ณธ UI๊ฐ ๋ง์์ ๋ค์ง ์๋๋ค๋ฉด ๋น์ฐํ ์ปค์คํ ๋ ๊ฐ๋ฅํ๋ค.
๋ณธ๊ฒฉ์ ์ผ๋ก Marker(๋ง์ปค)๋ฅผ ์ง๋ ๊ณต๊ฐ์์ ๋ ธ์ถ์ํค๊ณ ์ ์ดํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์.
GoogleMap ํ๋๋ฅผ ๋ณด๋ฉด markers๊ฐ ์๋๋ฐ, ํ์ ์ ๋ณด๋ฉด Set๋ก ๋์ด ์๋ ๊ฒ์ ์ ์ ์๋ค.
์ List๊ฐ ์๋ Set์ผ๊น ? ๋ง์ปค๋ ๋ฐ๋์ ๊ณ ์ ํ markerId๋ฅผ ๊ฐ์ ธ์ผ ํ๋๋ฐ, List์๋ค๋ฉด ์ค์๋ก ์ค๋ณต๋ ID๋ก ๋ง์ปค๋ฅผ ์ถ๊ฐํด๋ ๋ง์ ๋ฐฉ๋ฒ์ด ์๊ณ , List์ ๋นํด Set์ contains, add, remove ๋ฑ์ ์ฐ์ฐ์ด ๋น ๋ฅด๋ค๊ณ ์๋ ค์ ธ ์๋ค.
GoogleMap(
markers: {
...markers
}
)
Marker๋ ํ์๋ก ๊ณ ์ ํ ID์ธ markerId์ ์ง๋ ์ขํ๊ณ์ธ position์ ์ ๋ฌํด์ผ ํ๋ค.
Marker(
markerId: MarkerId(uniqueId),
position: LatLng(latitude, longitude)
)
๋ง์ผ ์ค๋ณต๋ ID๋ก markerId๊ฐ ์ฌ๋ฌ๊ฐ ํฌํจ๋ ๊ฒฝ์ฐ Set ํ์ ์ ์ํด ๋ฆ๊ฒ ๋ค์ด์จ id๊ฐ ์์ ์์ฑ๋ id๋ฅผ ๋ฎ์ด์ฐ๊ธฐ ๋๋ฌธ์, ๊ฒฐ๊ตญ ๊ฐ์ฅ ๋ง์ง๋ง์ผ๋ก ์ ์ธ๋ markerId๋ง ๋จ๊ฒ ๋๋ค.
Marker๋ฅผ ์ถ๊ฐํ์ฌ ๋ง์ปค๋ฅผ ํญํด๋ณด๋ฉด, ์๋์ผ๋ก ํฌ์ง์ ์ด ์ด๋ํ๋ ๊ฒ์ ํ์ธํ ์ ์๋๋ฐ ์ด๊ฑด ๋ด์ฅ๋ ๊ธฐ๋ฅ์ผ๋ก ์ต์ ์ ํตํด ์ ์ด๊ฐ ๊ฐ๋ฅํ๋ค.
infoWindow ํ๋์ InfoWindow๋ฅผ ์ฌ์ฉํ์ฌ ๋ง์ปค๊ฐ ํญํ์ ๋์, ๋ณด์ฌ์ฃผ๋ ์ ๋ณด์ฐฝ์ ๋ ธ์ถ์ํฌ ์ ์๋ค.
title, snippet ํ๋์ ํญ์ ๋ช ์นญ๊ณผ ์งง์ ์ค๋ช ์ ์ถ๊ฐํ ์ ์๊ณ , anchor๋ก ์คํ์ ์กฐ์ ์ด ๊ฐ๋ฅํ๋ค. ๋ํ ๋ง์ปค๊ฐ ํญํ์ ๋์ ๋ํ ์ฝ๋ฐฑ๋ ์ฌ์ฉํ ์ ์๋ค.
infoWindow: InfoWindow(
title: "NYC",
snippet: "New York City",
anchor: const Offset(0.5, 0),
onTap: () {},
)
๋ง์ปค์ ๊ธฐ๋ณธ ์์ด์ฝ์ ๋จ์ํ ๋นจ๊ฐ์์ด์ง๋ง, ๊ฐ๋จํ๊ฒ ์์์ ๋ณ๊ฒฝํ ์ ์๋ค.
BitmapDescriptor์ defaultMarkerWithHue(hue) ๋ฉ์๋์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณต๋๋ ์์กฐ(Hue)๋ฅผ ๋๊ฒจ์ฃผ๋ฉด ๋๋ค.
์ฌ๊ธฐ์ Hue๋ ์์กฐ๋ฅผ ์๋ฏธํ๋ฉฐ, ์์ํ(Color Wheel) ์์์์ ๊ฐ๋(0ยฐ~360ยฐ)๋ก ํํ๋๋ค.
๋ฏธ๋ฆฌ ์ง์ ๋ hueRed(0.0), hueOrange(30.0), hueYellow(60.0), hueGreen(120.0), hueCyan(180.0), hueBlue(240.0), hueViolet(270.0), hueMagenta(300.0), hueRose(330.0)๋ฅผ ์ฌ์ฉํ์ฌ๋ ๋๊ณ , ์ซ์๋ฅผ ์ง์ ๋ฃ์ด์ฃผ๋ฉด ์์ํ์ ๋ง๋ ์์กฐ ๊ฐ์ผ๋ก ๋ณํ๊ฒ ๋๋ค.
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueAzure,
),
icon: BitmapDescriptor.defaultMarkerWithHue(35),
ratation์ ๋ง์ปค๋ฅผ ํ์ ์ํค๋ ๊ฐ๋์ด๊ณ , alpha๋ ํฌ๋ช ๋๋ฅผ ์กฐ์ ํ๊ฒ ๋๋ค. flat์ ๋๋ ํจ๊ณผ๋ฅผ ์ง์ ํ๋ ๊ฒ์ผ๋ก, ์นด๋ฉ๋ผ ๊ฐ๋์ rotation์ ์ค์ ํ์ฌ ์ง๋ ๋ฐฉํฅ์ ๋ง๊ฒ ๋ณด์ฌ์ค ์ ์๋ค.
๋ง์ปค์์๋ infoWindow์ ๋์ผํ๊ฒ anchor๋ก ์คํ์ ์กฐ์ ์ ํ์ฌ ์ธ๋ฐํ๊ฒ ์์น๋ฅผ ์กฐ์ ํ๋๋ฐ ์ฌ์ฉํ๋ฉด ๋๋ค.
zIndex๋ double ํ์ ์ผ๋ก ์ง๋ ์์ ์ฌ๋ฌ ๋ง์ปค๊ฐ ์ค๋ฒ๋ ์ด ๋๋ ๊ฒฝ์ฐ ์ด๋ค ๋ง์ปค๋ฅผ ๋ ์์ ๋ณด์ด๊ฒ ํ ์ง๋ฅผ ๊ฒฐ์ ํ๋ ๊ฐ์ด๋ค. ํน์ ๋ง์ปค๋ค์ ๋ํ๊ณ ์ถ๊ฑฐ๋ ๊ท์น์ ์ํด ๋ ์์ ๋ณด์ด๊ฒ ํ ๋ง์ปค๋ฅผ ์ง์ ํ๊ณ ์ถ์ ๋ ๊ฐ ๋ง์ปค๋ง๋ค ์ ์ ํ ๊ฐ์ ์ธํ ํ์ฌ ์ฌ์ฉํ๋ฉด ๋๋ค.
infoWindow | icon | alpha | rotation | flat |
---|---|---|---|---|
![]() |
๋ง์ปค์ ๋ํ ์ฝ๋ฐฑ์ผ๋ก๋ ํญ ํ์ ๋์ onTap, ๊ธธ๊ฒ ํญํ๋ฉด ๋๋๊ทธ ๊ธฐ๋ฅ์ด ํ์ฑํ ๋๋ฉด์ onDragStart๊ฐ ํธ์ถ๋๊ณ , ๋๋๊ทธ ์ค์ธ ๊ฒฝ์ฐ onDrag, ํญ์ ๋์์ ๋์ onDragEnd์ ์ฝ๋ฐฑ ํจ์๊ฐ ์๋ํ๋ค. ๋๋๊ทธ์ ๋ํ ์ฝ๋ฐฑ์๋ ์ง๋ ์ขํ๊ณ ์ ๋ณด๊ฐ ์ ๊ณต๋๋ค.
๋๋๊ทธ ๊ธฐ๋ฅ์ ๋นํ์ฑํ ํ๊ณ ์ถ๋ค๋ฉด draggable๋ฅผ false๋ก ์ค์ ํ๋ฉด ๋ง์ปค์ ๋ํ ๋๋๊ทธ๊ฐ ์๋ํ์ง ์๋๋ค.
์์ ๋ง์ปค์ ๊ธฐ๋ณธ ์์ด์ฝ์ ๋ํ ์์ ๋ณ๊ฒฝ์ ๊ดํด์ ์์๋ดค๋๋ฐ, ๊ธฐ๋ณธ ์์ด์ฝ์ด ์๋ ์ปค์คํ ์์ด์ฝ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด์๋ ์์๋ณด๋๋ก ํ๊ฒ ๋ค.
๋ง์ปค๋ฅผ ์ปค์คํ ํ๊ฒ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์๋ ๋์์ธ๋ ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ ์๋ ์๊ณ , Flutter์์ ์์ฑํ ์์ ฏ์ ์ฌ์ฉํ ์๋ ์๋ค.
asset์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ BitmapDescriptor ํ์ ์ผ๋ก ํ๋ก์ ํธ ๋ด์ ํฌํจ๋ ์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
๋น๋๊ธฐ์ ์ผ๋ก asset์ ๋ง๋ค์ด์ผํ๊ธฐ ๋๋ฌธ์, ์ง์ ์ฌ์ฉํ์๋ฉด ์๋๊ณ ์์ฑ๋ BitmapDescriptor๋ฅผ ์ฌ์ฉํ์ฌ์ผ ํ๋ค.
BitmapDescriptor? _bikeIcon;
_bikeIcon = await BitmapDescriptor.asset(
createLocalImageConfiguration(context),
'assets/images/bike.png',
width: 64,
height: 64,
);
Marker(
markerId: const MarkerId("1"),
position: const LatLng(40.7128, -74.0059),
icon: _bikeIcon ?? BitmapDescriptor.defaultMarker,
),
๋คํธ์ํฌ ์ด๋ฏธ์ง๋ ์ด๋ป๊ฒ ์ฌ์ฉํด์ผ ํ ๊น ? ์ฌ๊ธฐ์๋ถํฐ ์กฐ๊ธ ๋ณต์กํด์ง๋๋ฐ, ๋คํธ์ํฌ ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ฐ์ ๋ฐ์ดํธ ํํ(Uint8List)๋ก ๋ณํํ ๋ค BitmapDescriptor์ asset์ด ์๋ bytes ๋ด์ฅ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
๋คํธ์ํฌ ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ฐ๊ธฐ ์ํด http ํจํค์ง๋ฅผ ์ถ๊ฐํด ์ฃผ์.
dependencies:
http: <latest_version>
๋ง์ปค์ ์ฌ์ฉํ ๋คํธ์ํฌ ์ด๋ฏธ์ง URL์ ์ถ๊ฐํ๊ณ , ๋ค์ด๋ก๋ ๋ฐ์ ๋ค Uint8List ํ์ ์ BitmapDescriptor๋ก ๋ณํํ๋ ์ฝ๋์ด๋ค.
Future<BitmapDescriptor> getNetworkMarkerIcon() async {
final http.Response response = await http.get(Uri.parse(imageUrl));
if (response.statusCode != 200) {
throw Exception("Failed to load image.");
}
final Uint8List imageBytes = response.bodyBytes;
final ui.Codec codec = await ui.instantiateImageCodec(
imageBytes,
targetWidth: 100,
targetHeight: 100,
);
final ui.FrameInfo frameInfo = await codec.getNextFrame();
final ByteData? byteData =
await frameInfo.image.toByteData(format: ui.ImageByteFormat.png);
if (byteData == null) return BitmapDescriptor.defaultMarker;
return BitmapDescriptor.bytes(byteData.buffer.asUint8List());
}
Flutter์์ ๋ ๋๋งํ๋ ์์ ฏ(Widget)์ ์ด๋ป๊ฒ ์ปค์คํ ๋ง์ปค๋ก ์ฌ์ฉํ ๊น ?
์ง์ ๋ง๋ ์์ ฏ์ Google Maps์ ๋ง์ปค๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๊ฐ๋ณด๋ค ๋จ์ํ์ง๋ ์๋ค. ๋ง์ปค๋ ๊ธฐ๋ณธ์ ์ผ๋ก BitmapDescriptorํํ์ ์ด๋ฏธ์ง๋ง ์์ด์ฝ์ผ๋ก ํ์ฉํ๊ธฐ ๋๋ฌธ์, ์์ ฏ์ ๊ทธ๋๋ก ์ฌ์ฉํ๊ธฐ๋ ์ด๋ ต๋ค.
์ด๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ์ปค์คํ ์์ ฏ์ ์ด๋ฏธ์ง๋ก ๋ ๋๋งํ ๋ค, ๋ฐ์ดํธ ํํ๋ก ๋ณํํ๋ ๊ณผ์ ์ ๊ฑฐ์ณ์ผ ํ๋๋ฐ, ํ๋ฉด์ ์บก์ณํ ๋์ ์ฌ์ฉ๋๋ RepaintBoundary ์์ ฏ์ผ๋ก ์์ฑํ์ฌ ๋ ๋๋ง์ด ์๋ฃ๋ ์์ ฏ์ ์ด๋ฏธ์ง๋ก ์บก์ฒํ์ฌ ๋ง์ปค ์์ด์ฝ์ผ๋ก ์ฌ์ฉํ๋ฉด ๋งํ์ ํํ, ์ฌ์ฉ์ ํ๋กํ, ํ ์คํธ๊ฐ ํฌํจ๋ ๋ค์ํ ๋์์ธ ๋ง์ปค๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ค.
๋จผ์ ์ฌ์ฉํ๊ณ ์ ํ๋ UI๋ฅผ ์์ ฏ์ผ๋ก ๋ถ๋ฆฌํ ๋ค, ๊ตฌ๊ธ ์ง๋๊ฐ ๋ ๋๋ง ๋๋ ํ๋ฉด์ ๋ณด์ด์ง ์๋ ์์ญ์ผ๋ก ๋ฐฐ์น์์ผ ์ฃผ์. Stack์ ์ฌ์ฉํด์ ๊ตฌ๊ธ ์ง๋ ์๋์ ๋ฐฐ์น์์ผ๋ ๋๋ค.
final GlobalKey _markerKey = GlobalKey();
Positioned(
top: -9999,
left: -9999,
child: RepaintBoundary(
key: _markerKey,
child: const CustomMarkerWidget(),
),
),
RepaintBoundary ์์ ฏ์ GlobalKey๋ฅผ ์ ๋ฌํ์ฌ, ๋ ๋๋ง ํ ์์ ฏ์ ์ด๋ฏธ์ง๋ก ์์ฑํ์ฌ Uint8List ํ์ ์ BitmapDescriptor๋ก ๋ณํํด์ฃผ๋ฉด ๋๋ค.
์ฌ์ค ์์ ์ดํด๋ณธ ๋คํธ์ํฌ ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์๊ณผ ๊ฑฐ์ ๋์ผํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค. ๋คํธ์ํฌ ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ฐ์ ์ฒ๋ฆฌํ๋๋, ์์ ฏ ์์ฒด๋ฅผ ์ด๋ฏธ์ง๋ก ์์ฑํ๋๋์ ๋ฐฉ์๋ง ๋ค๋ฅผ ๋ฟ ๋์ผํ๊ฒ bytes ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
Future<BitmapDescriptor> getMarkerWidgetIcon(GlobalKey key) async {
final RenderRepaintBoundary boundary =
key.currentContext!.findRenderObject() as RenderRepaintBoundary;
final ui.Image image = await boundary.toImage(pixelRatio: 3.0);
final ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
if (byteData == null) return BitmapDescriptor.defaultMarker;
final Uint8List markerIcon = byteData.buffer.asUint8List();
return BitmapDescriptor.bytes(markerIcon);
}
์์ ฏ์ ์ด๊ธฐ initState์์ ํธ์ถ์ ์ฃผ์ํ ์ ์ด ๋ ๋๋ง์ด ์๋ฃ๋ ํ ํธ์ถ ๋์ด์ผ ํ๋ค๋ ์ ์ด๋ค. ๋ ๋๋ง์ด ์๋ฃ๋๋ ์์ ์ ํ๋ ์์ ๋๋ ์ด ์ฃผ๊ณ ํธ์ถํด์ฃผ๋ฉด ๋๋ค.
void initState() {
super.initState();
_loadWidgetIcon();
}
Future<void> _loadWidgetIcon() async {
WidgetsBinding.instance.addPostFrameCallback((_) async {
await Future.delayed(const Duration(milliseconds: 50));
_widgetIcon = await GoogleMapHelper.getMarkerWidgetIcon(_markerKey);
});
}
์ปค์คํ ๋ง์ปค๋ฅผ ๋ง๋ค ๋๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ํ์์ ์ด๊ธฐ ๋๋ฌธ์, ๋ ๋๋ง ์ง์ฐ์ด๋ ๋๋ ์ด๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ๋๋ค. ๋ฐ๋ผ์ ์ฌ์ ์ ๋ ๋๋งํ ์ด๋ฏธ์ง๋ฅผ ์บ์ฑํ๊ฑฐ๋, ์ด๊ธฐํ ๋จ๊ณ์์ ๋ฏธ๋ฆฌ ์์ฑํด๋๋ ๋ฑ์ ์ต์ ํ ์ ๋ต์ด ์ค์ํ๋ค.
์ด ๊ธ์์๋ ์ปค์คํ ๋ง์ปค ์์ฑ ๋ฐฉ๋ฒ์ ํต์ฌ๋ง ๊ฐ๋จํ ๊ตฌํํ์ง๋ง, ์ค์ ์๋น์ค ํ๊ฒฝ์์๋ ๋ง์ปค๊ฐ ์ฌ๋ฌ ๊ฐ์ผ ๊ฒฝ์ฐ์๋ ํฐ ๋ฌธ์ ๊ฐ ์์ ์๋ ์์ด๋, ์ง์์ ์ผ๋ก ๋ฐ๋ณต ์์ฑํ๋ ๊ตฌ์กฐ๋ ๋ถํ์ํ ๋ฆฌ์์ค ๋ญ๋น๋ก ์ด์ด์ง ์ ์๋ค. ๋ฐ๋ผ์ ์ปค์คํ ๋ง์ปค๋ฅผ ๋์ ํ ๋์๋ ์ฑ๋ฅ๊ณผ ์ ์ฐ์ฑ ๋ชจ๋๋ฅผ ๊ณ ๋ คํ ์ ๋ต์ด ํ์ํ๊ฒ ๋ค.
basic | asset | network | widget |
---|---|---|---|
๋ง์ปค๋ฅผ ๊ตฌ์ฑํ ๋์ ์ค์ํ ๋์์ธ ์ ์ธ ์์์ ์ฌ์ฉ์ฑ ๊ฐ์ ์ด ๋ฐ๋ก ํด๋ฌ์คํฐ(Cluster)์ด๋ค.
์ ๋ง์ ๋ง์ปค๊ฐ ํ ํ๋ฉด์ ๋์์ ํ์๋ ๊ฒฝ์ฐ, ์ง๋๊ฐ ๋ณต์กํด์ง๊ณ ์์ธ์ฑ์ด ๋จ์ด์ง๋ฉฐ, ์ฌ์ฉ์ ๊ฒฝํ์ด ํฌ๊ฒ ์ ํ๋๊ธฐ ๋๋ฌธ์ ํด๋ฌ์คํฐ๋ง์ ํ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ๋ค.
ํด๋ฌ์คํฐ๋ ์๋ก ๊ฐ๊น์ด ์์น์ ์๋ ๋ง์ปค๋ค์ ๊ทธ๋ฃน์ผ๋ก ๋ฌถ์ด ํ๋์ ๋ง์ปค(Icon)๋ก ํํํจ์ผ๋ก์จ, ์ง๋๋ฅผ ๊น๋ํ๊ฒ ์ ์งํ๋ฉด์๋ ์ ๋ณด๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ ๋ฌํ ์ ์๋๋ก ๋๋ ๊ธฐ๋ฅ์ด๋ค.
ํด๋ฌ์คํฐ(Cluster)๋ ์ฌ๋ฌ ํจํค์ง๋ฅผ ํ์ฉํ๋ฉด ๋น๊ต์ ์์ฝ๊ฒ ์ ์ฉํ ์ ์์ง๋ง, ์ง๋์์ ๋ง์ปค ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ๊ทธ๋ฃนํํ ์ง, ์ค ๋ ๋ฒจ์ ๋ฐ๋ผ ์ด๋ป๊ฒ ํํํ ์ง, ์ปค์คํ UI๋ ์ด๋ป๊ฒ ์ ์ฉํ ์ง ๋ฑ ๋ค๋ค์ผ ํ ์์๋ค์ด ๋ง๋ค. ๋ฐ๋ผ์ ํด๋ฌ์คํฐ์ ๋ํ ์์ธํ ๋ด์ฉ์ ๋ณ๋์ ๊ธ์์ ๋ค๋ฃจ๋๋ก ํ๊ณ , ์ด ๊ธ์์๋ ํด๋ฌ์คํฐ๋ง ๊ตฌํ์ ๋ํ ์ค๋ช ์ ์๋ตํ๋๋ก ํ๊ฒ ๋ค.
์ง๋ ์์ ํน์ ์์น๋ฅผ ์ค์ฌ์ผ๋ก ๋ฐ๊ฒฝ(Radius)์ ์๊ฐ์ ์ผ๋ก ํํํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์ข ์ข ์๊ฒ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ด ์์น ๊ธฐ์ค 1km ์ด๋ด๋ฅผ ํ์ํ๊ฑฐ๋ ํน์ ์ง์ญ์ ๋ฒ์๋ ์ ํ ๊ตฌ์ญ์ ์๊ฐํํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ Circle ์์ ฏ์ ํ์ฉํ๋ฉด ๊ตฌ๊ธ ์ง๋ ์์ ์์ฝ๊ฒ ์ ํํ์ ์ค๋ฒ๋ ์ด๋ฅผ ์ถ๊ฐํ ์ ์๋ค.
circles ํ๋์ ์์์ ์ดํด๋ณธ ๋ง์ปค์ ๋์ผํ๊ฒ Set ํ์ ์ Circle ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
๊ณ ์ ํ circleId๋ฅผ ์์ฑํ๊ณ , center ํ๋์ ์ง๋ ์ขํ๊ณ๋ฅผ ์ง์ ํด์ค๋ค radius์ ๋ฒ์๋ฅผ ๋ฏธํฐ(meter) ๊ฐ์ผ๋ก ์์ฑํด์ฃผ๋ฉด ์ง๋์์ ์ํ์ ๋ฒ์๊ฐ ์ง์ ๋๊ฒ ๋๋ค.
๋ฒ์ ์์ ์์์ fillColor๋ฅผ ์ฌ์ฉํ๋ฉด ๋๊ณ , ํ ๋๋ฆฌ ์ ์ storkeColor์ ์ํ๋ ์์์ ์ง์ ํด์ฃผ๋ฉด ๋๋ค. ํ ๋๋ฆฌ ์ ์ ๋๊ป๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ถ๋ค๋ฉด strokeWidth ํ๋์ ์ํ๋ ๋๊ป๋ฅผ ์ฃผ๋ฉด๋๋ค.
๋ง์ปค๋ฅผ ๋ค๋ฃฐ ๋์ ๋์ผํ๊ฒ zIndex, visible, onTap, consumeTapEvents ํ๋๋ ๋์ผํ ๋ฐฉ์์ผ๋ก ํ์ฉ์ด ๊ฐ๋ฅํ๋ค.
circles: {
...
Circle(
circleId: const CircleId(uniqueId),
center: const LatLng(latitude, longitude),
radius: 1000,
...
),
},
์ด๋ฒ์๋ ๋ฒ์๊ฐ ์๋ ๊ตฌ์ญ์ ์ง์ ํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด๋๋ก ํ์.
๋ฒ์๊ฐ ์๋ ๊ตฌ์ญ(๋ฉด)์ ์ง๋์ ์ค๋ฒ๋ ์ดํ๋ ค๋ฉด Polygon์ ์ฌ์ฉํ์ฌ์ผ ํ๋ค.
์๋ฅผ๋ค์ด ๋ํ๋ฏผ๊ตญ, ์์ธ์, ๋ด์์ฒ๋ผ ํน์ ๋์/ํ์ ๊ตฌ์ญ/๋จ์ง๋ฅผ ๋ฐํฌ๋ช ์ค๋ฒ๋ ์ด๋ก ํ์ํ๊ฑฐ๋, ์ง๋ช ์ ํญํ์ ๋ ํด๋น ๊ตฌํ์ ๊ฒฝ๊ณ๋ฅผ ๊ทธ๋ ค ๊ฐ์กฐํ๋ ๋ฐ ์ฐ์ธ๋ค. ๋ค๋ง ํด๋ฆฌ๊ณค์ ๊ทธ๋ฆฌ๋ ค๋ฉด ํด๋น ์ง์ญ์ ๊ฒฝ๊ณ ์ขํ(์๋/๊ฒฝ๋ ๋ฆฌ์คํธ)๊ฐ ํ์ํ๋ฏ๋ก, ํ์ ๊ฒฝ๊ณ/์์ ๋ ๊ฐ์ ๊ฒฝ๊ณ ๋ฐ์ดํฐ(๊ณต๊ณต๋ฐ์ดํฐ, ์ง๋ ๊ฒฝ๊ณ API, ์คํ ์ง์ค๋ฐ์ดํฐ)๋ฅผ ํ๋ณดํด์ผ ์์ธํ ๊ตฌ์ญ์ ๋ณด์ฌ์ค ์ ์๋ค.
์์ ์ดํด๋ณธ ๋ง์ปค์ ์จํด์ฒ๋ผ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๊ฑฐ์ ๋์ผํ๋ค๊ณ ๋ณผ ์ ์๋ค.
Set ํ์ ์ polygons ํ๋์ Polygon ๊ฐ์ฒด๋ฅผ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
ํด๋ฆฌ๊ณค์๋ ์ค์ํ ๋ถ๋ถ์ด ์๋๋ฐ, ๋ฐ๋ก points์ holes์ด๋ค.
points๋ ํด๋ฆฌ๊ณค์ผ๋ก ์ง์ ํ๊ณ ์ถ์ ๊ตฌ์ญ์ ์ง๋ ์ขํ๊ณ๋ค์ด๊ณ , holes๋ ์ ์ธํ๊ณ ์ ํ๋ ๊ตฌ์ญ์ ์ง๋ ์ขํ๊ณ๋ค์ด๋ค. ์ฝ๊ฒ ์ค๋ช ํด์ ์์ธ์๋ฅผ ํด๋ฆฌ๊ณค์ผ๋ก ์ง์ ํ๊ณ ์ถ์๋ฐ, ๊ตฌ์ญ ๋ด์ ์ข ๋ก๊ตฌ๋ ์ ์ธ์ํค๊ณ ์ถ๋ค๋ฉด points ํ๋์ ์์ธ์์ ๊ฒฝ๊ณ ์ขํ๋ฅผ ๋ฐฐ์ด๋ก ์ง์ ํ ๋ค, holes ํ๋์ ์ข ๋ก๊ตฌ์ ํด๋นํ๋ ๊ฒฝ๊ณ ์ขํ๋ค์ ๋ฐฐ์ด๋ก ๋ฃ์ด์ฃผ๊ฒ ๋๋ฉด ์์ธ์์ ๊ตฌ์ญ์ด ์กํ๋ฉด์ ๊ทธ ์์ ์๋ ์ข ๋ก๊ตฌ๋ ์ ์ธ๋๊ฒ ๋๋ค.
ํด๋ฆฌ๊ณค์ ์ต์ ๋ ํ๋๋ก geodesic ํ๋๊ฐ ์๋๋ฐ, ์ด๊ฑด ์ง๊ตฌ์ ๊ณก๋ฅ ์ ๋ฐ์ํ ์ง ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ ๊ฒ์ผ๋ก ๊ฒฝ๊ณ ์ขํ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ์ฐจ์ด๊ฐ ์์ง๋ง ๋ค๊ฐํ์ ๊ฐ ๋ณ์ ํ๋ฉด ์ง์ ์ด ์๋ ์ง๊ตฌ ๊ณก๋ฅ ์ ๋ฐ์ํ๊ณ ์ถ์ ๋์ ์ฌ์ฉํ ์ ์๋ค. ์์ธํ ์ค๋ช ์ ์๋์์ ์ค๋ช ํ๋๋ก ํ๊ฒ ๋ค.
๋ง์ปค, Circle๊ณผ ๋์ผํ๊ฒ ์์ ์ปฌ๋ฌ๋ ๋๊ป ๋ฑ์ ์ต์ ๋ค์ ์๋ฏธ์ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋์ผํ๋ค.
polygons: {
Polygon(
polygonId: const PolygonId(uniqueId),
points: [
...
LatLng(latitude, longitude),
],
holes: [
...
LatLng(latitude, longitude),
],
)
},
์ง๋ ์์ ๋ ๊ฐ ์ด์์ ์ขํ๋ฅผ ์ฐ๊ฒฐํด ๊ฒฝ๋ก๋ฅผ ์๊ฐํํ ๋ ์ฌ์ฉํ๋ Polyline์ ๋ํด์ ์์๋ณด๋๋ก ํ์.
๋งต์ด๋ ์ง๋๋ฅผ ํ์ฉํ๋ ์๋น์ค๋ค์์ ์์ฃผ ๊ฒฝํํด๋ณธ ๊ธฐ๋ฅ์ผ ๊ฒ์ด๋ค. ์๋ฅผ ๋ค์ด, ๋ค๋น๊ฒ์ด์ ์๋น์ค์์ ์ฐจ๋์ ์ด๋ ๊ฒฝ๋ก๋ฅผ ํ์ํ๊ฑฐ๋, ์ฌํ ์๋น์ค์์ ๋นํ๊ธฐ์ ์ดํญ ๋ฃจํธ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.
Polyline์ ์ด๋ฌํ ๊ฒฝ๋ก๋ฅผ ๋จ์ํ ์ง์ ๋ฟ๋ง ์๋๋ผ, ๊ณก์ , ์์ ๋ณ๊ฒฝ, ์ ์ ํจํด ๋ฑ ๋ค์ํ ์คํ์ผ๋ก ํํํ ์ ์๊ธฐ ๋๋ฌธ์, ์๊ฐ์ ์ผ๋ก ๊ฒฝ๋ก๋ฅผ ๋์ฑ ์ง๊ด์ ์ด๊ณ ์ดํดํ๊ธฐ ์ฝ๊ฒ ๋ง๋ ๋ค.
์ด๋ฏธ ์์ Marker, Circle, Polygon ๊ธฐ๋ฅ์ ์ดํด๋ณด๋ฉด์, google_maps_flutter ํจํค์ง๊ฐ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ์ ๋ฐ์ ์ธ ํจํด์ ์ด๋ ์ ๋ ์ตํ์ ๊ฒ์ด๋ค. ๋ฐ๋ผ์ Polyline์ ์ฌ์ฉ ๋ฐฉ๋ฒ๊ณผ ์ต์ ์ญ์ ์์๊ณผ ํฌ๊ฒ ๋ค๋ฅด์ง ์๊ธฐ ๋๋ฌธ์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์์ ๊ฒ์ด๋ค.
Polyline๋ Set ํ์ ์ผ๋ก ๋จ์ผ ๊ฒฝ๋ก๊ฐ ์๋ ์ฌ๋ฌ ๊ฐ์ ๊ฒฝ๋ก๋ฅผ PolylineId ๋ผ๋ ๊ณ ์ ID๋ก ์์ฑํ๊ฒ ๋๋ค.
Polygon์์์ ๋์ผํ๊ฒ points ํ๋๋ฅผ ์ฌ์ฉํ์ฌ ์ง๋ ์ขํ๋ค์ ์์๋๋ก ์ง์ ํ๋ฉด, ์ด๋ฅผ ํ๋์ ์ด์ด์ง ์ (Line) ํํ๋ก ์ง๋ ์์ ํ์ํ๊ฒ ๋๋ค.
์ค์ ๋ก ๋ค๋น๊ฒ์ด์
์๋น์ค์์ ๊ฒฝ๋ก๋ฅผ ์์ฒญํ๋ฉด, ์๋ฒ๋ก๋ถํฐ ์ ๋ฌ๋ฐ์ ๊ฒฝ์ ์ง์ ๋ชฉ์ ์ง ์ขํ๋ค์ด Polyline์ points ๋ฆฌ์คํธ์ ๋งคํ๋์ด, ์ง๋ ์์ ๊ฒฝ๋ก๊ฐ ์๊ฐํ ๋๋ ๊ตฌ์กฐ๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.
์ ๋ค์ ์ต๋ํ ์์ฐ์ค๋ฝ๊ฒ ๋งคํํ๊ธฐ ์ํด์๋ ๋๋ก๋ ๊ฒฝ๋ก์ ๋ฐ๋ผ ์์ญ ๊ฐ์์ ์์ฒ ๊ฐ ๋๋ ๊ทธ ์ด์์ ์ง๋ ์ขํ๊ณ๋ค์ ์ฌ์ฉํ๊ธฐ๋ ํ๋ค.
๋ผ์ธ(Line)์ ํ์ํ ๋์ ์ค์ํ ๋ถ๋ถ์ด ํ๋ ์๋๋ฐ, ๋ฐ๋ก ์ฅ๊ฑฐ๋ฆฌ ๊ฒฝ๋ก๋ฅผ ๊ทธ๋ฆฌ๋ ๊ฒฝ์ฐ์ด๋ค.
๋จ์ํ ์ขํ๋ฅผ ์ง์ ์ผ๋ก ์ฐ๊ฒฐํ๋ฉด ์ค์ ์ง๊ตฌ ์์ ์ต๋จ ๊ฒฝ๋ก์๋ ๋ค๋ฅด๊ฒ ํ์๋ ์ ์๊ธฐ ๋๋ฌธ์ธ๋ฐ, ์ด๋ฌํ ํ์์ด ๋ฐ์ํ๋ ์ด์ ๋ Polyline์ด ํ๋ฉด ์ขํ๊ณ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ์ ๊ทธ๋ฆฌ๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์๋ geodesic ์์ฑ์ ์ค์ ํด์ฃผ๋ฉด ๋๋ค.
geodesic๋ ์์ Polygon์์๋ ์ฌ์ฉ ํ์๋ ์ต์ ์ด์๋๋ฐ, ์ข ๋ ์์ธํ ์ค๋ช ์ ํด๋ณด์๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์ง๋๋ ํ๋ฉด ํฌ์ ์์ ๊ทธ๋ ค์ง๊ธฐ ๋๋ฌธ์ ๋ ์ง์ ์ ์ ์ผ๋ก ์ด์ ๋ ๋จ์ ์ง์ ์ผ๋ก ํ์๋๋ค. ํ์ง๋ง ์ค์ ์ง๊ตฌ๋ ๊ตฌ ํํ์ ๊ฐ๊น๊ณ , ๋ ์ง์ ์ฌ์ด์ ์ค์ ์ต๋จ ๊ฒฝ๋ก๋ ๋๊ถ(Great-circle) ๊ฒฝ๋ก์ด๊ธฐ ๋๋ฌธ์, ๋จ๊ฑฐ๋ฆฌ๋ ๊ตญ์ ๊ตฌ์ญ์์ ์ฌ์ฉํ ๋์๋ ํฐ ์ฐจ์ด๊ฐ ์์ง๋ง ๋นํ ๊ฒฝ๋ก๋ ๊ตญ๊ฐ ๊ฐ ์ต๋จ๊ฑฐ๋ฆฌ์ฒ๋ผ ์ฅ๊ฑฐ๋ฆฌ ๋ผ์ธ์ ์๊ฐํ๊ฐ ํ์ํ ๊ฒฝ์ฐ์๋ ์์ฑ์ ์ฌ์ฉํ์ฌ ๋ณด๋ค ์์ฐ์ค๋ฌ์ด ๋ผ์ธ์ ๊ทธ๋ฆด ์ ์๊ฒ ๋๋ค.
์ฐจ์ด๋ฅผ ์๊ฐ์ ์ผ๋ก ์ง๋ ์์์ ํ์ธํ๊ณ ์ถ๋ค๋ฉด, ๋ํ๋ฏผ๊ตญ์์ ๋ฏธ๊ตญ์ ์ขํ๋ฅผ ์ง์ ํด ๋ณด๋ฉด false(default)์ธ ๊ฒฝ์ฐ ํํ์์ ๊ฐ๋ก์ง๋ฅด๋ ์ผ์ง์ ๋ผ์ธ์ผ๋ก ํ์๋์ง๋ง, true๋ก ๋ณ๊ฒฝํด ๋ณด๋ฉด, ์ค์ ๋นํ๊ธฐ ๊ฒฝ๋ก์ ์ ์ฌํ ๋ถ๊ทน ๋ผ์ธ์ ๊ฐ๋ก์ง๋ฅด๋ ๊ณก๋ฅ ๋ก ํ์๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
Polyline ๋์์ธ ์์๋ก๋ color, width๋ก ์ ์์๊ณผ ๋๊ป๋ฅผ ์ง์ ํ ์ ์๊ณ , ํฌ๋ช ๋๋ Color ๊ฐ์ฒด์ withOpacity๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
startCap, endCap์ Cap.buttCap(ํํ), Cap.roundCap(๋ฅ๊ทผ), Cap.squareCap(์ฌ๊ฐํ)์ผ๋ก ์์๊ณผ ๋์ ์ ๋ชจ์์ ์ง์ ํ ์ ์๋๋ฐ, iOS Google Map SDK์๋ ์ง์ํ์ง ์๋ ๊ธฐ๋ฅ์ผ๋ก Android์ Web์์๋ง ์ ์ฉํ ์ ์๋ค.
์ (Line)์ ํจํด์ patterns ํ๋์ ๋ฐฐ์ด๋ก PatternItem์ ๋ฐฐ์ด๋ก ์ถ๊ฐํด์ฃผ๋ฉด ํ๋์ ์ฐ๊ฒฐ๋ ์ ์ด ์๋ ํน์ ๊ตฌ๊ฐ๋ง๋ค ๋๊ธด ์ ์ ๋ฑ์ ๋ง๋ค์ด ์ค ์ ์๋ค. ์ ์ ์ ๋ง๋ค๊ณ ์ถ๋ค๋ฉด PatternItem.dash(double) + PatternItem.gap(double)์ ์กฐํฉํด์ ์ํ๋ ๊ธธ์ด์ ๊ฐ๊ฒฉ์ ์ปค์คํ ํ ์ ์๋ค.
๋ผ์ธ์ ๋ชจ์๋ฆฌ ๋ถ๋ถ๋ ๋์์ธ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ฐ jointType ํ๋์ JointType์ผ๋ก .mitered(default), .bevel, .round๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
- .mitered : ๋ ์นด๋ก์ด ๋ชจ์๋ฆฌ
- .bevel : ๋ชจ์๋ฆฌ๋ฅผ ๊น์์ ํํํ๊ฒ
- .round : ๋ชจ์๋ฆฌ๋ฅผ ๋ฅ๊ธ๊ฒ
๊ตฌ๊ธ ์ง๋๋ฅผ ์ปจํธ๋กคํ๊ณ , ์ง๋ ์์ ์ ๋ณด๋ฅผ ์๊ฐํํ๊ธฐ ์ํด Marker, Circle, Polygon, Polyline ๊ฐ์ ๋์์ธ ์์๋ค์ ์ดํด๋ณด์๋ค. ์ด๋ฒ ๊ธ์์๋ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ๊ณผ ํต์ฌ ์ต์ ์์ฃผ๋ก ์ ๋ฆฌํ์ง๋ง, ์ค์ ์๋น์ค์์๋ ์ง๋ ๋ทฐ์ ์ค ๋ ๋ฒจ, ๊ธฐ์ธ๊ธฐ/ํ์ , ์ ์ค์ฒ ์ ์ด, ๋์ ์คํ์ผ๋ง ๋ฑ ๊ณ ๋ คํด์ผ ํ ์์๊ฐ ๋ง์, ์์ฑ๋ ๋์ ์ง๋ ์๋น์ค๋ฅผ ๊ตฌ์ถํ๋ ์ผ์ ๊ฒฐ์ฝ ๊ฐ๋จํ์ง ์๋ค. ์์ผ๋ก ์ด๋ฌํ ๊ณ ๊ธ ๊ธฐ๋ฅ๊ณผ ์ต์ ํ ๋ฐฉ๋ฒ์ ์ค๋ฌด์ ์ ์ฉํ ์ ์๋ ์ฃผ์ ๋ก ์ง์์ ์ผ๋ก ๋ค๋ค๋ณผ ์์ ์ด๋ค.
์ง๋๋ฅผ ๋ค๋ฃจ๋ค ๋ณด๋ฉด ๋จ์ํ ๋ง์ปค๋ ์, ํด๋ฆฌ๊ณค ๊ฐ์ ์์๋ฅผ Overlay(์ค๋ฒ๋ ์ด)ํ๋ ๊ฒ๋ง์ผ๋ก๋ ๋ถ์กฑํ ๋๊ฐ ๋ง์๋ฐ, ์ฌ์ฉ์๋ ๋ณดํต "์ด ์ขํ๊ฐ ์ด๋ค ์ฃผ์์ธ์ง" ๋๋ "์ด ์ฃผ์๊ฐ ์ง๋์์ ์ด๋์ฏค์ธ์ง"๋ฅผ ์๊ณ ์ถ์ดํ๋ค.
์ด ๊ณผ์ ์ ๋ฐ๋ก ์ง์ค์ฝ๋ฉ(Geocoding), ๋ฆฌ๋ฒ์ค ์ง์ค์ฝ๋ฉ(Reverse Geocoding) ์ด๋ผ๊ณ ํ๋ค.
์ง๋ ์ขํ๊ณ(์๋/๊ฒฝ๋)๋ฅผ ์ฃผ์๋ก ๋ฐ๊ฟ์ฃผ๋ ๊ณผ์ ์ ๋ฆฌ๋ฒ์ค ์ง์ค์ฝ๋ฉ(Reverse Geocoding)์ด๋ผ๊ณ ํ๋ฉฐ, ์ง๋ ์์ ํน์ ๊ณต๊ฐ์ ๋๋ ์ ๋์, ๊ทธ ์ง๋ ์ขํ๊ณ๋ฅผ ์ด๋ค ํ์ ๊ตฌ์ญ์ด๋ ๋๋ก๋ช ์ฃผ์ ๋ฑ ์ฌ๋์ด ์ดํดํ ์ ์๋ ์ฃผ์๋ก ๋ณํํ๋ ๊ณผ์ ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด ์ง์ค์ฝ๋ฉ(Geocoding)์ ์ฃผ์๋ฅผ ์ง๋ ์ขํ๊ณ๋ก ๋ฐ๊ฟ์ฃผ๋ ๊ณผ์ ์ ๋งํ๋ค.
์ฌ์ฉ์๊ฐ ํน์ ์ฃผ์์ ๋ง์ปค๋ฅผ ์ฐ๊ณ ์ถ๋ค๋ฉด, ์ฃผ์๋ฅผ ์ง์ค์ฝ๋ฉํ์ฌ ์ง๋ ์ขํ๊ณ๋ก ๋ณํํ์ฌ ์ง๋ ๊ณต๊ฐ ์์ ํ์ํด์ฃผ๋ฉด ๋๋ ๊ฒ์ด๋ค.
์ง๋๋ ๋ณธ์ง์ ์ผ๋ก ์ขํ๊ณ ์์์ ๋์ํ์ง๋ง, ์ฌ๋์ ์ขํ๋ณด๋ค๋ ์ฃผ์๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฌ๊ณ ํ๊ธฐ ๋๋ฌธ์, ์ง๋ ๊ธฐ๋ฐ ์๋น์ค๋ฅผ ๋ง๋ค ๋๋ ์ฃผ์์ ์ขํ๋ฅผ ์ํธ ๋ณํํ๋ ๊ธฐ๋ฅ์ด ๋ฐ๋์ ํ์ํ๊ฒ ๋๋ค.
Google Maps์์๋ ์ด๋ป๊ฒ ์ด ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์๊น ? GCP์ Google Maps Platform์ Geocoding API๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค.
์์, Android์ iOS์์ ์ง๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด API Key๋ฅผ ๋ฐ๊ธ๋ฐ์ ํ๋ก์ ํธ์ ์ ์ฉํ์๋ค. ๊ทธ๋ฐ๋ฐ ์ฌ๊ธฐ์ Geocoding API๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ ๋์ ๋ฌธ์ ๊ฐ ์๊ธฐ๊ฒ ๋๋ค.
GCP์์ API Key๋ฅผ ๋ฐ๊ธํ ๋ ๋ณด์์ ์ํด ํํ ํค ์ ํ์ฌํญ - ์ ํ๋ฆฌ์ผ์ด์
์ ํ์ ๊ฑธ์ด๋ ๊ฒ์ ๊ธฐ์ตํ๊ณ ์์ ๊ฒ์ด๋ค.
์ด ๋ฐฉ์์ ์ง๋ SDK๋ฅผ ์ฑ์์ ์ง์ ํธ์ถํ ๋์๋ ๋ฌธ์ ๊ฐ ์์ง๋ง, Geoconding API๋ ๋ณดํต HTTP ์์ฒญ ๊ธฐ๋ฐ์ Web API ํํ๋ก ์ ๊ณต๋๊ธฐ ๋๋ฌธ์, ์ฑ ์์์ ์ง์ ํธ์ถํ๊ฒ ๋๋ฉด ํค ์ ํ์ด ์ ์ฉ๋ API ํค ์ฌ์ฉ์ผ๋ก ๊ถํ ์๋ฌ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค.
์ฆ, ์ง๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ํ๋ซํผ ๋ณ๋ก ๋ฐ๊ธ ๋ฐ์ API ํค๋ก๋ Geocoding API๋ฅผ ์ฌ์ฉํ ์๊ฐ ์๋ค.
ํ๋ซํผ๋ณ API ํค ์ ํ์ ๋์ง ์๊ณ ๋ชจ๋ ํ๊ฒฝ์์ ๊ณตํต์ผ๋ก ์ฌ์ฉํ๋๋ก ์ค์ ํ๋ค๋ฉด, Geocoding API๋ฅผ ํ์ฑํ ํด์ฃผ๋ฉด ๋์ง๋ง, ๋ณด์ ๊ฐํ๋ฅผ ์ํด ํ๋ซํผ๋ณ ์ ํ์ ์ ์งํ๊ณ ์ถ๋ค๋ฉด, ๊ธฐ์กด ํค๋ SDK ์ ์ฉ์ผ๋ก ์ ์งํ๊ณ ์ถ๊ฐ๋ก API Key๋ฅผ ๋ฐ๊ธ๋ฐ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
ํ ์คํธ ๋จ๊ณ์์๋ ์ ํ ์๋ API ํค ํ๋๋ง์ผ๋ก๋ ์ถฉ๋ถํ๋ค. ํ์ง๋ง ์ด์ ํ๊ฒฝ์์ ํค๊ฐ ๊ทธ๋๋ก ๋ ธ์ถ๋๋ฉด ๋ณด์์ ํฐ ์ํ์ด ์๊ธฐ๋๋ฐ, ๋๊ตฌ๋ ํค๋ฅผ ์ฌ์ฉํด API๋ฅผ ํธ์ถํ ์ ์์ด ๊ณผ๊ธ์ด๋ ์ฟผํฐ ์์ง ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฐ๋ผ์ ์ค์ ์๋น์ค์์๋ ํ๋ซํผ๋ณ๋ก ํค๋ฅผ ๋๋ ์ ํ์ ๋๊ฑฐ๋, ์๋ฒ๋ฅผ ํตํด Geocoding API๋ฅผ ํธ์ถํ๋ฉด์ IP ์ ํ์ ์ ์ฉํ๋ ๋ฐฉ์์ด ์์ ํ๋ค.
์๋ก์ด API ํค๋ฅผ ๋ฐ๊ธ ๋ฐ์๋ณด์.
ํค ๋ฐ๊ธ์ ์์ ํด๋ณธ ๊ฒ๊ณผ ๋์ผํ ์ ์ฐจ๋ก GCP > ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด ๋ง๋ค๊ธฐ > API ํค๋ก ์ด๋ํ์ฌ ์ ํ๋ฆฌ์ผ์ด์
์ ํ์ฌํญ์ ์์์ผ๋ก ํด์ฃผ๋๋ก ํ์.
๋ค๋ง, ํ
์คํธ ์ฉ๋๊ฐ ์๋๋ผ ์ค์ ์ด์ ํ๊ฒฝ์์ ์ฌ์ฉ๋ ์์ ์ด๋ผ๋ฉด IP ์ฃผ์ ์ ํ๊ณผ ๊ฐ์ ๋ณด์์ค์ ์ ๊ผญ ์ ์ฉํด ํด๋ผ์ด์ธํธ์์ ์ง์ ํธ์ถํ์ง ์๊ณ , ์๋ฒ์์ Geocoding API๋ฅผ ํ๋ก์๋ก ํธ์ถํ๋ ๋ฐฉ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ์์ ํ๋ค.
SDK๋ฅผ ์ถ๊ฐํ ๊ฒ๊ณผ ๊ฐ์ด API ์ ํ์ฌํญ์ Geocoding API๋ฅผ ์ ํํด ํ์ฑํ ํด์ฃผ๋๋ก ํ์.
![]() |
![]() |
์ ์ด์ ํ์ฑํ๋ Geocoding API ํค๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ค์ฝ๋ฉ/์ญ์ง์ค์ฝ๋ฉ์ ํธ์ถํด ๋ณด๋๋ก ํ์.
Geocoding API์ ์๋ํฌ์ธํธ Base URL์ด๋ค. ๊ธฐ๋ณธ์ json์ด์ง๋ง xml์ ์ํ ๊ฒฝ์ฐ xml๋ก ํธ์ถํ ์ ์๋ค.
https://maps.googleapis.com/maps/api/geocode/json
์ต์ ๋ ํ๋ผ๋ฏธํฐ๋ก key๋ฅผ ์ถ๊ฐํด์ผ ํ๋๋ฐ, ์ฌ๊ธฐ์ key๊ฐ ์์ ์์ฑํ API Key๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
์ธ์ด๋ ์ง์ ํ ์ ์๋๋ฐ, language=ko๋ก ํ๋ผ๋ฏธํฐ์ ์ถ๊ฐํด ์ฃผ๋ฉด ํ๊ตญ์ด๋ก ์๋ต ๊ฐ์ ๋ฐํํด ์ค๋ค.
๊ฐ์ฅ ์ค์ํ ์ง์ค์ฝ๋ฉ/์ญ์ง์ค์ฝ๋ฉ์ ์์ฒญํ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ์์๋ณด์.
์ง์ค์ฝ๋ฉ(Geocoding)์ ์ฃผ์๋ฅผ ์ง๋ ์ขํ๊ณ๋ก ๋ณํํ๋ ์ญํ ์ด๋ฏ๋ก ์ต์
๋ ํ๋ผ๋ฏธํฐ์ address๋ฅผ ์ถ๊ฐํ๊ณ ๋ณํํ๊ณ ์ ํ๋ ์ฃผ์๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋๊ณ , ๋ฐ๋์ธ ์ญ์ง์ค์ฝ๋ฉ(Reverse Geocoding)์ ์์ฒญํ๋ ๊ฒฝ์ฐ latlng ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋๋ฐ latitude(์๋), longitude(๊ฒฝ๋)๋ฅผ ์ฝค๋ง๋ก ๊ตฌ๋ถํด์ ์์ฒญํด์ฃผ๋ฉด ๋๋ค.
์ฌ๊ธฐ์ ์ฃผ์์ ์ ์๋/๊ฒฝ๋์ ์์๊ฐ ๋ฐ๋๋ฉด ์๋๋ค.
?key={api_key}&language=ko&address=์์ธํน๋ณ์ ์ข
๋ก๊ตฌ ์ฌ์ง๋ก 161
?key={api_key}&language=ko&latlng=37.580467, 126.976944
์๋ต JSON ๊ตฌ์กฐ๋ฅผ ์ดํด๋ณด๋๋ก ํ์.
๊ณตํต์ ์ผ๋ก ์๋ต ์ํ์ธ status์ ์ํ๋ ๊ฒฐ๊ณผ ๊ฐ results ํ๋๋ฅผ ๋ด๋ ค์ค๋ค.
results๋ ๋ฐฐ์ด ๊ตฌ์กฐ๋ก ์ฌ๋ฌ ๊ฐ์ ๋ฐ์ดํฐ๊ฐ ๋ด๊ฒจ์ ๋ด๋ ค์ค๊ฒ ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ง์ค์ฝ๋ฉ์ ์์ฒญํ๋ ๊ฒฝ์ฐ ๋๋ถ๋ถ 1๊ฐ์ ๊ฒฐ๊ณผ ๊ฐ๋ง ๋์ค์ง๋ง, ์ ํํ ์ฃผ์๊ฐ ์๋ ํน์ ํ์ ๊ตฌ์ญ๊น์ง๋ง ์
๋ ฅํ๋ฉด ๋์ผํ ๋ช
์นญ์ ์ฌ์ฉํ๋ ๋ฒ์ ๋/ํ์ ๋์ด ์กด์ฌํ ์ ์์ด ์ฌ๋ฌ ๋ฐ์ดํฐ๊ฐ ๋ฐฐ์ด์ ๋ด๊ฒจ ๋ฐํ๋ ์ ์๋ค.
์๋ฅผ ๋ค์ด, โaddress=์ค์๋กโ ์ ๊ฐ์ด ์์ฒญํ๋ฉด ์ ๊ตญ์ ์กด์ฌํ๋ โ์ค์๋กโ๋ผ๋ ๋๋ก๋ช
์ฃผ์๊ฐ ๋ชจ๋ ๊ฒ์๋์ด ์ฌ๋ฌ ๊ฒฐ๊ณผ๊ฐ ๋ฐํ๋๋ค.
๋ฐ๋ฉด, โ์์ธํน๋ณ์ ์ข
๋ก๊ตฌ ์ฌ์ง๋ก 161โ์ฒ๋ผ ์ ํํ ์ฃผ์๋ฅผ ์
๋ ฅํ๋ฉด ๋จ์ผ ๊ฒฐ๊ณผ๋ง ๋ฐํ๋๋ฏ๋ก ์ด ๊ฒฝ์ฐ์๋ results ๋ฐฐ์ด์ ์ฒซ ๋ฒ์งธ ๊ฒฐ๊ณผ๊ฐ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
์ญ์ง์ค์ฝ๋ฉ์ ๊ฒฝ์ฐ๋ ์กฐ๊ธ ๋ค๋ฅด๋ค.
ํ๋์ ์ขํ ๊ฐ์ ์ฃผ์๋ก ๋ณํํ๋ ๊ณผ์ ์์ ๊ทธ ์์น๊ฐ ์ํ ๋๋ก๋ช ์ฃผ์, ์ง๋ฒ ์ฃผ์, ํ์ ๋, ๋ฒ์ ๋, ์/๊ตฐ/๊ตฌ, ๊ตญ๊ฐ ๋จ์ ๋ฑ ์ฌ๋ฌ ์ฃผ์ ๊ณ์ธต์ด ํจ๊ป ๋งค์นญ๋๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋ฐฐ์ด๋ก ๋ด๋ ค์ค๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด์ด์, ํน์ ํ์ ์ ๊ตฌ๋ถํด ์ฌ์ฉํ๊ฑฐ๋ ๊ฐ์ฅ ์ ๋ขฐ๋๊ฐ ๋์ ์ฒซ ๋ฒ์งธ ๊ฒฐ๊ณผ ๊ฐ๋ง ์ฌ์ฉํ๋ ๋ฑ์ ์ ์ ํ ๋ฐฉ๋ฒ์ ๋ง๋ค์ด ์ฌ์ฉํ๋ฉด ๋๋ค.
Google Maps Platform Geocoding API Overview์ ์ ์ํด ๋ณด๋ฉด Geocoding API๊ฐ ์ด๋ป๊ฒ ์๋ ํ๋์ง์ ๋ํ ๊ฒฐ๊ณผ ๊ฐ์ ์ฃผ์ ๊ณ์ธต๋ค์ ์๊ฐ์ ์ผ๋ก ํ์ธํด ๋ณผ ์ ์๋ค.
results ๋ฐฐ์ด์ ๋ด๊ฒจ ์๋ ๋ฐ์ดํฐ๋ค์ ์ด๋ค ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๋์ง๋ ์ดํด๋ณด๋๋ก ํ์.
Google Maps Platform - Geocoding request and response
โ๏ธGeocoding API์ ๋ํ ์์ธํ ๋ด์ฉ์ ๊ณต์๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์๊ธธ ๋ฐ๋
results ๋ฐฐ์ด์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ์ง์ค์ฝ๋ฉ๊ณผ ์ญ์ง์ค์ฝ๋ฉ ๋ชจ๋ ๋์ผํ ํํ๋ฅผ ๊ฐ์ง๋ค.
์ด ์ค์์ ๊ฐ์ฅ ์ค์ํ ํ๋๋ ๋ฐ๋ก formatted_address์ geometry์ด๋ค.
formatted_address๋ ์ฌ๋์ด ์ฝ์ ์ ์๋ ์ต์ข ์ฃผ์ ๋ฌธ์์ด์ ๋ด๊ณ ์๊ณ , geometry๋ ์์น ๊ด๋ จ ์ธ๋ถ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
์ขํ๋ฅผ ์ฃผ์ ๊ฐ์ผ๋ก ๋ณํํ๋ ์ญ์ง์ค์ฝ๋ฉ์ ๊ฒฝ์ฐ์๋ formatted_address ํ๋์ ๋ด๊ธด ์ฃผ์ ๋ฌธ์์ด์ ํ์ฉํ ์ ์๊ณ , ๋ฐ๋๋ก ์ฃผ์๋ฅผ ์ขํ๋ก ๋ณํํ๋ ์ง์ค์ฝ๋ฉ์ ๊ฒฝ์ฐ์๋ geometry ํ๋์ ์ขํ ์ ๋ณด๋ฅผ ํ์ฉํ๋ฉด ๋๋ค.
formatted_address๋ ๋ฐํ ํ์ ์ด ๋ฌธ์์ด๋ก ๊ทธ๋๋ก ์ฌ์ฉํ ์ ์์ง๋ง geometry ํ๋๋ location, location_type, viewport ๊ตฌ์กฐ๋ก ์ด๋ฃจ์ด์ ธ ์๊ธฐ ๋๋ฌธ์, location์ lat, lng์ ์๋/๊ฒฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
viewport๋ northeast(๋ถ๋์ชฝ), southwest(๋จ์์ชฝ) ์ขํ ์ ๋ณด๋ฅผ ํตํด ํด๋น ์ขํ๊ฐ ํ๋ฉด์ ๋ณด์ฌ์ค ๋์ ์ ์ ํ ๋ฒ์๋ฅผ ์ ์ํ๋ ์ฌ๊ฐํ ์์ญ์ ๋ฐ์ดํฐ์ด๋ค. ์์ Geocoding API ์ค๋ฒ๋ทฐ์์ ํ์ธํด ๋ณด๋ ์ฌ๊ฐํ ๋ฐ์ค์ ์์ญ์ด๋ผ๊ณ ๋ณด์๋ฉด ๋๋ค.
์ถ๊ฐ๋ก ๊ฒฝ์ฐ์ ๋ฐ๋ผ์ bounds๊ฐ ํฌํจ๋๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ, ํ์ ๊ตฌ์ญ์ด๋ ์ฐํธ๋ฒํธ, ํน์ ๊ตฌ์ญ์ฒ๋ผ ๋ฒ์๋ฅผ ๊ฐ์ง๋ ๊ฒฐ๊ณผ์ผ ๊ฒฝ์ฐ ์ค์ ๊ฒฝ๊ณ๋ฅผ northeast, southwest ์ขํ๋ก ์ ๊ณตํด์ค๋ค.
๊ฑด๋ฌผ์ด๋ ๋๋ก๋ช
์ฃผ์์ฒ๋ผ ํน์ ์ง์ (point)์ ๋ํ๋ด๋ ๊ฒฐ๊ณผ์๋ ํฌํจ๋์ง ์๊ธฐ ๋๋ฌธ์ ์ต์
๋ํ๊ฒ ์ฌ์ฉํ์ฌ์ผ ํ๋ค.
๊ฒฐ๊ณผ์ ๋ํ ์ ํ๋ ์์ค์ location_type์ผ๋ก ๋ฐํํด ์ฃผ๋๋ฐ, ํด๋น ํ์ ๋ค์ ๋ํด์๋ ๊ณต์๋ฌธ์๋ฅผ ํ์ธํ์๋ ๊ฒ์ ์ถ์ฒ๋๋ฆฌ๋ฉฐ ๋์ฒด์ ์ผ๋ก ๋ง์ด ์ฌ์ฉํ๋ ํ์ ์ ์๋์ ๊ฐ๋ค.
๋๋จธ์ง ํ๋์ ๋ํด์๋ ๊ฐ๋จํ๊ฒ๋ง ์ดํด๋ณด๋๋ก ํ์.
address_components๋ ์ฃผ์๋ฅผ ๊ตฌ์ฑํ๋ ์์๋ค์ ๋ฐฐ์ด๋ก ์ ๊ณตํ๋ ํ๋์ด๋ค. ๊ฐ ์์๋ longname(์ ์ฒด ์ด๋ฆ), short_name(์ถ์ฝ/์ฝ๋), types(ํด๋น ์์์ ์ญํ /๋จ๊ณ) ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋ฉฐ, ์ด๋ฅผ ํตํด ํ์ ๊ตฌ์ญ์ ๊ณ์ธต ์ ๋ณด๋ฅผ ํ์ธํ ์ ์๋ค.
์๋ฅผ ๋ค์ด, "administrative_area_level_1"์ ๊ด์ญ์ยท๋ ๋จ์, "sublocality_level_1"์ ๊ตฌ ๋จ์, "premise"๋ ๊ฑด๋ฌผ ๋ฒํธ์ฒ๋ผ ์ธ๋ถ์ ์ธ ๋จ์๋ฅผ ์๋ฏธํ๋ค.
๋ฐ๋ผ์ _types ์ ๋ณด๋ฅผ ํ์ฉํ๋ฉด ์ฃผ์๋ฅผ ์/๋/๊ตฌ/๋ ๋จ์๋ก ์์ฝ๊ฒ ๋ถ๋ฆฌํด ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ํ place_id๋ Google Maps์์ ์ฅ์๋ฅผ ์๋ณํ๋ ๊ณ ์ ํ ID๋ฅผ ๋ด๊ณ ์์ด, ๋์ผํ ์ฅ์๋ฅผ ์ฌ์กฐํํ๊ฑฐ๋ ๋ค๋ฅธ API์ ์ฐ๋ํ ๋ ํ์ฉํ ์ ์๋ค.
์ต์์ types ํ๋๋ ํด๋น ๊ฒฐ๊ณผ์ ์ ํ์ ๋ํ๋ด๋ฉฐ, ๋๋ก๋ช ์ฃผ์์ธ์ง(street_address), ํ์ ๊ตฌ์ญ์ธ์ง(administrative_area_level_1), ์ฐํธ๋ฒํธ์ธ์ง(postal_code) ๋ฑ์ ์๋ ค์ฃผ์ด ๊ฒฐ๊ณผ๋ฅผ ํํฐ๋งํ๊ฑฐ๋ ์ํฉ์ ๋ง๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋์์ค๋ค.
types์ ์ํ๋ ์ ํํ ํ์ ๋ค์ ๊ณต์๋ฌธ์์์ ํ์ธํ ์ ์๋ค.
๋ง์ง๋ง์ผ๋ก plus_code๋ Google์ด ์ ๊ณตํ๋ Plus Codes ์ ๋ณด๋ก, ์ฃผ์๊ฐ ์๋ ๊ณณ๋ ์ขํ ๊ธฐ๋ฐ ์ฝ๋๋ก ํํํ ์ ์๊ฒ ํด์ฃผ๋ ๊ธฐ๋ฅ์ผ๋ก ์ฌ๋ง์ด๋ ๋ฐ๋ค ํ๊ฐ์ด๋ฐ์ฒ๋ผ ๊ธฐ์กด์ ๋๋ก๋ช ์ฃผ์๋ ํ์ ๊ตฌ์ญ์ด ์กด์ฌํ์ง ์๋ ๊ณณ๋ ์๋ยท๊ฒฝ๋๋ฅผ ๊ณ ์ ํ ์ฝ๋๋ก ๋ณํํด ๊ณต์ ํ ์ ์๋ค.
Plus Codes๋ ์ ์ธ๊ณ ์ด๋์๋ ๊ณ ์ ํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅํ global_code์ ํน์ ์ง์ญ ๋งฅ๋ฝ์์ ์งง๊ฒ ์ธ ์ ์๋ compound_code ๋ ๊ฐ์ง ํํ๋ฅผ ์ ๊ณตํ๋ค.
๋ฐ๋ผ์ plus_code๋ฅผ ํ์ฉํ๋ฉด ์ฃผ์ ์ฒด๊ณ๊ฐ ์๋ ์์น๋ ์์ฝ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ์ง๋์์ ์ฐพ์๋ณผ ์ ์๋ค๋ ์ฅ์ ์ ๊ฐ์ง๊ณ ์๋ค.
์ฐธ๊ณ ๋ก ์ญ์ง์ค์ฝ๋ฉ(ReverseGeocoding)์์๋ results ํ๋๋ด ๋ฐฐ์ด ์ธ์๋ ์ต์์ ํ๋์์ ๋ณ๋๋ก plus_code๋ฅผ ํฌํจํ๋ค.
์ด๋ ๊ฒ Google Maps์์ ์ ๊ณตํ๋ Geocoding API๋ฅผ ์ฌ์ํ์ฌ ์ง์ค์ฝ๋ฉ(Geocoding)/์ญ์ง์ค์ฝ๋ฉ(ReverseGeocoding) ๊ธฐ๋ฅ์ ๋ํด์ ์์๋ณด์๋ค.
Geocoding API๋ฅผ ์ฌ์ฉํ๋ฉด ์์ฝ๊ฒ ๋ณํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๊ฒ ์ธ์๋ ๋ํ ์ผํ ๋ฐ์ดํฐ๋ค๋ ํจ๊ป ์ ๊ณต๋ฐ์ ์ ์๋ค๋ ๋ฉ๋ฆฌํธ๊ฐ ์์ง๋ง ๋น์ฐํ ๋ฌด๋ฃ๋ ์๋๋ฉฐ ์ผ์ ๋์ ์ด๊ณผํ๋ฉด ๊ณผ๊ธ์ด ๋ฐ์ํ๋ค(์๋ณ ๋ฌด๋ฃ ์ฌ์ฉ๋์ ์ ๊ณต).
์ด๋ฒ ๊ธ์์๋ Google Maps๋ฅผ ํ์ฉํ ์ง๋ ์๋น์ค ๋งฅ๋ฝ์์ Geocoding API๋ฅผ ์๊ฐํ์์ง๋ง, ๊ตฌ๊ธ์ด ์๋๋๋ผ๋ ๋ค์ํ ์๋น์ค์์ Geocoding ๊ธฐ๋ฅ์ ์ ํ์ ์ผ๋ก ๋ฌด๋ฃ๋ก ์ ๊ณตํ๊ธฐ๋ ํ๋ Geocoding API๋ฅผ ์ค์ ์๋น์ค์ ์ ์ฉ ํ์ ๋ค๋ฉด ๋ฐ๋์ ์๊ธ ์ ์ฑ ์ ํ์ธํ๊ณ ๋น์ฉ์ ๊ณ ๋ คํด์ผ ํ๋ค.
Flutter๋ก ๋ชจ๋ฐ์ผ ํ๋ซํผ(iOS/Android)๋ง ๊ฐ๋ฐํ๋ ์ํฉ์์๋ ์ผ๋ฐ์ ์ผ๋ก ๋ค์ดํฐ๋ธ API๋ก ์ด๋ฏธ ๋ด์ฅ๋์ด ์๋ Geoding ์๋น์ค๋ฅผ ๊ทธ๋๋ก ํ์ฉํ ์ ์๋๋ฐ, Android์ Geocoder์ iOS์ CLGeocoder๋ฅผ ํธ์ถํ๋ geocoding ํจํค์ง๋ฅผ ์ฌ์ฉํ์๋ฉด ๋ฌด๋ฃ๋ก ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค. ๋ค๋ง ์น์ ์ง์ํ์ง ์์ผ๋ฉฐ, OS ๋ค์ดํฐ๋ธ API์ ์์กดํ๊ธฐ ๋๋ฌธ์ ์งง์ ์๊ฐ์ ๊ณผ๋ํ ํธ์ถ์ ํ๋ฉด ์์ฒญ ์ ํ(Rate Limit)์ด ๊ฑธ๋ฆด ์ ์๊ณ ํน์ ๊ตญ๊ฐ์์๋ ์๋น์ค์ ์ ํ์ ๋ฐ์ ์๋ ์๋ค.
Geocode.xyz๋ฅผ ์ฌ์ฉํ ์ ์๋ geocode ํจํค์ง๋ ๋ชจ๋ฐ์ผ๋ฟ๋ง ์๋๋ผ ์น์์๋ 1์ด๋น 1๊ฑด์ ์ ํ์ผ๋ก๋ ๋ฌด๋ฃ๋ก ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ฉฐ, ์ ๋ฃ ํ๋๋ ์ ๊ณตํ๊ณ ์๋ค.
์๊ฐํ Google Geocoding API์ geocoding, geocode ํจํค์ง ์ธ์๋ ์ง์ค์ฝ๋ฉ/์ญ์ง์ค์ฝ๋ฉ์ ์ ๊ณตํ๋ ์๋น์ค๋ค์ด ๋ง์ด ์์ผ๋ฏ๋ก ๋ณธ์ธ์ ์๋น์ค์ ๊ฐ์ฅ ์ต์ ํํ ์ ์๋ ์๋น์ค๋ฅผ ์ ํํด์ ์ฌ์ฉํ์๋ฉด ๋๋ค.
์ง๊ธ๊น์ง Google Maps Platform์ API ํค๋ฅผ ๋ฐ๊ธ๋ฐ์ Flutter์์ ๊ตฌ๊ธ ๋งต์ ๋์ฐ๊ณ , ์ง๋ ์ฌ์ฉ์ ์ํ ๊ธฐ๋ณธ ์ต์ ์ ๋ณด ๋ฐ Marker/Circle/Polyline/Polygon ๋ฑ์ ์ค๋ฒ๋ ์ด(Overlay) ๊ธฐ๋ฅ๊ณผ ์ง๋๋ฅผ ์ ์ดํ๊ธฐ ์ํ ๋ฐฉ๋ฒ๋ค์ ๋ํด์ ์์๋ณด์๋ค.
๋ํ ์ง๋๋ฅผ ๋ค๋ฃจ๋ ๋ฐ์ ํต์ฌ ๊ธฐ๋ฅ์ธ ์ง์ค์ฝ๋ฉ(Geocoding)๊ณผ ์ญ์ง์ค์ฝ๋ฉ(Reverse Geocoding)์ Geocoding API๋ฅผ ํตํด ์ด๋ป๊ฒ ๊ตฌํํ ์ ์๋์ง๋ ์ดํด๋ณด์๋ค. ์ด๋ฅผ ํ์ฉํ๋ฉด ๋จ์ํ ์๋/๊ฒฝ๋ ์ขํ๋ง ๋ค๋ฃจ๋ ๊ฒ์ด ์๋๋ผ, ์ฌ์ฉ์๊ฐ ์ดํดํ ์ ์๋ ์ฃผ์ ๋ฐ์ดํฐ์์ ์ฐ๊ฒฐ์ด ๊ฐ๋ฅํด์ ธ ์์น ๊ธฐ๋ฐ ์๋น์ค์ ํ์ฉ๋๊ฐ ํฌ๊ฒ ๋์์ง๋ค๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค.
Google Maps Platform์ ๊ธฐ๋ฅ์ ์ต๋ํ ์ด๋ฒ ๊ธ์์ ๋ค๋ฃจ๋ ค๊ณ ํ์์ง๋ง, ๋ด์ฉ๋ ๋๋ฌด ๊ธธ์ด์ ธ ์ํ๋ ์์น์ ์ฅ์๋ฅผ ๊ฒ์ํด ์ฃผ๋ Places API, ๋ ์ง์ ์ ์ต์ ๊ฒฝ๋ก๋ฅผ ํ์ํด ์ฃผ๋ Directions API์ ๋ํด์๋ ๋ณ๋๋ก ๋ค๋ค๋ณผ ์์ ์ด๊ณ , ๊ฐ API๋ค์ ๊ธฐ๋ฅ์ ์ด๋ฒ ๊ธ์์ ์ดํด๋ณธ ์ค๋ฒ๋ ์ด(Overlay) ๊ธฐ๋ฅ๋ค๊ณผ ๊ฒฐํฉํ์ฌ ์ข ๋ ์ค์ฉ์ ์ธ UI๋ฅผ ๊ตฌํํ์ฌ ์๊ฐํด ๋ณด๋๋ก ํ๊ฒ ๋ค.
๊ธด ๊ธ ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค โ๏ธ