주소에서 좌표값 얻기

개요

주소 데이터를 기반으로 지도에 위치를 표기하는 방법을 알아보겠습니다. 이번 글에서는 서울에 있는 고등교육기관 주소 데이터를 활용해 지오코딩(주소를 좌표로 변환)을 수행하고, 이를 지도에 시각화하는 과정을 단계별로 설명합니다.

데이터 준비하기

먼저, 교육통계서비스의 알림·서비스 > 자료실에서 고등교육기관 주소록 데이터를 다운로드합니다. 이 데이터에는 학교명과 주소 정보가 포함되어 있습니다. 지난번 생성한 수도권 지도를 불러오고, 고등교육기관 주소록 데이터를 읽어옵니다.

# 패키지 로드
library(tidyverse)
library(sf)
library(ggplot2)
library(showtext)
library(ggrepel)
library(readxl)
library(writexl)

# 글꼴 설정
font_add("kopub", "C:/Users/.../AppData/Local/Microsoft/Windows/Fonts/KoPub Dotum Medium.ttf")
showtext_auto()
showtext_opts(dpi=300)

theme.size = 8
text.size = theme.size / .pt

# 데이터 불러오기
sdg <- st_read("아웃풋/수도권 행정구 병합 지도.shp") %>% 
    separate(col = SGG_NM,
           into = c("SD_NM", "SGG_NM"),
           sep = " ",
           fill = "right")
## Reading layer `수도권 행정구 병합 지도' from data source 
##   `...\아웃풋\수도권 행정구 병합 지도.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 66 features and 2 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -10044.95 ymin: 477264 xmax: 274945.2 ymax: 631207.8
## Projected CRS: Korea_2000_Korea_Central_Belt_2010
# 고등교육기관 주소록 데이터 불러오기
univ <- read_xlsx("데이터/고등교육기관 주소록(2024.4.1.).xlsx", skip = 5)

# 데이터 확인하기
head(univ)
## # A tibble: 6 × 15
##   연도  학교종류 시도  행정구 학교명 `학교명(영문)` KEDI학교코드 본분교 학교상태
##   <chr> <chr>    <chr> <chr>  <chr>  <chr>          <chr>        <chr>  <chr>   
## 1 2024  대학교   강원  강원 … 국립…  Gangneung-Won… 51001000     본교(… 학교명… 
## 2 2024  대학교   강원  강원 … 국립…  Gangneung-Won… 51001000     본교(… 학교명… 
## 3 2024  일반대…  강원  강원 … 국립…  Gangneung-Won… 51001600     본교(… 학교명… 
## 4 2024  일반대…  강원  강원 … 국립…  Gangneung-Won… 51001600     본교(… 학교명… 
## 5 2024  특수대…  강원  강원 … 국립…  Gangneung Won… 51001607     본교(… 학교명… 
## 6 2024  특수대…  강원  강원 … 국립…  Gangneung Won… 51001607     본교(… 학교명… 
## # ℹ 6 more variables: 설립 <chr>, 우편번호 <chr>, 주소 <chr>, 전화번호 <chr>,
## #   팩스번호 <chr>, 홈페이지 <chr>

서울만 시각화할 예정이므로, 서울 지역에 해당하는 데이터만 추출합니다. 추출한 데이터를 엑셀 파일로 저장해 다음 단계에서 활용합니다.

# 서울 지도만 추출하기
sdg_seoul <- sdg %>% 
    filter(SD_NM == "서울특별시")

# 서울 고등교육기관 데이터 추출하기
univ_seoul <- univ %>% 
  filter(시도 == "서울")

# 서울 고등교육기관 데이터 저장하기
write_xlsx(univ_seoul, "아웃풋/서울 고등교육기관 주소록.xlsx")

지오코딩으로 주소에서 좌표값 찾기

주소를 위도(latitude)와 경도(longitude)로 변환하는 과정을 지오코딩(Geocoding)이라고 합니다. R에서도 지오코딩을 수행할 수 있지만, 구글 맵 API 키가 필요하고 유료로 사용해야 하는 제약이 있습니다. 대신, 이번에는 무료로 사용할 수 있는 지오서비스 웹을 활용합니다.

