ํ๋ก์ ํธ์์ ์ง์ญ์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ธ๊ตฌ์ง ๊ฒ์๊ธ์ ๋ฑ๋กํ๊ณ ๊ฒ์ํ๋ ๊ธฐ๋ฅ์ ๊ฐ๋ฐํ๊ฒ ๋์๋ค.
์ด ๊ธฐ๋ฅ์ ๊ฐ๋ฐํ๊ธฐ ์ํด ์ค๊ณ์ ๋ง์ ๊ณ ๋ฏผ์ ํ๊ณ , ๊ตฌํ์ ๋ง์ ์๊ฐ์ ํฌ์ํ๊ฒ ๋์๋ค. ๊ทธ ๊ณผ์ ์ ๋์ง์ด๋ณด๊ณ ๊ณต์ ํ๊ณ ์ ํ๋ค!
๊ตฌํ์ ์ํด ๋น์ทํ๊ฒ ๋๋ค ๊ธฐ๋ฐ์ ์๋น์ค(๋น๊ทผ๋ง์ผ, ๋ฐฐ๋ฏผ..)์์ ์ด๋ฌํ ๊ธฐ๋ฅ์ ์ด๋ป๊ฒ ๊ตฌํํ๋์ง ๋ง์ด ์ฐพ์๋ดค์๋ค. ์ ํํ ์ด๋ป๊ฒ ๊ตฌํํ๋์ง๋ ์ ์ ์์์ง๋ง, ๋ค๋ฅธ ์ฌ๋๋ค์ ๋น๊ทผ๋ง์ผ ํด๋ก ์ฝ๋ฉ๊ณผ ์ฌ๋ฌ ํ ํฌ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํ์ฌ ๋๋ฆ๋๋ก ํ๋ก์ ํธ์ ๋ง๊ฒ ํด๋น ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์๋ค.
๊ธฐ๋ฅ ์๊ฐ
๊ตฌ์ธ๊ตฌ์ง ๊ฒ์๊ธ ๋ฑ๋ก
- ๊ฒ์๊ธ ์์ฑ ์, ๊ตฌ์ธ๊ตฌ์ง์ ์์ธ ์กฐ๊ฑด๊ณผ ๊ฑฐ์ ์ง์ญ(ex. ์์ธํน๋ณ์ ๊ฐ๋จ๊ตฌ ์ญ์ผ๋)์ ์ ๋ ฅํ๋ค.
๊ตฌ์ธ๊ตฌ์ง ๊ฒ์๊ธ ๊ฒ์
- ๊ฒ์๊ธ ๊ฒ์ ์, ๊ฑฐ์ ์ง์ญ(ex. ์์ธํน๋ณ์ ๊ฐ๋จ๊ตฌ ์ญ์ผ๋)์ ์ ํํ๊ณ , ๊ทธ ๋ฐ๊ฒฝ(nkm)๋ฅผ ์ ํํ ์ ์๋ค.
์ ์ฌ ์๋น์ค ๋ถ์
๊ฒฐ๊ตญ ๋ด๊ฐ ๊ตฌํํด์ผ ํ๋ ๊ธฐ๋ฅ์ ๋๋ค ๊ธฐ๋ฐ์ ์ค๊ณ ๋ฌผํ ๊ฑฐ๋ ์๋น์ค์ธ '๋น๊ทผ๋ง์ผ'๊ณผ ์ ์ฌํ๋ค. ๋น๊ทผ๋ง์ผ์ GPS๋ก ์ธ์ฆ๋ ์ฌ์ฉ์์ ๋๋ค ์ฃผ๋ณ์ ์ค๊ณ ๊ฒ์๊ธ์ ๋ณด์ฌ์ค๋ค.
- ๋๋ค ๋ฒ์(๊ฐ๊น์ด ๋๋ค~๋จผ ๋๋ค)๋ฅผ ๋ณ๊ฒฝํ๋ฉด, ํ ํ๋ฉด์ ๋ณด์ฌ์ง๋ ๊ฒ์๊ธ์ ๋ฒ์๊ฐ ๋ฌ๋ผ์ง๋ค.
- ๋๋ค์ ๋ฒ์๋ ๊ฐ๊น์ด ๋๋ค๋ถํฐ ๋จผ ๋๋ค๊น์ง 4๋จ๊ณ๋ก ์ค์ ํ ์ ์๋ค.
- ๋จ๊ณ ๋ณ ๋๋ค๊ฐ ์ ํด์ ธ ์๋ค.
- ๋๋ค๋ ํ์ ๋์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ค.
๋น๊ทผ์ ์ด๋ฏธ 4๋จ๊ณ๋ก ๋ด ๊ทผ์ฒ ๋๋ค๊ฐ ์ ํด์ ธ ์๋ ๊ฒ ๊ฐ๋ค. ๊ทผ์ฒ ๋๋ค๊ฐ ๋น๊ทผ์์ ์ ํ ์ด๋ ํ ๊ธฐ์ค์ผ๋ก ๋ฏธ๋ฆฌ ๊ณ์ฐ๋์ด ๋ฐ๋ก ์ ์ฅ๋์ด ์์ง ์์๊น..
๋ด ํ๋ก์ ํธ๋ ์ ์ ๊ฐ ๊ฒ์ํ ๋๋ง๋ค km๋ฅผ ์กฐ์ ํด ๋๋ค์ ๋ฒ์๋ฅผ ์กฐ์ ํด์ผ ํ๋ค. ์ด ๋ถ๋ถ์์ ๋ค๋ฅด๋ค.
๋๋ค๋ฅผ ์ด๋ป๊ฒ ๋ค๋ฃฐ๊น?
1. ๋๋ค ๋ถ๋ฅ ์ฒด๊ณ : ๋ฒ์ ๋๊ณผ ํ์ ๋
์ฐ์ , ์ ๊ตญ์ ๋ชจ๋ ๋๋ค๋ฅผ ์์๋ด์ผ ํ๋ค. ์ฐ๋ฆฌ๋๋ผ์์ ๋๋ค๋ฅผ ๋ถ๋ฅํ๋ ๋ฐฉ๋ฒ์ ํฌ๊ฒ 2๊ฐ์ง๊ฐ ์๋ค.
๋ฒ์ ๋
- ๋ฒ๋ฅ ๋ก ์ง์ ํ ๊ณ ์ ์ง๋ช . ๋ฒ์ ๋ฌธ์์ ์ฌ์ฉํ๋ค.
- ๋ช ์นญ ๋ณ๋์ด ๊ฑฐ์ ์๋ค.
ํ์ ๋
- ํ์ ํธ์๋ฅผ ์ํด ์ค์ ํ ๊ตฌ์ญ. ํ์ ๋๋ง๋ค ์ฃผ๋ฏผ์ผํฐ๊ฐ ์๋ค.
- ์ฃผ๋ฏผ ์์ ์ฆ๊ฐ์ ๋ฐ๋ผ ์์๋ก ์ค์น, ํ์ง๋ ์๋ ์๋ค.
๋ฒ์ ๋๊ณผ ํ์ ๋์ ์ฐจ์ด๋ ์ด๋ฆ์ ๋ณด๋ฉด ์ ์ ์๋ค. ์์ ์ฒจ๋ถ๋ ์ด๋ฏธ์ง๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด, ์๋ฅผ ๋ค์ด, ์์ธ ํน๋ณ์ ์ข ๋ก๊ตฌ์ ๋ฒ์ ๋์ผ๋ก ์ฒญ์ด๋, ํจ์๋ ๋ฑ์ด ์๋ค. ํ์ง๋ง, ํ์ ๋์ผ๋ก๋ ๋ช ์นญ์ด ์ฒญ์ดํจ์๋์ผ๋ก ํตํฉ๋์ด ์๋ค.
์กํ๊ตฌ์ฒ๋ผ ์ธ๊ตฌ๊ฐ ๋ง์ ๋ฒ์ ๋์ด๋ผ๋ฉด ํ ๋ฒ์ ๋์ ํ์ ๋์ด ์ฌ๋ฌ ๊ฐ ์๊ธธ ์๋ ์๋ค. ๋ฐ๋๋ก ์ธ๊ตฌ๊ฐ ์ ์ผ๋ฉด ๋ฒ์ ๋ ์ฌ๋ฌ๊ฐ๋ฅผ ํ๋์ ํ์ ๋์ผ๋ก ๋ฌถ์ ์๋ ์๋ค.
๋ฐ๋ผ์, ์ด๋ค ๋ถ๋ฅ ์ฒด๊ณ๋ฅผ ์ฐ๋์ง์ ๋ฐ๋ผ ๋๋ค ๋ถ๋ฅ์ ๊ทผ์ฒ ๋๋ค์ ๋ฒ์๊ฐ ๋ฌ๋ผ์ง๊ฒ ๋๋ค.
2. ๋ฒ์ ๋ ์ ํ ์ด์
์ด์ ๋ถํฐ ํ๋ก ํธ์๋์์ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ํ๋ฉด์ ๊ตฌํํ๋ฉด์ ํ์ ๋ ์ฒด๊ณ๋ฅผ ์ฐ๊ณ ์์๋ค. ๊ทธ๋์ ๋ฐฑ์๋์์๋ ํ์ ๋ ์ฒด๊ณ๋ฅผ ์ฐ๊ธฐ๋ก ํ๋ค.
ํ์ง๋ง, ํ์ ๋ ์ฒด๊ณ๋ก ๊ตฌํ ์ค์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. ๊ฒฐ๊ตญ ๊ทธ๋์ ๋ฒ์ ๋ ์ฒด๊ณ๋ก ๋ฐ๊พธ๊ฒ ๋์๋ค.
1) ์นด์นด์ค๋งต API ๊ฒ์ ๊ณผ์ ์์ ์๋ฌ
๋ค์์ ์ค๋ช ํ๊ฒ ์ง๋ง, ์์ ๋ก ์ป๊ฒ ๋ ๋ชจ๋ ๋๋ค์ ์ขํ๊ฐ์ ์ป๊ธฐ ์ํด ์นด์นด์ค๋งต API๋ฅผ ์ฌ์ฉํ๊ฒ ๋์๋ค. ํ์ง๋ง, ์์ ๋ฐ์ดํฐ์ ์นด์นด์ค๋งต ์์ ํ์ ๋๊ณผ ๋ช ์นญ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ๊ฐ ์์ด ๊ฒ์์ด ์ ๋์๋ค.
ex)
์์ ๋ฐ์ดํฐ ์ - ์์ธ ์ค๋๊ตฌ ๋ฉด๋ชฉ์ 3.8๋
์นด์นด์ค ์ง๋ ์ - ์์ธ ์ค๋๊ตฌ ๋ฉด๋ชฉ 3.8๋
2) ์ ์ง๋ณด์ ์ธก๋ฉด์์ ์ ๋ฆฌ
ํ์ ๋์ ๋ฌธ์ ์ ์ ํ์ ์ ํธ์๋ฅผ ์ํด ์ธ๊ตฌ์๋ก ๋ช ์นญ๊ณผ ์์ญ์ ์ ํ๊ธฐ ๋๋ฌธ์ ๋ณ๋์ด ์ฆ๋ค๋ ๊ฒ์ด๋ค. ์ ์ง๋ณด์์ ์๊ฐํ๋ค๋ฉด ๋ช ์นญ ๋ณ๋์ด ๊ฑฐ์ ์๋ ๋ฒ์ ๋์ด ์ ๋ฆฌํ๋ค.
์ฐธ๊ณ ) ๋ฐฐ๋ฏผ์์๋ ์ง๋ฆฌ ๊ด๋ฆฌ ์ฒด๊ณ๋ฅผ ํ์ ๋์์ ๋ฒ์ ๋์ผ๋ก ์ ํํ๋ ์ด์ผ๊ธฐ๊ฐ ์๋ค. ํ์ ๋ ๋ฌธ์ ํด๊ฒฐํ๋ ค๊ณ ๊ฒ์ํ๋ค๊ฐ ๋ฐ๊ฒฌํ๋ค!
3. ๊ทผ์ฒ ๋๋ค๋ฅผ ์ด๋ป๊ฒ ์ ์ ์์๊น?
์ฐ์ , ๋ฒ์ ๋์ฝ๋์ ๊ท์น์ด ์๋์ง ์ดํด๋ดค๋ค. ๊ทผ์ฒ ๋๋ค ๊ฐ ์ฝ๋๊ฐ ์ ์ฌํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ด๋ค.
ํ์ง๋ง, ๋ฒ์ ๋์ฝ๋์ ์ฐจ์ด๊ฐ ์๋ค๊ณ ํด์ ๊ฑฐ๋ฆฌ๊ฐ ๊ฐ๊น์ด ๋๋ค๋ ์๋๋ค. ๊ฒฝ๊ธฐ๋ ์ฑ๋จ์์ ์์ ๋ถ์๋ ์ฝ๋์ ์ซ์๊ฐ ์๋ก ๊ฐ๊น์ง๋ง, ์ค์ ๋ก ๊ฑฐ๋ฆฌ๋ ๊ฒฝ๊ธฐ ๋จ๋ถ์ ๋ถ๋ถ๋ก ์์ฒญ๋ ์ฐจ์ด๊ฐ ์๋ค.
๊ทธ๋ ๋ค๋ฉด, ๋๋ค ์ฌ์ด์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํ์ฌ ๊ทผ์ฒ ๋๋ค๋ฅผ ๊ตฌํด์ผ ํ๋ค.
๊ฒฐ๊ตญ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํ๋ ค๋ฉด ๊ฐ ๋๋ค ๋ณ ์ขํ๋ฅผ ์์์ผ ํ๋ค.
๋๋ค ๋ณ ์ขํ ๊ตฌํ๊ธฐ
1. ์ ์ฒด ๋๋ค ๋ฐ์ดํฐ ๊ตฌํ๊ธฐ
์ ๊ตญ์ ๋ฒ์ ๋ ๋ฐ์ดํฐ๋ ํ์ ์์ ๋ถ ์๋ฃ๋ฅผ ํตํด์ xlsx(์์ ) ํ์ผ๋ก ์ป์ ์ ์์๋ค.
xlsx ํ์ผ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ ์ ์๋ Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ์ ๊ตญ์ ๋ชจ๋ ๋๋ค์ ์๋์ฝ๋, ์๋๋ช , ์๊ตฐ๊ตฌ๋ช , ์๋ฉด๋๋ช ์ ์ถ์ถํด DB์ ์ ์ฅํ๋ค.
์์ธํ ๊ณผ์ ์ ์๋ ํฌ์คํธ์์ ๋ณด๋ฉด ๋๋ค.
https://programmingiraffe.tistory.com/184
2. ์ ์ฒด ๋๋ค ์ขํ ๊ตฌํ๊ธฐ
ํ์ง๋ง, ๋ฒ์ ๋ ๋ณ ์ขํ๊ฐ์ ๋ฐ๋ก ํ์ผ๋ก ์ป๊ธฐ ํ๋ค์๊ณ , ์๋ค ํ๋๋ผ๋ ํ๋์ ์ขํ(์๋, ๊ฒฝ๋)๋ก ์ถ์ถํ๊ธฐ๊ฐ ์ด๋ ค์ ๋ค.
๊ทธ๋์ ์นด์นด์ค๋งต API๋ฅผ ์ฌ์ฉํ์ฌ ๋ฒ์ ๋์ ์ง๋์์ ๊ฒ์ํด ์ขํ(์๋, ๊ฒฝ๋)๋ก ๋ณํํ๋๋ก ํ๋ค. ์ด ๋ถ๋ถ ๋ํ, ๋ฒ์ ๋ ์ถ์ถํ๋ ๋ถ๋ถ๊ณผ ํจ๊ป Python์ผ๋ก ์นด์นด์ค API์ ํต์ ํด์ ์๋, ๊ฒฝ๋ ๊ฐ์ ๊ฐ์ ธ์ DB์ ์ ์ฅํ๋๋ก ํ๋ค.
์์ธํ ๊ณผ์ ์ ์๋ ํฌ์คํธ์์ ๋ณด๋ฉด ๋๋ค.
https://programmingiraffe.tistory.com/185
๋ฐ๊ฒฝ nKm ์ด๋ด ๋๋ค ๊ฒ์ํ๊ธฐ
์ฌ์ฉ์์ ๊ฑฐ์ ์ง์ญ ๊ทผ์ฒ์ ๊ฒ์๊ธ์ ๊ฒ์ํ๊ธฐ ์ํด์ ์ฐ์ ๊ฑฐ์ ์ง์ญ์ผ๋ก๋ถํฐ nKm ์ด๋ด์ ์๋ ๋๋ค๋ฅผ ์์์ผ ํ๋ค.
์ฐ์ ๊ณ ๋ คํ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
1) DB์์ ์ง์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํด ๊ฒ์ํ๋ ๋ฐฉ๋ฒ
2) Geocoding ๊ด๋ จ API๋ฅผ ์ฌ์ฉ(https://nominatim.org/)
ํธํ๊ฒ ๊ตฌํํ๊ธฐ ์ํด์ ์ฒ์์๋ API๋ฅผ ์ฌ์ฉํ๋๋ฐ, ์ํ ์๊ฐ์ด 12์ด๋ก ์์ฒญ ์ค๋ ๊ฑธ๋ ค์ ์ง์ DB์์ ๊ณ์ฐ์ ํ๊ธฐ๋ก ํ๋ค!
1. ์ฟผ๋ฆฌ๋ก ๊ฑฐ๋ฆฌ ๊ณ์ฐํ๊ธฐ
MySQL ์ฟผ๋ฆฌ ์ค์ ๋ ์ขํ ์ฌ์ด์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํ๋ ํจ์๊ฐ ์๋ค.
ST_DISTANCE_SPHERE(POINT(lng1, lat1), POINT(lng2, lat2))
๊ฒฝ๋, ์๋๋ก ๋ ๋ POINT๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.
@Query(
value = "SELECT address_code " +
"FROM address " +
"WHERE ST_Distance_Sphere(POINT(:lng, :lat), POINT(lng, lat)) <= :distance * 1000 ",
nativeQuery = true
)
List<String> getNearbyAddressCode(@Param("lat") double lat,
@Param("lng") double lng,
@Param("distance") Integer distance);
๊ทผ์ฒ ๋๋ค๋ฅผ ๊ฒ์ํ๋ ๋ฐ๋ง 20ms์ ์๊ฐ์ด ์์๋์๋ค.
์บ์๋ฅผ ์ฌ์ฉํด ์ต์ ํ
ํ์ง๋ง ๋งค๋ฒ ๊ฒ์๊ธ ๊ฒ์ ์์ฒญ์ด ๋ค์ด์ฌ ๋๋ง๋ค DB์์ ์ฟผ๋ฆฌ๋ก ๊ทผ์ฒ ๋๋ค๋ฅผ ๊ฒ์ํด์ผ ํ๋ค. ๋งค๋ฒ ๊ทผ์ฒ ๋๋ค๋ฅผ ๊ณ์ฐํ๋ ๊ฒ์ ๋นํจ์จ์ ์ธ ์์ ์ด๋ค. ํธ๋ํฝ์ด ์ปค์ ์์ฒญ์ด ๋ง์์ง๊ฒ ๋๋ค๋ฉด, ๋งค๋ฒ ๊ทผ์ฒ ๋๋ค๋ฅผ ๊ฒ์ํ๋ ๊ฒ์ ์ถ๊ฐ์ ์ธ ๋ถ๋ด์ด ๋ ๊ฒ์ด๋ค.
๊ทธ๋์ ์บ์ฑ์ ํ๊ธฐ๋ก ํ๋ค.
๋ก์ปฌ ์บ์ vs Redis ์บ์
์บ์ฑ์ ํ๋ ๋ฐ, ์คํ๋ง ์๋ฒ ๋ด์ ๋ก์ปฌ ์บ์๋ฅผ ์ฐ๊ฑฐ๋ ์ธ๋ถ์์ Redis์ ๊ฐ์ ์บ์๋ฅผ ์ธ ์ ์๋ค. ์ด ๊ธฐ๋ฅ์ ์ต์ ํํ๋ ๋ฐ, ๋ก์ปฌ ์บ์๋ฅผ ์ฐ๊ธฐ๋ก ํ๋ค.
- ์ธ๋ถ์ ๋ฐ๋ก Redis๋ฅผ ๊ตฌ์ฑํ๋ ๊ฒ์ ์ถ๊ฐ์ ์ธ ๊ด๋ฆฌ์ ๋น์ฉ์ด ๋ค๊ธฐ ๋๋ฌธ์ด๋ค.
- ๊ทผ์ฒ ๋๋ค ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฅธ ์๋ฒ์ ๊ณต์ ํ ํ์๊ฐ ์๋ค.
- ๋ฐ์ดํฐ์ ํฌ๊ธฐ๊ฐ ์์์ ์๋ฒ ๋ฉ๋ชจ๋ฆฌ๋ก๋ ์ถฉ๋ถํ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค.
๊ตฌํ
์ด๊ธฐํ ์, ๊ฐ ๋ฒ์ ๋ ์ฝ๋์ ๋ฐ๊ฒฝ๋ณ๋ก ๊ทผ์ฒ ๋๋ค๋ฅผ ๊ณ์ฐํ์ฌ ๋ก์ปฌ ์บ์์ ์ ์ฅํ๋๋ก ํ๋ค.
@Component
@RequiredArgsConstructor
public class AddressCacheInitializer {
private final AddressRepository addressRepository;
private final CacheManager cacheManager;
@PostConstruct
public void initializeCache() {
List<Address> addressList = addressRepository.findAll(); // DB์์ ๋ฒ์ ๋ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
Cache cache = cacheManager.getCache("nearbyAddresses"); // ์บ์ ๊ฐ์ ธ์ค๊ธฐ
for (Address address : addressList) {
for (int km = 1; km <= 5; km++) {
List<String> nearbyAddresses = calculateNearby(address, addressList, km);
String cacheKey = address.getAddressCode() + "-" + km; // ์บ์ ํค ์ค์
cache.put(cacheKey, nearbyAddresses); // ์บ์์ ์ ์ฅ
}
}
}
@Cacheable(value = "nearbyAddresses", key = "#addressCode + '-' + #km")
public List<String> getNearbyAddresses(String addressCode, int km) {
throw new IllegalStateException("Data should be preloaded into the cache.");
}
private List<String> calculateNearby(Address current, List<Address> allAddresses, double maxDistance) {
double latDiff = maxDistance / 6371.0 * (180 / Math.PI);
double lonDiff = maxDistance / (6371.0 * Math.cos(Math.toRadians(current.getLat()))) * (180 / Math.PI); // ๊ฒฝ๋ ๋ฒ์
double minLat = current.getLat() - latDiff;
double maxLat = current.getLat() + latDiff;
double minLon = current.getLng() - lonDiff;
double maxLon = current.getLng() + lonDiff;
return allAddresses.stream()
.filter(other -> !other.getAddressCode().equals(current.getAddressCode()))
.filter(other -> other.getLat() >= minLat && other.getLat() <= maxLat)
.filter(other -> other.getLng() >= minLon && other.getLng() <= maxLon)
.filter(other -> calculateDistance(current, other) <= maxDistance) // ์ต์ข
๊ฑฐ๋ฆฌ ํ์ธ
.map(Address::getAddressCode)
.collect(Collectors.toList());
}
private double calculateDistance(Address a, Address b) {
final double EARTH_RADIUS = 6371.0;
double latDistance = Math.toRadians(b.getLat() - a.getLat());
double lonDistance = Math.toRadians(b.getLng() - a.getLng());
double haversine = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
+ Math.cos(Math.toRadians(a.getLat())) * Math.cos(Math.toRadians(b.getLng()))
* Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
return 2 * Math.atan2(Math.sqrt(haversine), Math.sqrt(1 - haversine)) * EARTH_RADIUS;
}
}
- initializeCache() : ์ดํ๋ฆฌ์บ์ด์ ์์ ์ ์ด๊ธฐํ ์์ ์ด ์ด๋ฃจ์ด์ง๊ฒ ๋๋ค. ๊ทผ์ฒ ๋๋ค๋ฅผ ๊ณ์ฐํด `๋ฒ์ ๋์ฝ๋-๊ฑฐ๋ฆฌ` key๋ก ํ์ฌ ๋ก์ปฌ ์บ์์ ์ ์ฅํ๋ค.
- getNearbyAddresses(String addressCode, int km) : ๋ฒ์ ๋ ์ฝ๋์ ๋ฐ๊ฒฝ์ ํด๋นํ๋ ๊ทผ์ฒ ๋๋ค๋ฅผ ๋ก์ปฌ ์บ์์์ ๊ฒ์ํด ๋ฐํํ๋ค.
๊ฒฐ๊ณผ
์ดํ๋ฆฌ์บ์ด์ ์ด ์์๋ ๋, 5033๊ฐ ๋ฒ์ ๋์ ๊ทผ์ฒ ๋๋ค ๋ฐ์ดํฐ๊ฐ ๋ค์ด๊ฐ๋ค.
์บ์ฑ์ ์ ์ฉํ๋ ๊ทผ์ฒ ๋๋ค๋ฅผ ๊ฒ์ํ๋ ๋ฐ, ์ฝ 0.1ms ์๊ฐ์ด ์์๋์๋ค.