손 종 수 (mis026@korea.ac.kr)


0.
들어가며
본 자료는 글을 쓰는 본인이 경험적으로 체득한 것을 정리한 것으로써 교과서적 정리와는 근본적으로 다르다. 따라서 sparQL과 Linked data를 빠르게 접하고 체험하기에는 적합할지 모르나 이론적 원리를 이해함에 있어서는 부족함이 있다. 또한 설명하는 부분에서 필자 스스로에게 이해가 쉬운 어휘와 표현을 사용하고 있으므로 추후 sparQL의 스펙문서와 Linked data 관련 논문들을 찾아 읽어서 부족한 부분을 채우시길 부탁 드린다.

1. SparQL Overview
sparQL은 크게 PREFIX, {SELECT, ASK, DESCRIBE, CONSTRUCT}, WHERE로 구성된다.

PREFIX는 일반 데이터베이스에서 데이터베이스 선택과 비슷한 의미로써 일반적으로 사용할 데이터 셑을 지정할 때 사용한다.

SELECT는 탐색할 대상을 지정할 때 사용하며 변수를 사용할 수 있다. 변수는 '?변수'의 형식으로 사용하며 전체를 탐색할 때는 ' * '을 사용한다.

WHERE는 조건절이다. 중괄호로 묶어 여러 줄을 사용할 수 있다.

그 외에 ORDER BY 등 질의의 마지막 부분에 정렬순서 등을 지정할 수 있다.

2. 간단한 예제

PREFIX : <http://abbs.purl.org/music#>

SELECT ?instrument

WHERE {        :andrew :playInstrument ?intrument .    }


위 문장은 <http://abbs.purl.org/music#>이라는 데이터 셑에서 instrument를 찾을건데 앤드류(주어)가 'playInstrument'라는 술어를 갖는 어떤 목적어 instrument를 찾겠다는 것이다.

WHERE절에서 한 문장의 끝은 마침표( . )로 구분한다.


3. 조금 더 복잡한 예제

PREFIX : <http://aabs.purl.org/ont/journal#>
SELECT ?notes

WHERE {

    ?e a :JournalEntry .

    ?e :notes ?notes .

    ?e :date ?date .

}

ORDER BY ?date

LIMIT 5

OFFSET 150

SELECT절 – ?notes를 출력할 것이다.

WHERE절 –
a는 rdfs:type의 약자이다. 즉, ?e a :JournalEntry는 rdfs:type이 JournalEntry인 어떤 변수 e를 찾는다라는 뜻이다.
?e :notes ?notes 는 ?e의 notes를 가져와서 ?notes로 사용하겠다라는 뜻이다.

?e :date ?date 는 ?e의 date를 가져와서 ?date로 사용하겠다라는 뜻이다.

notes 와 date를 가져와서 사용하겠다는 것은 달리 말해 notes와 date가 있는 데이터를 가져와서 사용하겠다는 것과 같다. 따라서 세 줄을 합쳐서 생각하면 모든 JournalEntry 타입을 갖는 데이터를 가져오는데(?e라는 변수로 통칭) 그 중에서 notes와 date 라는 항목을 결과집합으로 쓰겠다는 것이다.

ORDER BY 이하 절 – ORDER BY는 정렬순서이고 LIMIT은 출력 결과 개수 제한, OFFSET은 결과가 만들어 지기 전에 150개가 넘는 결과를 받아오면 그 순간 결과를 받지 않겠다는 것이다.


4. Dbpedia의 Linked data

Dbpedia는 wikipedia의 자료들에 의미적 주석을 달아서 다른 웹 사이트나 프로그램에서 사용할 수 있도록 가공하여 제공해주는 사이트이다. Linked data 분야에서 Dbpedia는 중요한 역할을 수행하고 있으며 상대적으로 많은 양의 자료를 가지고 있어 활용성이 높다.

<Dbpedia 홈페이지 – http://www.dbpedia.org>

Dbpedia에서 제공하는 자료/자원은 고유의 웹 페이지 주소를 가지며 고유의 URI 또한 가진다. 늘 웹 페이지 주소와 URI 주소가 같은 자료를 보여주지는 않으나 Dbpedia에서는 URI주소를 찾아 들어가면 다음 그림과 같은 웹 페이지를 출력해준다. 아래 그림은 The_Beatles의 URI를 웹 브라우저의 주소창에 입력하고 찾아갔을 때의 화면이다.


<Dbpedia에서 제공하는 The_Beatles의 URI와 웹 페이지>

그리고 위 웹 페이지의 가장 하단을 보면 아래 그림과 같이 데이터 포맷을 선택해서 출력하거나 다운받을 수 있다.

<Dbpedia의 다양한 데이터 포맷>

Dbpedia에서는 Dbpedia의 모든 자료에 대해 검색할 수 있는 웹 기반 sparQL Endpoint를 제공하고 있다. Dbpedia의 sparQL Endpoint의 주소는 http://dbpedia.org/sparql 이다.


5. Dbpedia에서의 실전 예제 (1)

http://dbpedia.org/sparql 에 들어가서 일단 아래 질의를 입력한 후 'Run Query'를 클릭해보도록 하자.

SELECT ?uri ?name ?page ?nick
WHERE{

   ?uri a foaf:Person ;

   foaf:name ?name;

   foaf:page ?page;

   foaf:nick ?nick.

}
LIMIT 100

Dbpedia에서는 기본적으로 PREFIX가 많이 되어있으므로 쓰지 않아도 된다.

