본문 바로가기

Function

QGIS에서 레이어로 구분된 PDF 만들기

QGIS에서 레이어로 구분된 PDF를 만들어보자. 아래처럼 레이어를 끄거나 켜서 내용물을 선택적으로 볼 수 있다.


대표이미지



QGIS의 풀다운 메뉴에서 [프로젝트] → [새로운 프린트 구성] 기능을 이용하면 축척과 범례 등을 포함한 여러가지 레이아웃을 이용한 지도를 만들 수 있다. 자세한 내용은 여기를 참고하면 된다.


지도 구성 창에서 '아틀라스' 항목을 이용하면, 현재 지도를 구성하고 있는 레이어의 개체들을 차례대로 훑어가면서 지도를 반복적으로 만들 수 있다. 예를 들어 서울의 행정동 경계 424개 폴리곤으로 된 shp 레이어가 있다면, 행정동별로 된 424개 지도를 만들 수 있다. 덧붙여, 이 shp파일의 속성으로 행정동 이름이나 행정동의 인구와 같은 내용이 있다면, 일정한 설정을 통해 각각의 지도마다 서로 다른 행정동 지도 뿐만 아니라 해당 폴리곤에 연결된 값들을 지도 주변에 디스플레이 할 수도 있다. 자세한 내용은 여기를 참고하면 된다.



이 지도는 jpg와 같은 래스터 이미지로 출력할 수 있지만, 벡터 형식의 pdf나 svg로도 만들 수 있다. 벡터 형식의 pdf는 지도 파일을 받은 사람이 좀 더 크게 출력하고 싶을 때 큰 종이에 맞추어 확대 출력하더라도 선들이 깨지지 않고 깔끔하게 출력된다는 장점이 있다.


여기서 마지막으로 한 가지 욕심을 더 부려볼 수 있다. 지도 파일이 다양한 레이어(shp)들을 포함하고 있을 때, 마치 QGIS상에서 레이어를 켜고 끄는 것처럼 PDF에서도 개체를 선택적으로 볼 수 있게 만들면 어떨까? 물론 QGIS에서 자유자재로 지도들을 다루는 정도에 비할 바는 아니겠지만, QGIS는 비전문가들이 쉽게 다룰 수 있는 툴은 아니기 때문에, 범용적인 PDF형식에 레이어를 추가한다면 배포받는 사람들의 입장에서 조금 더 지도의 활용도가 높아질 수 있다.


다행히도 PDF에 레이어를 추가하는 것은 가능하지만, 안타깝게도 QGIS3.0이 나온 2018년 3월의 시점까지도 한두번의 클릭으로 되는 쉬운 방법은 존재하지 않는다. 한 두장의 지도라면 오픈소스 프로그램을 받아서 한단계씩 따라가면서 해 볼 수 있고, 만약 몇 십 장이나 몇 백 장의 지도라면 코드를 작성하거나 수정할 수 있어야 한다. 이 글에서는 후자의 경우, 즉 많은 양의 지도에 대해 대응하는 방법을 다룬다. 


우선, 한 두장의 지도를 만드는 방법은 의 답변과 댓글을 참고하자. 요약하자면, 우선 qgis에서 svg 파일로 출력한 후 Inkscape나 Scribus라는 프로그램을 내려받아 따라해보면 된다. 그러나 이 방법은 메뉴를 일일이 클릭하고 선택해야 하기 때문에 대량의 지도에는 대응하기가 어렵다. 대량의 지도를 다룰 때는 Adobe Illustrator를 이용할 수 있는데, 크게 구분하여 다음과 같은 단계를 거치면 된다.


1. 우선 QGIS의 아틀라스에서 svg형식으로 파일들을 내보낸다.

2. svg 형식은 메모장에서 열 수 있는 text 파일이다. 폰트 이름이나 선 굵기등 기본적인 svg 출력의 미진한 점들을 수정해준다.

3. Illustrator에서 svg 형식을 읽어들인 후, clipping mask 기능을 이용하여 지도 외곽선 밖으로 나온 지도 내용들을 정리한다. 레이어를 정리한 후, pdf로 저장한다.

4. Acrobat Reader등에서 pdf 문서를 열어 레이어를 확인한다.


이제부터 한 단계씩 자세히 따라가보자.


1. QGIS에서 SVG형식으로 내보내기



아틀라스를 이용할 경우 아래 같은 메뉴에서 SVG를 내보낼 수 있다.


지도 구성 창에서 아틀라스든, 한 장의 지도든 SVG로 형식으로 내보내려고 하면, 다음과 같은 경고가 뜬다.



"QGIS의 SVG 내보내기 기능은 버그와 결함때문에 몇가지 문제가 있습니다 Qt4 svg 코드에 있어 조금 문제가 있습니다. 특히 레이어가 지도 도곽에서 잘리지 않는 문제가 있습니다.

