중요

번역은 여러분이 참여할 수 있는 커뮤니티 활동입니다. 이 페이지는 현재 100.00% 번역되었습니다.

16.4. 크로스 레이어 데이터 연결 및 편집 작업

서로 다른 레이어들의 데이터를 연결할 수 있는 기능은 GIS 소프트웨어의 필수적인 기능 가운데 하나입니다. 피처들 간의 공간 관계 또는 공유되는 속성을 기반으로 이런 연결을 만들 수 있습니다. QGIS는 이러한 모든 결합들을 다룰 수 있는 다음과 같은 도구들을 제공합니다:

  • 위치로 속성 결합하기, 최근접으로 속성 결합하기, 필드값으로 속성 결합하기 등등과 같이 데이터 연결의 결과로서 새 레이어를 생성할 수 있는 공간 처리 알고리즘들

  • 데이터베이스 관리자 로부터 새 레이어를 생성하거나, 가상 레이어 로서 새 레이어를 생성할 수 있는 SQL 쿼리

  • 지정한 레이어에 있는 피처들의 속성을 몇몇 일치하는 속성(들)을 바탕으로 또다른 레이어에 있는 피처들의 속성으로 일시적으로 확장시키는 결합 속성 또는 관계 설정

    결합(join)과 관계(relation)는 데이터베이스 테이블들에 저장되어 있는 데이터를 테이블의 내용을 합쳐서 가장 효율적으로 사용하기 위해 빌려온, 데이터베이스에서 사용되는 개념입니다. 서로 다른 레이어(테이블)들의 피처(행)들이 서로 연결될 수 있다는 뜻이죠. 서로 간에 일치하는 행의 개수는 어떤 값이든 (0이든, 1이든, 다수든) 될 수 있습니다.

16.4.1. 두 레이어 간 피처 결합하기

QGIS에서는 현재 레이어의 피처와 또다른 레이어의 피처를, 두 레이어가 공간적으로 활성화되어 있는지 그리고 도형의 유형이 일치하는지 관계 없이, 결합 을 통해 연결시킬 수 있습니다. 이 결합은 두 레이어가 1대1 관계로 공유하는 속성을 기반으로 생성됩니다.

어떤 (다음에서 target layer 로 표기되는) 레이어 상에 결합을 생성하려면:

  1. 레이어 메뉴에서 Properties ► join Joins 탭으로 가십시오.

  2. symbologyAdd Add new join 아이콘을 클릭하면 Add vector join 대화창이 열립니다.

  3. 대상 벡터 레이어와 연결하려는 Join layer 를 선택하십시오.

  4. (join layer 로부터) Join field 를 그리고 (target layer 로부터) Target field 를 지정하십시오. 두 레이어에서 일치하는 피처를 찾는 데 쓰이는 필드들이기 때문에 두 필드가 공통된 값들을 가지고 있어야 합니다.

  5. OK 를 누르면 Join 패널에 선택한 파라미터들의 요약이 추가됩니다.

../../../_images/join_attributes.png

그림 16.101 기존 벡터 레이어에 속성 테이블 결합

앞의 단계들을 통해 생성된 결합은, 결합 레이어에서 처음으로 일치하는 피처모든 속성을 대상 레이어의 피처에 추가시킵니다. 결합 과정에서 피처 쌍을 만드는 데에는 다음과 같은 논리가 쓰입니다:

  • 일치하는 피처가 있는지에 상관 없이, 대상 레이어(target layer)에 있는 모든 피처를 반환합니다.

  • 대상 필드가 중복되는 값들을 담고 있을 경우, 이 피처들은 결합 레이어의 동일한 피처에 할당됩니다.

  • 결합 필드가 중복되는 일치하는 값들을 담고 있을 경우, 맨 처음 가져온 피처만 선택합니다.

참고

QGIS에서 결합은 일치하는 단일 필드에 기반하기 때문에 대부분의 경우 두 레이어의 두 필드들이 담고 있는 값들이 유일한지 확인해보는 편이 좋습니다.