지오서비스 웹은 아래 순서로 사용할 수 있습니다.

  1. 로그인 후 아카이브에 ’서울 고등교육기관 주소록.xlsx` 파일을 업로드합니다.
  2. 상단 메뉴에서 변환 > 지오코딩 > 주소를 좌표로 변환을 클릭합니다.
  3. 업로드한 파일을 선택하고, 주소 필드에 주소 열을 지정합니다.
  4. 변환이 완료된 파일을 다운로드합니다.

변환된 데이터를 R로 불러옵니다.

# 지오코딩된 데이터 불러오기
univ <- st_read("데이터/서울 고등교육기관 지오코딩/a.shp")
## Reading layer `a' from data source 
##   `...\데이터\서울 고등교육기관 지오코딩\a.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 565 features and 17 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: 126.8145 ymin: 37.46644 xmax: 127.1327 ymax: 37.65177
## Geodetic CRS:  WGS 84
# 데이터 확인하기
head(univ)
## Simple feature collection with 6 features and 17 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: 126.9524 ymin: 37.4674 xmax: 127.0781 ymax: 37.63234
## Geodetic CRS:  WGS 84
##   field1     field2 field3      field4                        field5
## 1   2024     대학교   서울 서울 종로구                    서울대학교
## 2   2024 일반대학원   서울 서울 종로구         서울대학교 일반대학원
## 3   2024     대학교   서울 서울 관악구                    서울대학교
## 4   2024 전문대학원   서울 서울 종로구       서울대학교 치의학대학원
## 5   2024 일반대학원   서울 서울 관악구             서울대학교 대학원
## 6   2024 일반대학원   서울 서울 노원구 서울과학기술대학교 일반대학원
##                                          field6   field7          field8 field9
## 1                     Seoul National University 51012000 본교(제2캠퍼스)   기존
## 2  Graduate School of Seoul National University 51012600 본교(제2캠퍼스)   기존
## 3                     Seoul National University 51012000 본교(제1캠퍼스)   기존
## 4 Seoul National University School of Dentistry 51012B54 본교(제2캠퍼스)   기존
## 5  Graduate School of Seoul National University 51012600 본교(제1캠퍼스)   기존
## 6                               Graduate School 51027600 본교(제1캠퍼스)   기존
##      field10 field11                                                   field12
## 1 국립대법인    3080                                    서울 종로구 대학로 103
## 2 국립대법인    3080                                    서울 종로구 대학로 103
## 3 국립대법인    8826           서울특별시 관악구 관악로 1 (신림동, 서울대학교)
## 4 국립대법인    3080                                    서울 종로구 대학로 103
## 5 국립대법인    8826           서울특별시 관악구 관악로 1 (신림동, 서울대학교)
## 6       국립    1811 서울특별시 노원구 공릉로 232 (공릉동, 서울과학기술대학교)
##       field13     field14
## 1 02-880-5114 02-885-5272
## 2 02-880-5114 02-885-5272
## 3 02-880-5114 02-885-5272
## 4 02-740-8611 02-745-1906
## 5 02-880-5114 02-885-5272
## 6 02-970-6114 02-970-6800
##                                                     field15 X_GC_TYPE
## 1                                             www.snu.ac.kr        정
## 2 https://www.snu.ac.kr/academics/graduate/graduate_schools        정
## 3                                             www.snu.ac.kr        정
## 4                                       dentistry.snu.ac.kr        정
## 5 https://www.snu.ac.kr/academics/graduate/graduate_schools        정
## 6                                       www.seoultech.ac.kr        정
##                             X_CLEANADDR                  geometry
## 1 서울특별시 종로구 대학로 103 (연건동) POINT (126.9996 37.58097)
## 2 서울특별시 종로구 대학로 103 (연건동) POINT (126.9996 37.58097)
## 3   서울특별시 관악구 관악로 1 (신림동)  POINT (126.9524 37.4674)
## 4 서울특별시 종로구 대학로 103 (연건동) POINT (126.9996 37.58097)
## 5   서울특별시 관악구 관악로 1 (신림동)  POINT (126.9524 37.4674)
## 6 서울특별시 노원구 공릉로 232 (공릉동) POINT (127.0781 37.63234)

데이터는 총 565개로 지도에 표기하기에는 많아서 대학교만 추출하고 중복된 학교명을 정리하겠습니다. 이렇게 정리하면, 총 41개 학교가 남습니다.

