@keedi - Seoul.pm 리더, Perl덕후, 거침없이 배우는 펄의 공동 역자, keedi.k at gmail.com
지난 기사인 여섯째 날: 너무 간단한 지도 그리기에서는 Perl을 이용해 지도를 화면에 그리는 방법을 알아보았습니다. 원하는 지점을 지도에 나타내기 위해 주소를 입력하기도 했고, 위도(씨줄. 緯度, latitude)와 경도(날줄. 經度, longitude) 좌표를 입력하기도 했죠. 생각해보면 이 둘은 무언과 분명히 상관 관계가 있어 보입니다. 보통 우리는 나라에서 공식적으로 지정해서 사용하는 주소 체계에 익숙합니다. 대부분은 주소만 들어도 대충 "아~ 거기~"라고 인지하죠. 하지만 이 주소를 지도상에 컴퓨터로 표시하려면 좀 문제가 있습니다. 지도는 평면적으로 넓게 펼쳐놓고 보았을 때 일종의 2차원 그래프로 X축과 Y축 단 두 개의 좌표만 있으면 아주 손쉽게 특정 위치를 지정할 수 있죠. 이 X축과 Y축이 경도와 위도 정보입니다. 하지만 주소로 특정 위치를 찾는 일은 쉽지 않기에 이 주소 정보에 해당하는 위도와 경도 정보를 안다면 훨씬 쉽게 지도 상에 해당 위치를 표시할 수 있겠죠. 역으로 GPS 장비가 시시각각 위도와 경도 좌표를 저장한다면, 사실 이 소숫점을 포함한 복잡하고 긴 수치를 보았을 때 여기가 어디인지 파악하는 것은 현실적으로 불가능하죠. 이 때는 대부분의 평범한 사람은 해당 위도와 경도 좌표가 해당하는 주소를 보았을 때야 "아~ 여기였구나~"할 것입니다. 이 때 필요한 것이 바로 지오코딩(geocoding)과 역지오코딩(reverse geocoding)입니다. Perl을 이용해 가장 널리 사용하는 구글맵의 지오코딩을 사용해보죠.
필요한 모듈은 다음과 같습니다.
직접 CPAN을 이용해서 설치한다면 다음 명령을 이용해서 모듈을 설치합니다.
$ sudo cpan Geo::Coder::Google
사용자 계정으로 모듈을 설치하는 방법을 정확하게 알고 있거나 perlbrew를 이용해서 자신만의 Perl을 사용하고 있다면 다음 명령을 이용해서 모듈을 설치합니다.
$ cpan Geo::Coder::Google
구글 지도 보여 줄 때와 마찬가지로 지오코딩을 하기 위해서도 Google Maps API 키가 필요합니다. API 키를 발급받는 방법은 지난 기사인 여섯째 날: 너무 간단한 지도 그리기를 참고하세요.
지오코딩(geocoding)은 "서울 종로구 세종로 1"와 같은 주소를
37°35'11.9"N 126°58'36.4"E
와 같은 지리 좌표로 변환하는 작업입니다.
반대로 역지오코딩은 지리 좌표를 주소로 변환하는 것입니다.
우선 지오코딩을 위해서는 Geo::Coder::Google
모듈 객체를 생성해야 합니다.
use utf8; use strict; use warnings; use feature qw( say ); use Geo::Coder::Google; my $geocoder = Geo::Coder::Google->new( apidriver => 3, api_key => "AIzABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHkY", );
구글은 더이상 구글맵 API 버전2를 지원하지 않기 때문에 버전3을 써야하므로 딱히 선택의 여지는 없습니다.
API 버전은 apidriver
인자를 이용해서 명시하고, 발급받은 키는 api_key
인자로 명시합니다.
이제 지오코딩을 할 모든 준비는 끝났습니다.
my @locations = $geocoder->geocode( location => "서울 종로구 세종로 1", ); die "failed to geocode\n" unless @locations;
geocode()
메소드를 이용해서 실제 지오코딩을 실행하며, 지오코딩을 결과를 배열로 반환 받습니다.
이 때 결과 배열의 첫 번째 항목이 가장 정확하게 일치된 항목이며,
이후 항목은 근접한 후보 항목을 반환합니다.
스칼라 문맥으로 반환받을 경우 배열로 반환 받을 때의 가장 첫 번째 항목을 반환합니다.
my $location = shift @locations; say "$location->{geometry}{location}{lat}, $location->{geometry}{location}{lng}"; if (@locations) { say "candidate:"; for my $candidate (@locations) { say " $candidate->{geometry}{location}{lat},$candidate->{geometry}{location}{lng}"; } }
실행 결과는 다음과 같습니다.
$ ./geocoding.pl 37.586652,126.9767701 $
이번에는 역지오코딩을 해볼까요? 지오코딩과 대동소이합니다.
my $result = $geocoder->reverse_geocode( latlng => "37.586652,126.9767701" ); die "failed to reverse geocode\n" unless $result; say $result->{formatted_address};
역지오코딩을 하기 위해서는 reverse_geocode()
메소드를 사용합니다.
이 때 인자는 latlng
이며, 위도와 경도 정보를 쉼표를 이용해 조합한 문자열을 전달합니다.
결과는 해시 참조(reference)를 반환하며 여기에 저장된 항목은 크게 다음과 같은 구조를 가집니다.
address_components
formatted_address
geometry
place_id
types
우리가 흔히 필요로 하는 최종 결과물은 formatted_address
에 문자열로 저장되어 있거나
address_components
에 배열 참조로 각각의 주소 체계에 맞는 정보가 저장되어 있습니다.
$result->{formatted_address}
의 값을 출력하면 일단 우리가 원하는 역지오코딩 결과를 확인할 수 있습니다.
실행 결과는 다음과 같습니다.
$ ./reverse-geocoding.pl 1 Sejongno, Jongno-gu, Seoul, South Korea $
어라, 결과가 영어로 나오는 군요.
구글은 전세계적으로 서비스를 지원하기 때문에 다양한 언어를 지원하지만
특별히 언어를 설정하지 않은 경우 기본적으로 영어로 결과를 반환하기 때문입니다.
Geo::Coder::Google
모듈은 language
속성을 지원하므로 이를 사용해서 한국어로 설정해보죠.
my $geocoder = Geo::Coder::Google->new( apidriver => 3, api_key => "AIzABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHkY", language => "ko", );
실행 결과는 다음과 같습니다.
$ ./reverse-geocoding.pl Wide character in say at ./reverse-geocoding.pl line XX. 대한민국 서울특별시 종로구 세종로 1 $
원하는 결과가 나온 것 같긴한데 Wide character ...
관련 경고가 발생하네요.
이것은 표준 출력의 인코딩을 설정하면 간단히 해결할 수 있습니다.
use Geo::Coder::Google; binmode STDOUT, ":utf8"; my $geocoder = Geo::Coder::Google->new( ... );
실행 결과는 다음과 같습니다.
$ ./reverse-geocoding.pl 대한민국 서울특별시 종로구 세종로 1 $
이제 정말 잘 되는 것 같네요. :-)
비단 구글 지도 뿐만 아니라 네이버 지도와 카카오(다음) 지도도 지오코딩과 역지오코딩 기능을 지원하니 관심이 있다면 한 번쯤 확인해보세요. 여러분이 인지는 못했겠지만 사실 지오코딩의 역사는 무척 오래되었으며, 컴퓨터를 이용한 무료 지도 서비스와 스마트폰의 지도 서비스가 일상이 되면서 우리는 하루에도 몇 번씩 지오코딩과 역지오코딩 기능을 사용하고 있습니다. 위치 기반 서비스가 일상이 된 지금 지도와 지오코딩 등에 대해서 자세히 알아두면 꽤 유용하겠죠? :-)
EOT
X-mas tree
& Llama
ASCII Art by ASCII Art Farts.
Computer ASCII Art by Chris.com.
Cup ASCII Art by ascii.co.uk.
Candle ASCII Art by heartnsoul.com.
Font ASCII Art by ASCII Art Farts.
Text ASCII Art by patorjk.com.
Artwork by
Inkyung Park
& Keedi Kim.
Designed by
Hojung Youn
& Keedi Kim.
Articles by
Seoul Perl Mongers.
Edited by
Keedi Kim.
Hosting sponsored by
SILEX.
Sponsored by
SILEX.
.-''' __ __ / \/ \/ \ =-_- | \. -____- / \ // /|| '' //| //|| == = == ==