QGIS는 이 결합을 미세 조정할 수 있는 많은 옵션을 제공하고 있습니다:

  • checkbox Cache join layer in virtual memory: 검색 속도를 향상시키기 위해, 메모리에 결합된 레이어의 (도형을 제외한) 값들을 저장할 수 있게 합니다.

  • unchecked Create attribute index on the join field: 이 옵션을 활성화하면 검색 속도를 향상시키기 위해 결합 필드에 속성 인덱스를 생성합니다.

  • unchecked Dynamic form: 결합 필드들을 Target field 를 따라서 실시간으로 동기화할 수 있습니다. 이 옵션을 활성화하면, 결합 필드에 있는 제약조건도 정확하게 업데이트됩니다. 이 옵션이 기본적으로 비활성화돼 있는 것은 피처나 결합이 많을 경우 처리 시간이 너무 오래 걸리기 때문이라는 사실을 기억하세요.

  • 대상 레이어가 편집 가능 상태인 경우, 필드에 대한 정보를 알려주기 위한 몇몇 아이콘들이 속성 테이블의 필드 옆에 표시될 것입니다:

    • joinNotEditable: 결합 레이어를 편집할 수 있도록 환경 설정되지 않았습니다. 대상 속성 테이블에서 결합 피처를 편집할 수 있도록 하고 싶다면, checkbox Editable join layer 옵션을 체크해야 합니다.

    • joinedLayerNotEditable: 결합 레이어를 편집할 수 있도록 환경 설정돼 있지만, 현재 읽기 전용 상태입니다.

    • joinHasNotUpsertOnEdit: 결합 레이어를 편집할 수 있지만, 동기화 메커니즘이 활성화되지 않았습니다. 대상 레이어에서 피처를 생성하면 결합 레이어에 피처를 자동적으로 추가하게 하려면, checkbox Upsert on edit 옵션을 체크해야 합니다. 마찬가지로, 대상 레이어에서 피처를 삭제하면 결합 레이어에서도 자동적으로 삭제하게 하려면 checkbox Delete cascade 옵션을 체크해야 합니다.

  • unchecked Joined fields: 결합된 레이어의 모든 필드를 추가하는 대신, 하위 집합을 지정할 수 있습니다.

  • unchecked Custom field name prefix: 이름의 충돌을 방지하기 위해 결합된 필드명에 사용자 지정 접두어를 추가합니다.

16.4.2. 여러 레이어 간 관계 설정하기

두 레이어의 피처들 사이에 1대1 연결을 정의하는 결합과는 달리, 관계는 사용자가 두 개 이상의 레이어들의 여러 피처들 사이에 상호 연결(interconnection)을 작성할 수 있도록 해줍니다. 이와 같이, 관계란 프로젝트 수준의 설정이므로 Project ► Properties ► relations Relations 탭에서 설정합니다. 이 탭에서 다음을 설정할 수 있습니다:

  • symbologyAdd Add relation: 다음과 같은 유형의 관계를 추가할 수 있습니다:

    참고

    비다형성(non-polymorphic) 관계를 한번 생성하고 나면, 이 관계를 간단하게 편집할 수 있는 방법이 없습니다. 더블클릭으로 관계의 이름만 편집할 수 있을 뿐이죠. 이런 관계의 다른 모든 파라미터의 경우, 사용자가 제거한 다음 다시 생성해야만 할 것입니다.

  • symbologyAdd Discover relations: QGIS는 지원하는 데이터베이스 포맷들(PostgreSQL, 지오패키지, ESRI 파일 지오데이터베이스, …)로부터 기존 관계를 발견할 수 있습니다. 이를 통해 관계를 보다 쉽게 정의할 수 있습니다.

  • symbologyRemove Remove relation: 현재 선택 집합에서 선택한 관계를 제거합니다.

../../../_images/project_relations.png

그림 16.102 관계 탭

16.4.2.1. 1대다(1-N) 관계

예를 들어 사용자에게 알래스카의 모든 지역을 담고 있고, 지역명, 지역 유형, (기본키로 동작하는) 유일 ID 관련 속성을 제공하는 (폴리곤) 레이어가 있다고 해보겠습니다.

그런데 알래스카 지역에 위치한 공항 관련 정보를 담고 있는 또다른 포인트 레이어 또는 테이블을 얻었고, 사용자가 이 공항들도 파악하고 싶다고 해보겠습니다. regions 레이어에 이 공항들을 추가하려면, 외래 키(foreign key)를 이용해서 일대다 관계를 생성해야 합니다. 왜냐하면 대부분의 지역에 공항이 몇 군데씩 있기 때문입니다.

../../../_images/regions_with_airports.png

그림 16.103 알래스카의 지역과 공항

레이어와 키

