Inside

하나의 지도가 만들어지기까지

데이터 시각화의 첫 발걸음
임상아 뉴스룸 디벨로퍼|동아일보 디프런티어센터 2022-02-23 07:31:10
히어로콘텐츠를 통해 독자들에게 새로운 경험을 주기 위해 여러 시도를 했다. 특히 이번 히어로콘텐츠팀 4기 ‘공존’은 경기도 안산을 중심으로 이야기가 전개됐기 때문에 처음부터 지도를 활용한 그래픽을 쓰자는 논의가 나왔다. 앞서 ‘동행’에서 지도 그래픽을 제작한 경험이 있었고, 데이터 시각화에 관심이 있었기 때문에 지도 제작을 맡게 됐다.

지도를 기사 어느 부분에 삽입할 지 논의한 끝에 인트로 페이지에 활용하기로 결정했다. 인트로 페이지의 역할은 기사에 대한 독자들의 호기심을 최대로 끌어내는 것이었다. 그렇게 하기 위해 ‘시각적인 자극’을 주기로 했다.

데이터를 시각화하면 추상적이고, 잘 체감할 수 없는 내용을 한 눈에, 직관적으로 전달할 수 있다는 장점이 있다. 그래서 지도를 통해 우리나라의 현실이자 미래를 직관적으로 보여주고자 했다.

한국에서 외국인이 가장 많이 사는 도시인 안산에서, 전국 지도로 줌아웃되며 외국인 비율 5% 이상인 도시가 표시되는 그래픽을 제작하기로 했다. 이 그래픽을 통해 안산과 같은 지역이 앞으로 더 많아질 것이라는 걸 한 눈에 보여주고자 했다. 다문화 사회를 체감하지 못하는 사람도 이주민과의 공존에 대해 생각해보도록 만들고 싶었다.
처음에는 Mapbox GL JS로 지도를 제작했다. Mapbox는 웹에 지도를 나타내는 자바스크립트 라이브러리인데 여러 기능을 사전에 제공해 개발자들이 쉽게 인터랙티브 그래픽을 제작할 수 있게 돕는다. 예를 들어 지도에 지역명이 자동으로 표기되고, 이용자가 스크롤이나 드래그를 하면 지도가 특정 지역을 비추도록 움직이게 만들 수 있는 기능이 있다. 하지만 여러 기능을 포함하고 있기 때문에 용량이 클 수밖에 없다. 그렇게 되면 라이브러리를 불러오는 시간이 길어져 페이지 로딩 속도에 영향을 미칠 수 있다. 인트로 페이지는 독자들에게 기사의 첫인상을 심어주는 중요한 역할을 하고, 실제 독자들에게 가장 많이 노출됐다. 그렇기 때문에 성능 부분을 더 신경 써야 했다.

D3.js를 사용해서 다시 개발을 시작했다. D3는 지도, 차트 등 다양한 데이터 시각화를 구현할 수 있는 자바스크립트 라이브러리다. Mapbox처럼 그래픽 제작을 돕는 기능이 기본으로 포함돼 있진 않지만, 그런 점 때문에 오히려 웹페이지 성능에는 도움이 된다. 원하는 기능만 골라서 코드로 추가할 수 있어 더 깔끔하게 구동되고 훨씬 자유롭게 커스터마이징할 수 있기 때문이다. 이전에 D3로 개발해 본 경험이 있었기 때문에 전체적인 틀을 만드는 데에는 그렇게 긴 시간이 걸리지 않았다. 하지만 디테일한 부분을 수정하는 데 시간을 많이 들였다.
최적화하기
D3로 지도를 나타내기 위해서는 두 가지 파일이 필요하다. 지도의 정보를 담고 있는 JSON 파일과 통계 정보를 담은 CSV 파일이다. JSON은 속성과 값의 쌍으로 이루어진 데이터 형식이다. 예를 들어 {”이름”:”철수”, “나이”:20}에서 이름과 나이는 속성이고 철수와 20은 각 속성에 대한 값이다. 이런 JSON 형식 중에서도 geoJSON은 위치 정보에 대한 속성과 값을 담고 있는 데이터 파일이다. geoJSON은 다시 topoJSON이라는 파일 형식으로 변환할 수 있다. topoJSON은 geoJSON과 같은 정보를 담고 있지만 훨씬 압축할 수 있어 용량을 줄일 수 있다. 웹페이지 성능 향상을 위해 topoJSON 파일을 사용했다.
왼쪽의 사진이 통계청에서 제공하는 대한민국의 시군구를 나타내는 topoJSON 파일로 그린 지도이다. 보이는 것처럼 매우 상세한 지형까지 모두 그려진다. 하지만 ‘공존’ 기사에서는 이렇게까지 상세한 지형 정보가 필요하지는 않았다. mapshaper를 통해서 오른쪽처럼 지도를 단순화시켰다. 파일 용량도 5분의 1로 줄었고, 경계선들이 정리돼 보기에 더 깔끔해졌다.

