[database] 공간 데이터베이스란? (공간DB 개념)
- 4 mins공간DB (Spatial DataBase)
DB에 익숙한 사람도 ‘공간DB’라는 용어는 처음들어보는 경우가 많을 것이다.
혹은 용어는 한두번쯤 접해 보았더라도, 정확한 목적이 무엇인지 궁금했던 사람도 많을 것이다.
보통 공간DB를 설명할때 GIS쪽 용어를 혼재해서 쓰는 경우가 많아서,
설명을 읽어도 그 필요성이나 개념이 잘 와닿지 않는 경우가 대부분이다.
그래서 공간DB가 무엇인지 감이라도 한 번 잡아보자는 차원에서 정말 정말 간단하게 정리해봤다.
좌표계나 R-Tree같은 깊은 설명은 우선 배제하도록 하겠다.
공간 데이터
결국 공간DB는 “공간 데이터를 다루기 위한 DB”이다.
그럼 공간 데이터가 뭘까?
말 그대로 공간에 존재하는 건물이나 도로, 산과 강 같은 객체 들을 데이터화 한것이다.
그럼 공간에 존재하는 객체를 데이터화 하려면 어떻게 해야할까?
바로 좌표를 이용하면 된다.
모든 공간 객체는 점, 선, 면으로 이루어져 있다.
한 번 더 생각해보면 점이 모여 선이되고, 선이 모여 면이 되므로,
결국엔 모든 공간 객체는 점으로 이루어져 있다고 봐도 된다.
공간DB에서는 하나의 점을 다음과 같이 표현한다.
POINT(10 10)
더욱 자세한 설명을 위해서는 좌표계의 개념이 들어가야 하지만,
우선은 공간DB의 개념만 잡기위해 이 부분은 추후에 따로 다루도록 하겠다.
일단 위 데이터는 좌표 평면에서 x좌표가 10, y좌표가 10인 점을 생각하면 된다.
이를 공간DB가 아닌 일반적인 DB에서 표현하려면 어떻게 해야할까?
x좌표와 y좌표를 저장하는 컬럼을 따로 만들어서 저장하면 된다.
그럼 복잡하게 공간DB를 굳이 쓰지 않고 그냥 x, y 좌표를 따로 저장하면 되지 않냐고 할 수도 있다.
나도 처음엔 “왜 꼭 공간 객체를 이런 방식으로 저장해야하지?” 라는 의문이 들었었다.
일단 의문을 잠시 접어두고 계속 내려가보자.
선은 어떻게 표현할까?
LINESTRING(10 10, 20 20)
POINT(10 10)과 POINT(20 20)을 연결한 선을 공간DB에서는 이렇게 표현한다.
일반적인 DB에서는 POINT(10 10)의 x, y좌표와 POINT(20 20)의 x, y좌표를 각각 따로 저장하고,
다시 이 점들끼리 하나의 선으로 연결되어있다는 정보도 어딘가 따로 저장해줘야 할 것이다.
이것만 해도 슬슬 복잡해지면서 공간DB의 필요성을 조금은 알 것도 같다.
면은 어떻게 표현할까?
POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))
원점에서 시작하고, 한 변의 길이가 10인 정사각형이다.
아주 간단한 도형인데도 기존의 DB에서 이를 표현하려고 생각하면 벌써부터 머리가 아프다.
일단 네 개의 POINT의 x, y좌표를 다 따로 저장해야하고,
닫힌 도형이라는 것을 표현하기 위해 시작 점과 끝 점은 항상 같아야 한다는 규칙을 따라야 한다.
이를 사용자가 저장할때 일일이 신경쓰면서 저장해야하고,
이 네 개의 점들은 하나의 면에 포함된다는 정보를 또 따로 저장해야한다.
내가 쓰면서도 머리가 아프다.
그럼 그냥 이렇게 복잡하게 하지 말고,
일반적인 DB에서 문자열로 ‘점(10 10)’ 이라던지, ‘선(10 10, 20 20)’ 으로 저장하면 안될까?
물론, 단순히 좌표값을 확인하기 위한 참고용으로 저장만 한다면상관없다.
하지만 이러한 좌표들을 가지고 연산을 해야 한다면?
공간 연산
공간DB의 궁극적인 목적은 결국 공간 연산이다.
두 개의 면이 있을 때, 이 면이 서로 겹치는지 겹치지 않는지 판단하고 싶은 것이다.
더 나아가, 그 겹치는 면의 면적과 좌표까지 알고싶은 것이다.
혹은 어떠한 점이 특정한 면에 포함되는지 판단하고 싶은 것이다.
이 외에도 지도에 존재하는 수 많은 공간 객체에 적용할 수 있는 연산이 무궁무진할것이다.
이를 기존의 DB가 제공하는 함수를 가지고 어떻게 연산하겠는가?
공간DB에서는 두 면이 겹치는지 여부를 다음과 같이 간단한 함수를 통해 알 수 있다.
ST_CONTAINS(GEOM1, GEOM2)
GEOM1이라는 공간 객체가 GEOM2라는 공간 객체를 포함하고 있는지 여부를 반환하는 공간 연산이다.
만약 공간 DB를 쓰지 않고, 일반적인 DB에서 지원하는 함수로 이러한 기능을 구현하려면?
특정 도형이 다른 도형을 포함하는가 하는 여부를 공간DB를 사용하지 않고 어떻게 표현하겠는가?
뭐, 작정하고 하려면 아주 못하는건 아닐 것이다.
각 도형은 적게는 서너개에서 많으면 수십개의 POINT를 가지고 있고, 이 POINT들 끼리의 선후관계또한 존재한다.
한 도형이 가지고 있는 POINT를 모두 연결해 가상의 공간을 만들고,
다른 도형이 가지고 있는 POINT를 모두 연결해 가상의 공간을 만든 후,
겹치는부분을 찾아내는 알고리즘을 잘 계산한 뒤(난 어떻게 해야할지 잘 모르겠다) 값을 도출하면 된다.
정말 기적적으로 이런 것들을 모두 고려해서 데이터를 저장하고 SQL을 짠다고 해도, 결국엔 성능적인 문제에 부딪힐것이다.
사실 좌표계까지 고려하면 이는 일반적인 DB에서는 거의 불가능한 수준에 이른다.
복잡해질까봐 좌표계에 대해서는 언급도 하지 않았지만,
좌표계를 고려하지 않더라도 이는 쉬운 문제가 아니라는것을 알 수 있다.
결론
정리하자면,
공간DB는 공간 데이터를 다루기 위한 특수한 목적으로 사용되는 DB이며,
크게 다음과 같은 두 가지 목적으로 사용된다는 점을 기억하면 된다.
- 좌표로 표현할 수 있는 공간 객체들을 데이터화해서 보다 쉽게 저장하기 위한 목적.
- 저장한 공간 데이터에 대해 다양하고 손쉬운 연산을 수행하기위한 목적.
공간DB는 결국 저장한 공간데이터를 활용해 공간연산을 수행하는 것이 목적이다.
사실 공간데이터 자체를 사용할 일이 많이 없기 때문에 공간DB의 개념을 알 필요가 없었을 것이다.
일반적인 프로그램은 문자열과 숫자를 가지고 거의 모든 기능을 수행하고,
때문에 저장하는 데이터의 형태도 문자열이나 숫자 타입 정도만 지원하면 충분하다.
다만, 앞으로 지리정보나 위치정보를 기반의 서비스가 증가하는 추세이며,
이러한 서비스를 구축하기 위해서는 공간DB는 필수적으로 활용되어야 할 것이다.
따라서 이정도의 기본적인 개념정도는 알아두는 것도 나쁘지 않을 것 같다.
(사실 제대로 하려고 파보면 꽤 복잡해서, 나도 공부 시작한지 2년이 지났는데도 아직 열심히 공부중이다…ㅠㅠ)