QGIS는 테이블과 벡터 레이어를 전혀 구분하지 않습니다. 기본적으로, 벡터 레이어는 도형을 지닌 테이블입니다. 따라서 사용자의 테이블을 벡터 레이어로 추가할 수 있습니다. 일대다 관계를 시연해보기 위해, 동일한 데이터셋에 있는 regionsairports 셰이프파일을 불러오겠습니다. 실제로는 각 공항이 딱 1개 지역에만 속해 있는 반면 각 지역은 공항을 몇 개든 가지고 있을 수 있다는 뜻입니다. (전형적인 일대다 관계죠.)

airports 셰이프파일은 regions 레이어에 대한 외래 키 필드(fk_region)를 가지고 있습니다.

공항을 설명하는 속성에 더해, 공항 레이어는 외래 키처럼 동작하는 또다른 fk_region 필드를 가지고 있습니다. (데이터베이스를 사용하는 경우, 이 외래 키 필드에 제약조건을 정의해놓는 편이 좋을 겁니다.) 이 fk_region 필드는 항상 지역의 ID를 담고 있을 것입니다. 이 ID를 해당 지역을 가리키는 포인터라고 볼 수도 있겠죠.

편집 작업을 위한 사용자 지정 편집 양식을 설계할 수 있도록 QGIS에 레이어들 사이의 관계를 알려주면 끝입니다. QGIS가 나머지 설정을 처리할 것입니다. 서로 다른 제공자와도 같은 방식으로 작업할 수 있습니다. (즉 셰이프파일 및 CSV 파일에도 동일하게 사용할 수 있습니다.)

1대다(1-N) 관계 정의하기

가장 먼저 할 일은 QGIS 에 두 레이어 간의 관계를 알려주는 것입니다. Project ► Properties… 메뉴에서 이 작업을 할 수 있습니다. Relations 탭을 선택한 다음 symbologyAdd Add Relation 버튼을 클릭하십시오.

  • 이름(Name): 제목으로 사용됩니다. 관계의 목적을 설명하는, 사람이 읽을 수 있는 문자열이어야 합니다. 이 예시에서는 그냥 airport_relation 라고 하겠습니다.

  • 참조되는 레이어(Referenced Layer) (부모): 부모 레이어로도 간주되는 이 레이어는 외래 키가 가리키는 기본 키를 가지고 있습니다. 즉 이 예시에서는 regions 레이어입니다. 참조되는 레이어의 기본 키를 정의해야 하는데, 이 예시에서는 ID 입니다.

  • 참조하는 레이어(Referencing Layer) (자식): 자식 레이어로도 간주되는 이 레이어가 외래 키 필드를 담고 있습니다. 이 예시에서는 airports 레이어입니다. 이 레이어의 경우 다른 레이어를 가리키는 참조하는 필드를 추가해야 합니다. 이 예시에서는 fk_region 입니다.

    참고

    어떤 경우, 레이어에 있는 피처들을 유일하게 식별하기 위해 단일 필드 이상이 필요할 때가 있습니다. 이런 레이어와의 관계를 생성하는 데에는 복합 키(composite key), 예를 들어 일치하는 필드들의 단일 쌍 이상이 필요합니다. symbologyAdd Add new field pair as part of a composite foreign key 버튼을 이용해서 필요한만큼 많은 쌍을 추가하십시오.

  • ID: 내부 목적으로 사용되며, 유일한 값이어야 합니다. 사용자 지정 양식 을 작성하기 위해 필요할 수도 있습니다. 이 항목을 비워둘 경우, 자동적으로 생성되지만 사용자가 더 쉽게 다룰 수 있는 ID를 직접 할당할 수도 있습니다.

  • 관계 강도(Relationship Strength): 상위(부모)와 하위(자식) 레이어 사이의 관계 강도를 설정합니다. 기본 Association 유형은 상위 레이어가 하위 레이어에 단순하게 링크되어 있다는 의미인 반면, Composition 유형은 상위 피처를 복제할 때 하위 피처도 복제할 수 있으며 상위 레이어의 피처를 삭제하면 하위 피처도 삭제할 수 있는 등, 모든 수준에서 순차적(cascade)으로 결과물을 산출합니다. (다시 말해 하위의 하위의 … 하위 피처도 삭제할 수 있다는 뜻입니다.)

../../../_images/regions_airports_mapping.png

그림 16.104 지역과 공항 레이어 사이에 관계 추가하기