# 대학교 데이터 추출 및 정리하기
univ_tmp <- univ %>% 
  filter(field2 == "대학교") %>% 
  select(field5, geometry) %>% 
  rename(학교명 = field5) %>% 
  group_by(학교명) %>% 
  filter(row_number() == 1)

# 데이터 확인하기
head(univ_tmp)
## Simple feature collection with 6 features and 1 field
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: 126.9996 ymin: 37.50174 xmax: 127.1327 ymax: 37.63234
## Geodetic CRS:  WGS 84
## # A tibble: 6 × 2
## # Groups:   학교명 [6]
##   학교명                        geometry
##   <chr>                      <POINT [°]>
## 1 서울대학교         (126.9996 37.58097)
## 2 한국체육대학교     (127.1327 37.52127)
## 3 가톨릭대학교       (127.0047 37.50174)
## 4 건국대학교         (127.0788 37.54164)
## 5 서울과학기술대학교 (127.0781 37.63234)
## 6 서울시립대학교     (127.0556 37.58431)

지도에 맵핑하기

서울 지도와 지오코딩된 데이터의 좌표계가 다를 경우, 데이터를 지도와 동일한 좌표계로 변환해야 합니다. 서울 지도 좌표계는 ‘EPSG: 9001’, 고등교육기관 데이터 좌표계가 ’EPSG: 4326’으로 되어 있어서 고등교육기관 데이터 좌표계를 서울 지도 좌표계로 변환하겠습니다.

# 좌표계 변환하기
univ_final <- univ_tmp %>% 
  st_transform(crs = st_crs(sdg_seoul))

geom_sf로 먼저 서울 지도를 그리고, 두 번째 geom_sf로 지도 위에 고등교육기관 위치를 점으로 표시합니다. shape = 21로 설정하면 점의 외곽선(color)과 내부 색(fill)을 분리해서 설정할 수 있습니다. 서울 지도에 41개 위치를 표기하면 텍스트가 겹칠 가능성이 있기 때문에, geom_text_repel 함수를 이용해 텍스트를 표기하겠습니다.

# 지도 작성하기
ggplot() +
  geom_sf(data = sdg_seoul, color = "gray40", fill = "#eaeaea", linewidth = 0.5) +
  geom_sf(data = univ_final, 
          shape = 21,
          size = 4,
          stroke = 0.1,
          color = "white", fill = "#00D353") +
  geom_text_repel(data = univ_final, 
                  aes(label = 학교명, geometry = geometry),
                  stat = "sf_coordinates",
                  family = "kopub",
                  size = text.size,
                  force = 0.001,
                  force_pull = 1000,
                  color = "white",
                  bg.color = "black",
                  bg.r = 0.1,
                  segment.color = "gray") +
  theme_void()

서울 소재 대학교 위치를 나타낸 지도

이렇게 해도 29개 라벨이 겹치는 문제가 발생합니다. 학교명에서 ’대학교’를 제거해 텍스트 길이를 줄이고, geom_text_repel에서 max.overlaps = Inf으로 지정해 텍스트가 모두 표시되도록 설정합니다.

# 학교명에서 대학교 제거하기
univ_cnt <- univ_final %>% 
  mutate(학교명 = sub("대학교", "", 학교명))

# 지도 작성하기
ggplot() +
  geom_sf(data = sdg_seoul, color = "gray40", fill = "#eaeaea", linewidth = 0.5) +
  geom_sf(data = univ_final, 
          shape = 21,
          size = 4,
          stroke = 0.1,
          color = "white", fill = "#00D353") +
  geom_text_repel(data = univ_cnt, 
                  aes(label = 학교명, geometry = geometry),
                  stat = "sf_coordinates",
                  family = "kopub",
                  size = text.size,
                  force = 0.001,
                  force_pull = 1000,
                  color = "white",
                  bg.color = "black",
                  bg.r = 0.1,
                  segment.color = "gray",
                  max.overlaps = Inf) +
  theme_void()

서울 소재 대학교 위치를 나타낸 지도 테마 수정

이번 글에서는 주소 데이터를 활용해 지오코딩을 수행하고, 얻은 좌표값을 지도에 표시하는 과정을 살펴보았습니다. 무료 지오코딩 서비스를 활용해 데이터를 변환하고, 이를 R에서 정리한 뒤 맵핑하는 전체 과정을 따라해 보세요. 지오코딩은 위치 기반 데이터 시각화에 필수적인 기술로, 매우 유용하게 쓰일 수 있습니다.