만약 Qgis에서 벡터기반 출력 파일이 필요하다면 PostScript로 출력할 것을 권장합니다. SVG로 출력은 신뢰도가 낮습니다."


이 글의 뒤에서 해결하려는 것이 바로 위의 문제들이다.

위의 경고를 확인 후 넘어가면, 아틀라스 방식의 경우 SVG를 내보낼 폴더를 선택하게 된다. 그 후에 아래와 같은 창이 뜬다.




위와 같이 체크해준다. 지도 레이어를 svg그룹으로 내보내야 뒤에서도 레이어별 컨트롤을 할 수 있다. 두번째 창도 체크해서 map labels도 되도록이면 outline으로 render해준다. svg는 한글 폰트를 내보낼 때 약간의 문제가 있기 때문에 텍스트를 outline으로 깨버리면 여러가지로 편리하다. 단, 최종 결과인 pdf 문서 내에서 ctrl-F 등으로 찾기 기능은 쓸 수 없으니 적절히 잘 판단하여 정한다.


별 문제가 없다면 아래와 같이 여러 개의 svg파일이 생성될 것이다. 여기서는 지하철역들을 중심으로 지도를 만들었다.





2. svg 수정하기




svg는 위와 같은 xml 형식의 문서다. 그렇기 때문에 메모장 등 텍스트 에디터에서 직접 수정이 가능하다. svg 에서 직접 수정해 줄 것은 다음의 세 가지다.


레이어 이름

폰트 이름

선 굵기(stroke-width)


수정에 앞서 알아야 할 기본적 문서의 형식들이 있다. QGIS는 지도의 레이어와 지도 구성 창에서 작업한 내용들을 '그룹'으로 묶어서 SVG로 내보낸다. SVG에서 그룹은 <g> 태그에 해당한다. 


출력된 svg문서를 보면 지도의 레이어보다 몇개 더 많은 <g> 태그를 볼 수 있다. 각 그룹의 id는 Layer 1, Layer 2, 등으로 자동 할당되고, 지도 구성 창에서 작업한 범례나 스케일 바와 같은 내용은 일반적으로 맨 마지막 그룹에 하나로 묶인다.

맨 마지막에서 두 번째 그룹에는 지도구성 화면에서 지도의 외곽 한계선이 있다. 원래 이 경계선이 클리핑 마스크의 역할을 해서 지도 내용들이 경계를 벗어나지 않도록 해야 하지만, 불완전한 svg출력라이브러리로 인해 클리핑되지 않는다.

나머지 레이어들은 대부분 지도에서의 레이어들과 일치한다. <g> 태그 안의 id 이름을 원하는대로 바꿔주면 된다.


 <g fill="none" inkscape:label="Layer 1" inkscape:groupmode="layer" stroke="black" fill-rule="evenodd" stroke-linejoin="bevel" stroke-linecap="square" id="Layer 1" stroke-width="1">


여기서 바꾼 이름들이 나중에 pdf에서 레이어의 이름들이 된다.



그 다음에는 폰트 이름을 바꿔준다.

굴림체와 같은 경우 아래와 같이 Gulim으로 지정되어 있고, 일러스트레이터에서도 문제 없이 읽힌다. 


<g stroke-opacity="1" fill="none" font-family="Gulim" stroke="#000000" stroke-linejoin="bevel" font-style="normal" stroke-linecap="square" font-weight="400" stroke-width="1" transform="matrix(11.8081,0,0,11.8081,0,0)" font-size="37.5"/>


그러나 새로 설치한 폰트나 일부 폰트의 경우 한글 이름이 그대로 들어가버리기 때문에, 일러스트레이터에서는 제대로 읽어내지 못한다. 각각의 적절한 폰트 이름을 찾아내서 수정해 주어야 한다.


<text x="10" y="95.3125" fill="#000000" font-family="나눔고딕" stroke="none" font-style="normal" fill-opacity="1" font-weight="700" xml:space="preserve" font-size="71">구로디지털단지역</text>


나눔고딕의 경우 NanumGothic 으로 변경해주면 된다. 텍스트 에디터의 찾기-바꾸기 등의 기능을 이용하여 일괄적으로 변경할 수 있다.



마지막으로 선 굵기를 수정해주어야 한다. svg를 일러스트레이터에서 읽을 때, <svg> 태그에서 선언해 준 width와 height, viewbox 등은 다른 항목들의 stroke-width와 적절하게 계산되어 해석되지 않는다. 일반적인 경우 일러스트레이터에서 읽었을 때 선으로 정의된 개체들은 QGIS상에서 보는 것보다 몇 배 굵게 나온다.