Relations 탭에서, symbologyAdd Discover Relation 버튼을 눌러 불러온 레이어들의 제공자로부터 사용할 수 있는 관계를 가져올 수도 있습니다. 이 기능은 PostgreSQL 또는 SpatiaLite 같은 데이터 제공자에 저장된 레이어에 대해서 사용할 수 있습니다.

1대다(1-N) 관계용 양식

이제 QGIS가 관계를 인지했으니, 관계를 이용해서 QGIS가 생성하는 양식을 향상시킬 것입니다. 기본 양식 생성 방법(자동 생성)을 변경하지 않았으므로, 양식에 위젯 하나만 추가할 것입니다. 범례에서 regions 레이어를 선택한 다음 식별 도구를 써보십시오. 사용자 설정에 따라 양식이 바로 열릴 수도 있고, 식별 대화창의 액션을 통해 양식을 열어야 할 수도 있습니다.

../../../_images/airport_relation_dataview.png

그림 16.105 “airports”와 관계가 생성된 “regions”의 식별 대화창

그림에서 보이듯이, 이 특정 지역에 할당된 공항이 테이블에 전부 표시됩니다. 또 사용할 수 있는 버튼도 몇 개 있습니다. 이 버튼들을 간단히 설명하겠습니다.

  • toggleEditing 버튼은 편집 모드를 켜고 끕니다. 현재 regions 레이어에 있는 피처의 피처 양식을 보고 있긴 하지만, 이 버튼은 airports 레이어의 편집 모드를 켜고 끈다는 점을 조심하십시오. 왜냐하면 테이블이 airports 레이어의 피처를 표시하고 있기 때문입니다.

  • saveEdits 버튼은 하위 레이어(airports)의 모든 편집 내용을 저장합니다.

  • capturePoint 버튼은 맵 캔버스에 공항(airports) 도형을 디지타이즈할 수 있게 해주며, 기본적으로 현재 지역(regions)에 새 피처를 할당합니다. 도형 유형에 따라 아이콘이 바뀔 것이라는 사실을 기억하십시오.

  • newTableRow 버튼은 airports 레이어의 속성 테이블에 새 레코드를 추가하고, 기본적으로 현재 지역(regions)에 새 피처를 할당합니다. 나중에 Add part 디지타이즈 작업 도구로 도형을 그릴 수 있습니다.

  • duplicateFeature 버튼은 하위 레이어 안에 있는 하나 이상의 하위 피처를 복사하고 붙여넣기할 수 있습니다. 나중에 서로 다른 상위 피처에 이 하위 피처를 할당하거나 또는 하위 피처의 속성을 수정할 수 있습니다.

  • deleteSelectedFeatures 버튼은 선택한 공항(들)을 영구 삭제합니다.

  • link 심볼은 나중에 현재 지역에 할당될 어떤 공항이든 선택할 수 있는 새 대화창을 엽니다. 사용자가 실수로 잘못된 지역에 공항을 생성한 경우 편리할 수도 있습니다.

  • unlink 심볼은 현재 지역에서 선택한 공항(들)을 링크 해제합니다. 즉 선택한 공항(들)을 실질적으로 할당되지 않은 상태로 남겨둔다는 (외래 키를 NULL로 설정한다는) 뜻입니다.

  • zoomToSelected 버튼을 사용하면 선택한 자식 피처로 맵을 확대/축소할 수 있습니다.

  • 오른쪽에 있는 formViewopenTable 두 버튼은 관련된 하위 피처들의 테이블 뷰와 양식 뷰 를 전환합니다.

regions 피처에 드래그&드롭 설계자 를 사용하는 경우, 어떤 도구를 사용할 수 있는지 선택할 수 있습니다. Force hide form on add feature 옵션을 이용해서 새 피처를 추가할 때 새 양식을 열지 여부를 결정할 수도 있습니다. 이 옵션이 정확하게 동작하기 위해 NULL 값을 가진 속성이 무결한 기본값을 반드시 가져오지 않아도 된다는 사실을 기억하십시오.

../../../_images/airport_relation_formproperties.png

그림 16.106 지역-공항 관계를 환경 설정하기 위한 드래그&드롭 설계자 도구