이제 D3를 이용해 topoJSON 파일로 웹페이지에 지도를 나타내는 것은 간단하다. 지도의 크기를 결정하고, 얼마나 확대할 것이며 지도의 위치를 어디에 둘 것인지를 코드로 작성하면 지도가 그려진다.
지도에 정보를 추가하기
빈 지도가 완성됐다. 지도의 배경색과 테두리 색은 직접 코드로 변경했다. 다음은 이 지도에 원하는 정보를 표시해야 될 차례였다. 여기에서는 각 지역 위에 이름을 표시하고, 안산 지역만 분홍색으로 표시하고자 했다.

제작 과정을 더 쉽게 이해하기 위해 topoJSON 파일의 일부를 가져왔다.
복잡해보이지만 여러 개의 속성과 값의 쌍들로 이루어진 집합이다. 이 중에서 지도에 나타낼 정보는 일부분이다. 그 예시로 하나의 지역을 가져왔다.
하나의 지역은 다음과 같은 속성을 갖고 있다. 위의 예시에서 지역의 이름(name)은 “안산시 단원구”이고, 기준년도(base_year)는 2018년, 영어 표기법(name_eng)은 “Ansansidanwongu”, 지역코드(code)는 31092다.
D3에는 지도 위에 텍스트, 도형, 이미지 등을 추가할 수 있는 기능이 있다. 위의 코드를 통해 지도에 텍스트를 추가하고, 그 텍스트를 각 지역의 가운데(centroid)에 위치하도록 했다.

하지만 몇 지역은 이름이 지역의 중앙이 아닌 곳에 표시됐다. 아무래도 지역의 모양이 일정하지 않다 보니 중앙에 위치해도 지역 경계선 바깥으로 넘어가는 경우가 있었다. 그런 지역들은 직접 텍스트의 x좌표, y좌표 위치를 조정했다.
조건문을 통해 지역의 “name”이 “안산시 단원구”, 혹은 “안산시 상록구”라면, 해당 지역의 칠(fill)을 분홍색으로 변경하도록 해 안산시를 지도 상에 표시했다.
지도에 정보를 연결하기
지금까지는 topoJSON 파일 내부에 존재하는 정보들을 지도에 표시했다. 이제는 외국인 비율이 5% 이상인 지역을 나타내기 위해 CSV 파일을 이 지도에 연결할 차례다.
CSV 파일은 구조가 더 간단하다. 왼쪽의 Excel 파일에서 각 열을 쉼표로 분리한 파일이다. 맨 위의 영단어들이 각 열을 대표하는 이름이 된다.
topoJSON과 CSV 파일에서 유일한 공통 요소는 ‘지역명’이다. topoJSON 파일에서는 “name”이 “안산시 단원구”라는 값을 갖고 있고, CSV 파일에서는 city의 값으로 “안산시 단원구”가 있다.
D3에는 topoJSON 파일의 properties에 속성을 추가할 수 있는 기능이 있다. topoJSON 파일의 name 값과 CSV 파일의 city 값이 같다면, 해당하는 지역에 rate라는 새로운 속성을 추가했다.
그렇게 해서 “안산시 단원구” 지역에 “rate”라는 새로운 속성이 추가됐다. 외국인 비율이 5% 이상인 지역에만 “rate” 속성이 추가된 것이다. 그리고 앞서 지역의 이름을 텍스트로 추가한 것처럼, 해당 지역들에 원을 추가했다.