첫 번째 줄에서 ?uri, ?name, ?page, ?nick은 이 네 개의 항목을 가져오겠다는 것이다.

세 번째 줄에서 ?uri a foaf:Person; 은 foaf:Person이라는 type을 가진 모든 항목을 ?uri라는 변수로 사용하겠다는 명령이다. (a == rdfs:typeOf)

네 번째 줄에서 foaf:name ?name 은 ?uri로 선택된 항목의 foaf:name을 ?name이라는 변수에 넣겠다는 명령이다.

다섯 번째 줄과 여섯 번째 줄도 같은 의미이다. 그리고 마지막 줄에서 LIMIT 100은 최대 100개 가져오겠다는 명령이다.

요약하자면, foaf:Person이라는 타입을 가진 모든 자원에서 foaf:name, foaf:page, foaf:nick의 데이터를 각각 ?name, ?page, ?nick이라는 변수에 넣어서 출력하겠다는 것이다.

다음 그림은 위 질의에 대한 결과화면이다. 결과화면은 html로 출력 선택을 하여 웹 페이지 형식으로 보이며 xml, RDF/XML, JSON 등 다양한 형태로 전송 받을 수 있다.



<예제 질의를 실행한 결과 화면>



6. Dbpedia에서의 실전 예제 (2)


위 예제와 유사한 예제를 하나만 더 해보도록 한다. 일단 예제 질의를 보기 전에 다음 화면을 먼저 확인해보자.

<Dbpedia에서 Terry_Holbrook의 정보>

위 화면은 Terry_Holbrook 이라는 축구 심판의 URI 주소와 Dbpedia의 자료 화면이다. 이 화면에서 보면 dbpprop:countryofbirth 와 같은 형식의 다양한 속성명을 확인할 수 있다. 우리는 이 자료를 통해 '사람 클래스'를 Dbpedia에서 어떻게 표현해주는지 알 수 있다. 따라서 이를 활용하여 질의를 만들어 볼 수 있다.

다음 예제는 Dbpedia의 자료들 중에서 사람이름, 태어난 나라, 직업만을 골라서 출력해주는 예제이다.


SELECT ?name ?birth ?role
WHERE{

   ?x a foaf:Person ;

   dbpprop:fullname ?name;

   dbpprop:countryofbirth ?birth;

   dbpprop:role ?role.

}
LIMIT 100

첫 번째 줄은 ?name, ?birth, ?role을 출력하겠다는 것이다.

세 번째 줄은 foaf:Person이라는 타입을 가진 모든 항목 ?x를 설정한다.
네 번째 줄은 그 ?x의 dbpprop:fullname 속성에 해당하는 데이터를 ?name으로 지정한다.
다섯 번째와 여섯 번째 줄은 네 번째 줄과 동일하다.

세미콜론은 4~6번줄 모두 주어가 ?x 이기 때문에 문장의 끝이 아님을 구분하기 위해서이다. 위 예제를 개념적으로 다시 설명하면..

(주어 - ?x) + (술어 - dbpprop:fullname) + (목적어 - ?name)
(주어 - ?x) + (술어 - dbpprop:countryofbirth) + (목적어 - ?birth)
(주어 - ?x) + (술어 - dbpprop:role) + (목적어 - ?role)

이 세 문장을 묶어서

(주어 - ?x) +
[
   { (술어 - dbpprop:fullname) + (목적어 - ?name) }

   { (술어 - dbpprop:countryofbirth) + (목적어 - ?birth) }

   { (술어 - dbpprop:role) + (목적어 - ?role) }

]

이렇게 만들었다고 생각하면 간단하다. 다음 화면은 결과화면이다.

<결과 화면>

위 결과를 보면 이름, 태어난 나라, 직업이 출력된걸 확인할 수 있다. 그럼 이제 태어난 곳이 England 인 사람의 이름과 직업만을 출력하고 싶다면 어떻게 하면 될까? 답은 FILTER를 사용하면 된다. 아래 예제 질의를 보자.


SELECT ?name ?birth ?role
WHERE{

?x a foaf:Person ;

dbpprop:fullname ?name;

dbpprop:countryofbirth ?birth;

dbpprop:role ?role.


FILTER regex(?birth, "land$").

FILTER regex(?birth, "^Eng").
FILTER regex(?birth, "England").

}
LIMIT 100

위 질의문을 보면 FILTER라는 조건이 붙은걸 볼 수 있다. FILTER는 결과로 받아온 데이터들을 걸러주는 역할을 한다. 예제 질의에는 FILTER 를 세 개 붙여 놓았다. 물론 한 개만 붙여도 되며 더 늘려도 괜찮다. sparQL의 정규표현식은 기본적으로 XML - XPATH의 정규식을 따른다고 한다. 따라서 FILTER에 정교한 필터링이 필요한 경우 XPATH의 정규표현식을 공부하면 된다.
첫 번째 FILTER 예제는 ?birth의 결과물 중에서 'land'로 끝나는 것을 선택하라는 것이다.
두 번째 FILTER 예제는 'Eng'로 시작하는 것을 선택하라는 것이다.

세 번째 FILTER 예제는 'England'와 일치하는 것을 선택하라는 것이다.

세 문장을 우리는 한 질의에 모두 넣었으므로 결과적으로 ?birth가 'England'인 사람만 출력이 될 것이다. 아래는 그 결과화면이다.


<결과 화면>