앞의 예시에서 참조하는 레이어가 도형을 보유하고 있기 (즉 그저 문자와 숫자를 조합한 테이블이 아니기) 때문에, 앞의 단계를 수행하면 레이어 속성 테이블에 대응 도형 피처가 없는 항목을 생성할 것입니다. 도형을 추가하려면:

  1. openTable Open Attribute Table: 참조하는 레이어의 속성 테이블을 여십시오.

  2. 참조되는 레이어의 피처 양식 안에서 이전에 추가된 레코드를 선택하십시오.

  3. addPart Add Part 디지타이즈 작업 도구를 사용해서 선택한 속성 테이블 레코드에 도형을 첨부하십시오.

공항 테이블을 작업하는 경우, (관계를 생성하기 위해 사용된) fk_region 필드를 대상으로 관계 참조 위젯을 자동으로 설정합니다. 관계 참조 위젯 을 참조하세요.

공항 양식의 fk_region 필드 오른쪽에 formView 버튼이 있을 겁니다. 이 버튼을 클릭하면 지역 레이어의 양식이 열릴 것입니다. 이 위젯에서 링크된 부모 피처의 양식을 쉽고 빠르게 열 수 있습니다.

../../../_images/airport_attributes.png

그림 16.107 “regions”와 관계가 생성된 “airports”의 식별 대화창

관계 참조 위젯은 자식 레이어의 양식 안에 부모 레이어의 양식을 삽입할 수 있는 옵션도 가지고 있습니다. 공항 레이어의 Properties ► Attributes Form 메뉴를 선택하고, fk_region 필드를 선택한 다음 Show embedded form 옵션을 활성화하십시오.

지금 피처 대화창을 보고 있다면, 지역의 양식이 공항 양식 안에 삽입돼 있고 현재 공항을 다른 지역으로 할당할 수 있는 콤보박스도 있다는 것을 알 수 있을 겁니다.

../../../_images/airport_attributes_expanded.png

게다가 공항 레이어의 편집 모드를 켜고 끌 경우, fk_region 필드도 자동 완성 기능을 지원합니다. 사용자가 입력하는 중에 지역 레이어의 id 필드의 모든 값을 보게 될 것입니다. 이때 공항 레이어의 Properties ► Attributes Form 메뉴에서 Allow adding new features 옵션을 선택했다면 symbologyAdd 버튼을 눌러 폴리곤을 디지타이징할 수 있습니다.

자식 피처의 속성을 기반으로 부모 레이어의 피처를 선택하기 위해 값으로 피처 선택 도구에서 자식 레이어를 사용할 수도 있습니다.

그림 16.108 에서, 공항의 평균 해발고도가 500m를 초과하는 모든 지역을 선택합니다.

이 양식에서 여러 서로 다른 집계 함수들을 사용할 수 있을 것입니다.

../../../_images/relation_select_by_value.png

그림 16.108 자식 값으로 부모 피처 선택

16.4.2.2. 다대다(N-M) 관계

N-M 관계란 두 테이블 간의 다대다 관계를 말합니다. airportsairlines 레이어를 예로 들 수 있습니다. 공항은 여러 항공사의 노선을 받아들이고 항공사는 여러 공항에 이착륙합니다.

다음 SQL 코드는 PostgreSQL/PostGIS 스키마에 locations 라는 이름의 N-M 관계를 위해 필요한 테이블 3개를 생성합니다. PostGIS의 경우 Database ► DB Manager… 메뉴를 통해, 또는 pgAdmin 같은 외부 도구들을 통해 코드를 실행할 수 있습니다. 공항 테이블은 airports 레이어를, 항공사 테이블은 airlines 레이어를 저장하고 있습니다. 이 두 테이블에서 관계를 분명히 하기 위해 사용되는 필드는 몇 개 되지 않습니다. 까다로운 부분은 airports_airlines 테이블입니다. 이 테이블에 모든 공항에 대해 모든 항공사를 (그리고 그 반대도) 전부 목록화해야 합니다. 이런 유형의 테이블을 피벗(pivot) 테이블 이라고 합니다. 공항과 항공사 둘 다 이미 각각의 레이어에 존재하는 경우에만 공항을 항공사와 관련지을 수 있도록 강제하는 것이 이 테이블의 제약조건 입니다.

CREATE SCHEMA locations;

CREATE TABLE locations.airports
(
   id serial NOT NULL,
   geom geometry(Point, 4326) NOT NULL,
   airport_name text NOT NULL,
   CONSTRAINT airports_pkey PRIMARY KEY (id)
);