이 문제의 해결 방법은 대략 두 가지가 있다. 하나는 문서 맨 앞의 svg 태그 안의 width와 height 항목을 viewBox 항목과 같이 만들어주는 것이다.


<svg width="296.926mm" version="1.2" xmlns="http://www.w3.org/2000/svg" height="209.973mm" viewBox="0 0 3507 2480" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="tiny" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">


예를 들어 위의 부분을, 아래와 같이 수정하면 된다.


<svg width="3507" version="1.2" xmlns="http://www.w3.org/2000/svg" height="2480" viewBox="0 0 3507 2480" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="tiny" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">


일러스트레이터에서 수정된 파일을 읽어보면 선 굵기가 제대로 보인다. 한 가지 문제는 애초에 A4로 정의했던 문서의 크기가 커졌다는 점이다. 물론, pdf로 변환시킨 후 인쇄하고 싶을 때 A4에 꽉 차도록 설정해서 인쇄하면 사실 별 문제는 없다. 그래도 문서 크기 자체가 바뀌었으므로 어딘가 찜찜하다면 두 번째 방법을 사용하자.


두 번째 방법은 svg출력을 300dpi로 설정했을 경우, 문서 안의 stroke-width 항목의 값들을 모두 3.07087으로 나누어 기존 값들을 치환하는 것이다. 문자열을 바꾸는 간단한 코드를 작성할 수 있다면 어려운 일은 아니지만, 그렇지 않을 경우에는 꽤 어려운 방법이다. 200dpi 설정의 경우 2.04724로 나누어 주면 된다. (300dpi일 경우 0.26mm가 3.07087 pixel 이 된다. 0.26mm를 기본 변수값으로 사용하여 svg를 생성하는 것 같다.)


svg 파일을 수정하는 java 파일은 아래와 같다. 경우에 따라 내용을 수정하여 사용해야 한다.




3. 일러스트레이터에서 스크립트로 수정하기


수정된 svg 파일을 일러스트레이터에서 읽어오면 아래와 같이 보인다. 앞에서 언급한 것처럼 지도의 내용들이 clip 되지 않은 채 프레임 밖으로 뻗어나와 있다.



위에서 레이어 항목을 보면, Layer 1 아래에 15개의 하위 항목들이 보인다. svg에서는 layer를 만들 수 없으며, 일러스트레이터에서 읽어올 때 자동적으로 layer 1을 만들고 그 하위에 15개의 그룹을 두게 된다. 후에 PDF로 변환할 때 활성화 되는 레이어는 최상위 레이어들이므로 여기서 하위 15개의 그룹을 각각 레이어로 만들어주고 최상위로 끌어올린 후 현재 보이는 최상위 레이어인 Layer 1을 지워주면 된다.


수동으로 작업할 경우 최상위 레이어가 선택된 상태에서 Layer 의 메뉴를 열고 Release to Layers (Sequence)를 실행시킨다.



실행시키면 아래와 같은 상태가 된다. 하위 레이어들을 최상위로 끌어올리고 현재 최상위 레이어(Layer 1)를 지워주면 된다.




그리고, 레이어 이름들도 다시 하위 그룹의 이름들로 바꿔주어야 한다. 그 후에 지도 내용물 레이어에 대해 clipping mask를 만들고 pdf로 저장하면 된다. 보통 위에서 두번째 레이어에 지도 프레임이 있다. 이 레이어 안의 path를 클리핑 마스크로 사용할 수 있다.



위와 같이 Path를 클리핑하고자 하는 레이어의 최상위에 놓은 후에 메뉴를 열어 Make Clipping Mask를 선택한다.




해당 Path가 Clipping Path로 변하면서 외곽선 밖의 지도들이 감춰진 것을 확인할 수 있다.




이번에는 이 작업을 스크립트를 이용해서 실행시켜보자. 일단 코드를 살펴보자. 주석으로 설명을 달아놓았다.

아래 스크립트는 범용적으로 쓸 수 없다. 빠른 시간안에 주어진 문제만 해결하기 위해 미리 알고 있는 위치들을 지시적으로 지정했다.(좋은 범용적 코드가 아니다) 레이어 구성이 다르다면 내용을 수정하여 적용해야 함에 유의하자.





스크립트는 일러스트레이터 설치파일 아래 Scripts 폴더 밑에 둔다. 확장자는 jsx로 해야한다. 그 후 일러스트레이터를 실행시키면,  풀다운메뉴의 [File]→[scripts] 밑에서 해당 스크립트 이름을 찾아볼 수 있다. 실행하면, 클리핑과 레이어정리가 되고 pdf로 저장할 수 있다. 일러스트레이터 스크립트에 대한 일반적인 내용은 여기를 참고한다.


이제 모두 끝났다. pdf에서 레이어를 on/off하면서 제대로 만들어졌는지 확인해보자.