PostGIS 덕분에

최근에는 MySQL대신 PostgresQL을 사용하고 있습니다. 테이블에서 필드를 추가/삭제하는 경우에도 table lock이 걸리지 않는다는 점1이 가장 큰 이유였습니다. 손에 익기까지 시간이 좀걸리긴 하지만, 서비스 다운타임을 최소화 시켜줄 수 있지 않을까 생각합니다.

PostGIS는 설치과정이 좀 복잡한데요. gist에서 올바른 설치 법을 발견했습니다. 몇가지 오류를 수정해서 gist에 올렸습니다. (우분투버전도 있습니다.)

레일즈에서 사용하려면, 젬이 필요한데, rgeo + activerecord-postgis-adapter 조합이 제일 편한 듯 합니다.

사실, 예전부터 실무에서 이 조합을 적용해보고 싶었지만 적당한 데이터가 없었습니다. 다행히 이번 과제에서 아주 딱 맞는 상황을 발견해서 적용할 수 있었습니다.

다음은 작업하던 데이터 중 일부인데요. “주소-경도-위도-도시이름” 이 차례로 들어가있습니다.

이를 처리하기 위해서 모델 데이터베이스에 필드를 추가했습니다.

# PostGIS를 도입하면 decimal 대신 point 를 쓸수있다.
#t.decimal :longitude, :precision=>10, :scale=>6
#t.decimal :latitude, :precision=>10, :scale=>6
t.point :gps, :geographic=>true

gps 라는 필드에는 x,y (위도,경도)를 입력할 수 있습니다. 이것만으로는 별로 의미가 없어보입니다.  중요한 것은 아래의 nearby_to 라는 녀석입니다. 모델쪽 클래스에 이렇게 적어두면

scope :nearby_to,
    lambda { !hotel, max_distance|
        where("ST_DWithin(gps, ?, ?) AND id != ?", hotel.gps, max_distance, hotel.id)
    }

뷰에서 이렇게 사용할 수 있습니다.

<h6>근처의 호텔들</h6>
<% nears = Hotel.nearby_to(@hotel, 600).order(:name) 
   nears.each do |hotel| %>
    <%=link_to hotel.name, hotel%>(<%=hotel.longitude%>)
<% end %>

이 녀석과 구글맵 API를 잘 연동하면, 여러가지 조작이 가능하겠구요. 위도/경도 가 포함된 데이터를 처리할 때도 꽤 편하게 응용할 수 있었습니다.

뭔가 그럴싸한 젬이라도 하나 올리면서 포스팅을 하면 좋을텐데 말이죠. 데이터에 NDA라던가 하는 것들이 걸려있어서 오픈할만한 것들이 별로 없네요. 언젠가는 오픈소스 할만한 것이 있겠습니다만…

레일즈와 PostGIS 연동은 link을 참고했습니다.



  1. 모든 alter table에 락이 없는 것은 아닙니다. nullable 일 경우라던가 하는 제약이 있습니다. 또 mysql의 경우에도 이런 것이 있으니, 불가능한 것은 아닙니다. [return]