CREATE INDEX airports_geom_idx ON locations.airports USING gist (geom);

CREATE TABLE locations.airlines
(
   id serial NOT NULL,
   geom geometry(Point, 4326) NOT NULL,
   airline_name text NOT NULL,
   CONSTRAINT airlines_pkey PRIMARY KEY (id)
);

CREATE INDEX airlines_geom_idx ON locations.airlines USING gist (geom);

CREATE TABLE locations.airports_airlines
(
   id serial NOT NULL,
   airport_fk integer NOT NULL,
   airline_fk integer NOT NULL,
   CONSTRAINT airports_airlines_pkey PRIMARY KEY (id),
   CONSTRAINT airports_airlines_airport_fk_fkey FOREIGN KEY (airport_fk)
      REFERENCES locations.airports (id)
      ON DELETE CASCADE
      ON UPDATE CASCADE
      DEFERRABLE INITIALLY DEFERRED,
   CONSTRAINT airports_airlines_airline_fk_fkey FOREIGN KEY (airline_fk)
      REFERENCES locations.airlines (id)
      ON DELETE CASCADE
      ON UPDATE CASCADE
      DEFERRABLE INITIALLY DEFERRED
 );

PostgreSQL 대신 GeoPackage도 사용할 수 있습니다. 이 경우, 사용자가 Database ► DB Manager… 메뉴를 통해 세 테이블을 직접 생성할 수 있습니다. GeoPackage에는 스키마가 존재하지 않기 때문에 접두어 locations 을 붙일 필요도 없습니다.

Table ► Create Table… 또는 Table ► Edit Table… 메뉴로는 airports_airlines 테이블의 외래 키 제약조건을 생성할 수 없기 때문에, Database ► SQL Window… 를 사용해서 생성해야 합니다. GeoPackage는 ADD CONSTRAINT 선언문을 지원하지 않으므로 airports_airlines 테이블을 다음 두 단계를 거쳐 생성해야 합니다:

  1. Table ► Create Table… 메뉴를 사용해서 id 필드만 보유한 테이블을 설정합니다.

  2. Database ► SQL Window… 메뉴로 SQL 창을 열고, 다음 SQL 코드를 입력하고 실행합니다:

    ALTER TABLE airports_airlines
       ADD COLUMN airport_fk INTEGER
       REFERENCES airports (id)
       ON DELETE CASCADE
       ON UPDATE CASCADE
       DEFERRABLE INITIALLY DEFERRED;
    
    ALTER TABLE airports_airlines
       ADD COLUMN airline_fk INTEGER
       REFERENCES airlines (id)
       ON DELETE CASCADE
       ON UPDATE CASCADE
       DEFERRABLE INITIALLY DEFERRED;
    

그 다음 QGIS에서, 앞에서 설명한 대로 일대다(1-N) 관계 2개를 설정해야 합니다:

  • airlines 테이블과 피벗 테이블 간의 관계

  • airports 테이블과 피벗 테이블 간의 두 번째 관계

Project ► Properties ► Relations 메뉴에서 Discover Relations 메뉴 옵션을 사용하면 (PostgreSQL인 경우에만) 이 작업을 더 쉽게 할 수 있습니다. QGIS가 사용자 데이터베이스의 모든 관계를 자동으로 읽어들여, 사용자는 필요한 두 관계만 선택하면 됩니다. 먼저 QGIS 프로젝트에 세 테이블을 불러와야 한다는 것을 잊지마세요.

../../../_images/airports_airlines_relation.png

그림 16.109 관계와 자동검색

사용자가 airport 또는 airline 을 제거하고자 하는 경우, QGIS는 airports_airlines 테이블에서 관련 레코드(들)를 제거하지 않을 것입니다. 현재 예시에서처럼 피벗 테이블 생성 시 올바른 제약조건 을 지정한 경우 데이터베이스가 관련 레코드(들)를 제거할 것입니다.

참고

다대다 관계를 자동 트랜잭션(transaction) 그룹과 결합하기

이런 맥락에서 작업하는 경우 Project Properties ► Data Sources ► 메뉴 옵션에서 트랜잭션 모드를 활성화시켜야 합니다. QGIS가 모든 테이블(airlines, airports 및 피벗 테이블)에 있는 행(들)을 추가하거나 업데이트할 수 있어야 하기 때문입니다.