하지만 일부 지역에는 원이 표시되지 않았다. 원의 개수를 일일이 세어보지 않아도 CSV 파일 속의 지역 수보다 현저히 적은 수의 원이 지도에 표시됐다. 처음에는 코드에 오류가 있다고 생각해 코드를 계속 수정했다. 하지만 코드를 수정해도 오류는 해결되지 않았다. 코드 내부의 오류가 아니라면 코드 파일에 연결되어 있는 외부 파일의 문제일 확률이 높다. 그래서 표시가 되지 않은 지역을 중심으로 topoJSON 파일과 CSV 파일을 천천히 살펴보았다.

문제는 역시 외부 파일에 있었다. topoJSON 파일과 CSV 파일에서 각각 지역을 표기하는 방식이 달라 오류가 발생했다. 예를 들면 중구는 서울에도 있고 인천, 부산에도 있다. 그리고 세 중구는 모두 외국인 비율이 5% 이상인 지역이다. topoJSON 파일에는 “중구”가 중복된 이름으로 여러 개 존재했고, CSV 파일에서는 서울 중구, 부산 중구, 인천 중구로 각각 표기되어 있었다. 모든 중구에 원을 표시하기 위해서는 topoJSON 파일에서 이름이 중복되지 않도록 수정해야 했다. 따라서 속성값 중 하나인 지역코드를 검색해서 각 중구에 서울, 인천, 부산을 앞에 추가했다. 이런 식으로 서로 다른 지역 이름들을 전부 통일해 오류를 해결할 수 있었다.
마지막 사소한 부분까지
위의 과정만으로도 그래픽은 완성할 수 있었다. 하지만 개발은 끊임없이 수정할 부분이 생기고, 욕심이 생기기 마련이다. 우선 전국 지도로 줌아웃되었을 때, 모든 지역에 이름이 뜨는 것은 너무 지저분해 보이고 정보를 과다하게 제공하는 것 같아 과감하게 삭제했다. 또 PC에서 웹페이지를 볼 때, 원에 마우스를 올리면 해당 지역에 대한 정보가 뜨도록 했다. 정보를 담은 말풍선에도 단순히 시군구명이 아닌, 도의 이름까지 뜨는 것이 더 친절할 것이라고 생각했다. 그래서 CSV 파일에 city_full이라는 값을 추가해서, OO도 OO시/군/구로 표시되게 만들었다.

이렇게 단순해보이는 하나의 그래픽도 많은 것들을 고려하고 수정한 끝에 탄생하게 된다. 결과물이 웹페이지에서 잘 구동될 때, 그리고 다른 요소들과 잘 어우러지면서 독자들에게 흥미를 줄 수 있을 때 가장 뿌듯함을 느낀다. 이 지도를 통해 독자들에게 기사에 대한 호기심을 이끌 수 있었다면, 성공했다고 생각한다. 앞으로도 더 다양하고 참신한 시도들을 많이 해보고 싶다.
관련 콘텐츠 더보기
공존 : 그들과 우리가 되려면 인구절벽 시대, 감소한 인구를 대체하는 이주민과의 공존은 피할 수 없는 과제가 됐다.
우리는 그들과 더불어 살 수 있을까. 한국에서 외국인이 가장 많은 도시 경기 안산시를 중심으로 답을 찾아본다.
2022.01.16~01.19·시리즈 4화·히어로 콘텐츠 4기
임상아 뉴스룸 디벨로퍼
임상아 뉴스룸 디벨로퍼|동아일보 디프런티어센터

디오리지널의 기사를 기술적으로 구현하는 일을 하고 있습니다. 이야기와 기술이 만날 때 이야기가 전달할 수 있는 가치는 더욱 극대화될 수 있다고 생각합니다. 많은 사람들에게 새로움과 감동을 줄 수 있는 기사들을 만들어가고 싶습니다.