마지막으로 Layer Properties ► Attributes Form 메뉴에서 airportsairlines 레이어에 대한 올바른 기수(cardinality)를 선택해야 합니다. 첫 번째 기수로 airlines (id) 옵션을, 두 번째 기수로는 airports (id) 옵션을 선택해야 합니다.

../../../_images/airports_airlines_relation_formproperties.png

그림 16.110 관계 기수성 설정

이제 Add child feature 또는 하위 양식에 있는 Link existing child feature 를 통해 공항을 항공사와 (또는 항공사를 공항과) 관련시킬 수 있습니다. 레코드가 airports_airlines 테이블에 자동적으로 삽입될 것입니다.

../../../_images/add_airport_airline.png

그림 16.111 공항과 항공사 사이의 N-M 관계

참고

다대일 관계 기수성 사용하기

N-M 관계에서 피벗 테이블을 숨기는 것이 바람직하지 않을 때가 있습니다. 주로 관계가 확정된 후에야 값을 가질 수 있는 관계에 있는 속성이 존재하기 때문입니다. 사용자 테이블이 도형 필드를 보유하고 있는 경우 피벗 테이블의 외래 키 필드에 대해 On map identification 옵션을 (Layer Properties ► Attributes Form ► Available widgets ► Fields) 활성화시켜보면 재미있을 수도요.

참고

피벗 테이블의 기본 키

피벗 테이블의 기본 키에 여러 필드를 사용하는 일을 피하십시오. QGIS는 단일 기본 키를 가정하기 때문에 constraint airports_airlines_pkey primary key (airport_fk, airline_fk) 같은 제약조건은 작동하지 않을 것입니다.

16.4.2.3. 다형성 관계

목적

다형성 관계(polymorphic relation)는 1대다(1-N) 관계의 특례로, 단일 (문서) 참조 레이어가 참조되는 레이어 여러 개의 피처를 담고 있는 경우입니다. 서로 다른 참조하는 레이어가 각각 참조되는 레이어를 필요로 하는 일반적인 관계와는 다릅니다. (문서) 참조하는 레이어에 참조되는 레이어를 식별하기 위한 정보를 저장하는 추가적인 layer_field 열을 추가하면 단일 (문서) 참조 레이어를 생성할 수 있습니다. 가장 단순한 형태의 경우, (문서) 참조 레이어는 그냥 이 필드에 참조되는 레이어의 레이어 이름을 삽입할 것입니다.

좀 더 정확하게 말하자면, 다형성 관계란 참조하는 레이어는 동일하지만 참조되는 레이어는 동적으로 정의되는 일반적인 관계들의 집합입니다. 레이어의 다형성 설정은 참조되는 레이어의 테이블 이름, 레이어 ID, 레이어 이름 같은 일부 속성과 일치해야 하는 표현식을 이용해서 정의할 수 있습니다.

공원에 방문해서 그곳에서 볼 수 있는 다양한 plantsanimals 종들의 사진을 찍는다고 상상해보십시오. 각 식물 또는 동물과 관련된 사진이 여러 장일 것이기 때문에, 일반적인 일대다 관계를 이용해서 사진을 저장하는 경우 animal_imagesplant_images, 2개의 개별 테이블이 필요할 것입니다. 테이블이 2개라면 문제가 되지 않을 수도 있겠지만, 버섯이나 새 등등에 대해서도 개별적으로 사진을 찍기를 원한다면 어떨까요.

다형성 관계는 모든 참조 피처를 동일한 documents 테이블에 저장함으로써 이 문제를 해결합니다. 각 피처에 대해 referenced_layer 필드에 참조되는 레이어를, referenced_fk 필드에 참조되는 피처의 ID를 저장해서 말이죠.

다형성 관계 정의하기

먼저, Project ► Properties… 메뉴를 통해 QGIS에 레이어들 간의 다형성 관계가 존재한다는 사실을 알리십시오. Relations 탭으로 가서 symbologyAdd Add Relation 버튼 옆에 있는 아래 방향 화살표를 클릭하면, 새로 나타나는 드롭다운 목록에서 Add Polymorphic Relation 옵션을 선택할 수 있습니다.

../../../_images/polymorphic_relation_properties.png

그림 16.112 documents 레이어를 참조하는 레이어로, animalsplants 레이어를 참조되는 레이어로 이용해서 다형성 관계를 추가합니다.

  • ID: 내부 목적으로 사용되며, 유일한 값이어야 합니다. 사용자 지정 양식 을 작성하기 위해 필요할 수도 있습니다. 이 항목을 비워둘 경우, 자동적으로 생성되지만 사용자가 더 쉽게 다룰 수 있는 ID를 직접 할당할 수도 있습니다.

  • 참조하는 레이어(Referencing Layer) (자식): 자식 레이어로도 간주되는 이 레이어가 외래 키 필드를 담고 있습니다. 이 예시에서는 documents 레이어입니다. 이 레이어의 경우 다른 레이어를 가리키는 참조하는 필드를 추가해야 합니다. 이 예시에서는 referenced_fk 입니다.

    참고

    어떤 경우, 레이어에 있는 피처들을 유일하게 식별하기 위해 단일 필드 이상이 필요할 때가 있습니다. 이런 레이어와의 관계를 생성하는 데에는 복합 키(composite key), 예를 들어 일치하는 필드들의 단일 쌍 이상이 필요합니다. symbologyAdd Add new field pair as part of a composite foreign key 버튼을 이용해서 필요한만큼 많은 쌍을 추가하십시오.

  • 레이어 필드: 평가된 레이어 표현식의 결과를 저장하는, 해당 피처가 속해 있는 참조하는 테이블인, 참조하는 테이블에 있는 필드입니다. 이번 예시에서는 referenced_layer 필드입니다.

  • 레이어 표현식: 이 표현식의 평가 결과가 레이어의 유일 식별자가 됩니다. 레이어 이름 @layer_name, 레이어 ID @layer_id, 레이어의 테이블 이름 decode_uri(@layer, 'table'), 또는 레이어를 유일하게 식별할 수 있다면 무엇이든 가능합니다.

  • 관계 강도(Relationship Strength): 상위(부모)와 하위(자식) 레이어 사이에 생성된 관계의 강도를 설정합니다. 기본 Association 유형은 상위 레이어가 하위 레이어에 단순하게 링크되어 있다는 의미인 반면, Composition 유형은 상위 피처를 복제할 때 하위 피처도 복제할 수 있으며 상위 레이어의 피처를 삭제하면 하위 피처도 삭제할 수 있는 등, 모든 수준에서 순차적(cascade)으로 결과물을 산출합니다. (다시 말해 하위의 하위의 … 하위 피처도 삭제할 수 있다는 뜻입니다.)

  • 참조되는 레이어: 상위(부모) 레이어로도 간주되는 참조된 레이어는 기본 키(primary key)가 가리키는 레이어이기 때문에, 이 예시에서는 plantsanimals 레이어입니다. 드롭다운 메뉴에서 참조되는 레이어의 기본 키를 정의해야 합니다. 이 예시에서는 fid 입니다. 무결한 기본 키를 정의하려면 참조되는 레이어 모두가 이 이름을 가진 필드를 가지고 있어야 한다는 사실을 기억하십시오. 참조되는 레이어 가운데 하나에라도 이 이름을 가진 필드가 없다면, 다형성 관계를 저장할 수 없습니다.

다형성 관계를 추가하고 나면, Edit Polymorphic Relation 메뉴 항목을 통해 다형성 관계를 편집할 수 있습니다.

../../../_images/polymorphic_relations.png

그림 16.113 새로 생성한 다형성 관계와 이 관계의 동식물에 대한 하위(자식) 관계의 미리보기

이 예시는 다음과 같은 데이터베이스 스키마를 이용합니다:

CREATE SCHEMA park;

CREATE TABLE park.animals
(
   fid serial NOT NULL,
   geom geometry(Point, 4326) NOT NULL,
   animal_species text NOT NULL,
   CONSTRAINT animals_pkey PRIMARY KEY (fid)
);

CREATE INDEX animals_geom_idx ON park.animals USING gist (geom);

CREATE TABLE park.plants
(
   fid serial NOT NULL,
   geom geometry(Point, 4326) NOT NULL,
   plant_species text NOT NULL,
   CONSTRAINT plants_pkey PRIMARY KEY (fid)
);

CREATE INDEX plants_geom_idx ON park.plants USING gist (geom);

CREATE TABLE park.documents
(
   fid serial NOT NULL,
   referenced_layer text NOT NULL,
   referenced_fk integer NOT NULL,
   image_filename text NOT NULL,
   CONSTRAINT documents_pkey PRIMARY KEY (fid)
);