- Cypher & GQL
세상이 본 대로, 국제탐사보도언론인협회(ICIJ)는 노출된 고도로 연결된 네트워크, 즉 세계에서 가장 부유한 엘리트들이 사용하는 역외 조세 구조를 밝혀냈어요.
이러한 구조는 유출된 금융 문서에서 드러났고, 언론인들이 분석했는데요. 그들은 Apache Solr와 Tika를 사용해서 문서의 메타데이터를 추출한 다음, 유출된 데이터베이스를 이용해서 모든 정보를 연결해서 **nodes**와 **edges**의 그래프를 만들었어요. 이 그래프는 로 구축되었고, Linkurious' 시각화 애플리케이션을 통해 액세스할 수 있게 만들었죠.
이번 포스팅에서는 ICIJ에서 사용한 그래프 데이터 모델을 살펴보고, Cypher를 사용해서 Neo4j에서 이를 구성하는 방법을 보여드릴게요. 유출된 데이터에서 예제를 분석하고, Cypher를 사용해서 이를 다시 생성하고, 모델이 어떻게 확장될 수 있는지 보여줄 거예요.
문서 분석과 관련된 단계
- 스캔/OCR
- 문서 메타데이터 추출
- 엔터티 및 해당 관계 결정
- 잠재적 엔터티 및 관계 속성 결정
- 해당 엔터티 및 해당 속성의 소스 결정
- 문서에 대한 분석기, 규칙, 파서 및 명명된 엔터티 인식 작업
- 문서 메타데이터와 문서 및 엔터티 관계를 구문 분석하고 저장합니다.
- 저자, 명명된 엔터티, 날짜, 출처 및 분류별로 구문 분석합니다.
- 엔터티 관계 추론
- 유사성, 전이적 표지 및 삼각형 계산
- Graph 쿼리 및 시각화를 사용하여 데이터 분석
Graph에서 트라이어드를 찾으면 추론된 연결을 표시할 수 있어요. 여기 Bob은 CompanyA를 통해 CompanyB와 추론된 연관성이 있네요.
문서에서 Graph로
지주 내 비즈니스 상호 관계의 조직 영역에 대한 간단한 모델은 간단하고 다음에서 사용하는 모델과 유사합니다. , Neo4j의 일반적인 사용 사례이죠. 최소한 다음이 필요해요.
- 클라이언트
- 임원(자연인 및 회사 모두)
이러한 관계를 사용하면 다음과 같아요.
(:Officer)-[:is officer of]->(:Company)- 다음과 같은 분류를 사용합니다.
- 수익자, 주주, 이사
(:Officier)-[:registered address]->(:Address)(:Client)-[:registered]->(:Company)(:Officer)-[:has similar name and address]->(:Address)
이러한 모든 엔터티에는 문서 번호, 지분 금액, 참여 시작 및 종료 날짜, 주소, 시민권 등과 같은 많은 속성이 있어요. 동일한 이름을 가진 두 개체에는 매우 다른 양의 정보가 첨부될 수 있지만 이는 출처에서 추출된 관련 정보에 따라 달라요. 예를 들어 일부 경찰관은 이름만 갖고 있고 다른 경찰관은 15개 이상의 속성이 포함된 전체 기록을 가지고 있답니다.
이들은 사람이 회사의 "임원"인 것처럼 특정한 관계를 가지고 있어요. 이는 조세 피난처 위장 회사(일명)를 보유한 문서에서 채울 수 있는 기본 도메인입니다. #파나마페이퍼.
처음에는 원시 문서를 유형 및 하위 유형(예: 또는 )으로 분류해요. 그런 다음 문서 유형(예: 이메일의 발신자와 수신자, 계약 당사자)에서 직접 및 간접 메타데이터를 최대한 많이 첨부하죠. 추론된 메타데이터는 문서의 콘텐츠에서 얻는데요. 이때 Natural Language Processing, 명명된 엔터티 인식 또는 고유한 이름이나 역할과 같은 잘 알려진 용어에 대한 일반 텍스트 검색과 같은 기술을 활용할 수 있어요.
Graph 모델을 구축하는 첫 번째 단계는 문서와 해당 메타데이터에서 명명된 엔터티를 추출하는 거예요. 여기에는 회사, 개인, 주소가 포함되죠. 이러한 엔터티는 그래프의 Node가 되고요. 예를 들어 회사 등록 문서에서 회사 및 임원 엔터티를 추출할 수 있어요.
일부 Relationship은 문서에서 직접 추론할 수 있어요. 이전 예에서는 임원을 회사에 직접 연결된 것으로 모델링했죠.
(:Officer)-[:IS_OFFICER_OF]->(:Company)
이메일 기록을 분석하면 다른 Relationship도 추론할 수 있어요. 한 사람과 회사 사이에 여러 개의 이메일이 있다면, 그 사람이 해당 회사의 고객이라고 추론할 수 있는 거죠.
(:Client)-[:IS_CLIENT_OF]->(:Company)
유사한 논리를 사용해서 동일한 주소를 공유하거나, 가족 관계 또는 비즈니스 관계가 있거나, 정기적으로 통신하는 엔터티 간의 Relationship을 생성할 수 있어요.
- 직접 메타데이터 -> 엔터티 -> 문서와의 Relationship
- 작성자, 수신자, 계정 소유자, 첨부된, 언급된, 같은 위치에 있는
- 레지스트리 및 프로필 문서를 사용하여 일반 엔터티/이름을 전체 기록으로 전환
- 다른 소스로부터 추론된 메타데이터 및 정보 -> 엔터티 간의 Relationship
- 직접 메타데이터의 사람 또는 조직과 관련됨
- 동일한 주소/조직
- 사기 활동 내에서 피어 그룹/링 찾기
- 가족관계, 사업관계
- 통신 체인의 일부
ICIJ가 사용하는 그래프 데이터 모델
ICIJ 데이터 모델의 문제
ICIJ 데이터 모델에는 모델링 및 데이터 품질 문제가 있어요.
ICIJ 데이터에는 중복된 내용이 많이 포함되어 있지만, 그 중 "유사한 이름이나 주소가 있음" Relationship으로 연결된 것은 극히 일부에 불과하고, 대부분 이름의 첫 번째와 마지막 부분, 주소 및 가족 관계로 유추할 수 있죠. 또한 데이터 모델이 이러한 중복 항목을 실제로 병합하는 것이 유익할 수 있으며, 그러면 특정 중복 Relationship도 병합될 수 있어요.
ICIJ 데이터 모델에서 주식 수, 발행일 등과 같은 주주 정보는 임원이 여러 회사의 주주가 될 수 있는 "임원"에 저장되는데요. 해당 주주 정보를 "임원 - 주주" Relationship에 저장하는 것이 더 나을 거예요.
부울 속성 중 일부는 Label로 표시될 수 있어요. "시민권=예"는 Person Label이 되는 거죠.
ICIJ가 사용하는 기본 그래프 모델을 어떻게 확장할 수 있을까요?
ICIJ가 사용하는 도메인 모델은 정말 기본적이며 네 가지 유형의 엔터티(책임자, 클라이언트, 회사, 주소)와 이들 간의 네 가지 Relationship만 포함하는데요. 조직 관계에 대한 정적인 관점이지만 상호 작용이나 활동은 포함되지 않아요. 보고서에 설명된 소스 문서와 기타 활동을 살펴보면 이 Graph 모델을 더욱 풍부하게 만들어 표현력을 높일 수 있는 더 많은 것들이 있답니다.
우리는 다음을 모델링할 수 있어요. 와 그들의 메타데이터와 사람들과의 Relationship. 그러한 Relationship의 일부는 대화의 일부이거나 언급되거나 문서의 주제에서 추론되는 Relationship이기도 해요. 다른 흥미로운 Relationship은 분석 중에 사용된 개체의 별칭과 해석으로, 이를 통해 다른 언론인이 원래 사고 과정을 재현할 수 있죠.
또한 기업 등록, 감시 목록, 인구 조사 기록 또는 기타 언론 데이터베이스와 같은 추가 정보에 대한 출처를 추가할 수 있어요. 가족이나 사업 관계와 같은 인간 관계는 명시적으로 생성될 수도 있고, 행위자가 동일한 사기 집단이나 조직에 속해 있다고 추론하는 암묵적인 Relationship도 생성될 수 있죠.
누락된 또 다른 측면은 활동과 자금 흐름이에요. 활동의 예로는 계정 개설/폐쇄, 회사 설립 또는 합병, 해당 회사에 대한 기록 제출 또는 책임 할당 등이 있죠. 자금 흐름의 경우 언급된 금전 거래에 사용된 은행, 계좌 및 중개자를 추적할 수 있으므로 이체 금액과 이체 패턴에 대한 개요를 얻을 수 있어요. 그런 다음 이러한 패턴을 적용하여 다른 거래 시스템에서 추가적인 사기 자금 흐름을 추출할 수 있답니다.
Graph 데이터는 매우 유연하고 가단성이 있어요. 단일 연결 지점이 있으면 새로운 데이터 소스를 통합하고 이전에는 추적할 수 없었던 추가 패턴과 Relationship을 찾을 수 있죠.
- 새 엔터티:
- 문서: 이메일, PDF, 계약서, DB-기록, …
- 자금 흐름: 계좌/은행/중개업체
- 가족/사업 관계
- 동료 그룹/링
- 언급/주제
구체적인 예를 살펴볼까요?
가족 관계를 한번 살펴볼까요? 이 중에는 아제르바이잔의 대통령인 일함 알리예프도 있는데, 이미 Linkurious의 GraphGist에서 화제가 된 인물이죠. 아래 그림은 그의 아내, 두 딸, 그리고 아들을 보여주고 있어요.
ICIJ는 "파워 플레이어" 출판물에서 다음과 같이 인용했어요 (이름 강조는 추가되었습니다):
그의 가족은 경제의 거의 모든 부문에 대한 재정적 이해관계 덕분에 매력적이고 화려한 삶을 누리고 있어요. 그의 아내, 메리반은 은행, 보험 및 건설 회사, 텔레비전 방송국 및 화장품 라인을 소유한 특권적이고 강력한 Pashayev 가문 출신이에요. 그녀는 학교, 병원 및 국가의 주요 스포츠 단지 건설을 지원하는 아제르바이잔의 저명한 자선 단체인 Heydar Aliyev 재단을 이끌고 있죠. 그들의 큰 딸 레일라는 바쿠 잡지 편집장이고, 그녀의 언니, 아르주는 서부 마을인 Chovdar와 국내 최대 휴대전화 사업체인 Azerfon에서 금 채굴권을 획득한 회사의 재정적 지분을 보유하고 있어요. Arzu는 식사부터 공항 택시까지 아제르바이잔 항공(“Azal”)과 관련된 거의 모든 운영을 통제하는 SW Holding의 주요 주주이기도 해요. 자매 둘 다와 는 2010년에 두바이의 자체 자산 가치가 약 7,500만 달러였어요. Heydar는 약 4,400만 달러에 구입한 두바이의 고급 맨션 9채의 법적 소유자이죠.
저희는 ICIJ 시각화에서 데이터를 가져와 2D 그래프 시각화를 Cypher 쿼리 언어의 그래프 패턴으로 변환했어요. 자세히 보면 시각화에서와 동일한 구조를 볼 수 있을 거예요. "수혜자, 주주, 이사의 임원"만 IOO_BSD로 압축했고, 다른 "담당자" 관계 앞에는 IOO라는 접두사가 붙어있어요.
저희는 법인이나 관계의 자산인 주식, 시민권, 등록 번호 또는 주소를 추가하지 않았어요. 포함된 원본 시각화의 요소를 클릭하면 이를 볼 수 있을 거예요.
시각화된 엔터티 및 관계를 설정하는 Cypher 구문
CREATE
(leyla: Officer {name:"Leyla Aliyeva"})-[:IOO_BSD]->(ufu:Company {name:"UF Universe Foundation"}),
(mehriban: Officer {name:"Mehriban Aliyeva"})-[:IOO_PROTECTOR]->(ufu),
(arzu: Officer {name:"Arzu Aliyeva"})-[:IOO_BSD]->(ufu),
(mossack_uk: Client {name:"Mossack Fonseca & Co (UK)"})-[:REGISTERED]->(ufu),
(mossack_uk)-[:REGISTERED]->(fm_mgmt: Company {name:"FM Management Holding Group S.A."}),
(leyla)-[:IOO_BSD]->(kingsview:Company {name:"Kingsview Developents Limited"}),
(leyla2: Officer {name:"Leyla Ilham Qizi Aliyeva"}),
(leyla3: Officer {name:"LEYLA ILHAM QIZI ALIYEVA"})-[:HAS_SIMILIAR_NAME]->(leyla),
(leyla2)-[:HAS_SIMILIAR_NAME]->(leyla3),
(leyla2)-[:IOO_BENEFICIARY]->(exaltation:Company {name:"Exaltation Limited"}),
(leyla3)-[:IOO_SHAREHOLDER]->(exaltation),
(arzu2:Officer {name:"Arzu Ilham Qizi Aliyeva"})-[:IOO_BENEFICIARY]->(exaltation),
(arzu2)-[:HAS_SIMILIAR_NAME]->(arzu),
(arzu2)-[:HAS_SIMILIAR_NAME]->(arzu3:Officer {name:"ARZU ILHAM QIZI ALIYEVA"}),
(arzu3)-[:IOO_SHAREHOLDER]->(exaltation),
(arzu)-[:IOO_BSD]->(exaltation),
(leyla)-[:IOO_BSD]->(exaltation),
(arzu)-[:IOO_BSD]->(kingsview),
(redgold:Company {name:"Redgold Estates Ltd"}),
(:Officer {name:"WILLY & MEYRS S.A."})-[:IOO_SHAREHOLDER]->(redgold),
(:Officer {name:"LONDEX RESOURCES S.A."})-[:IOO_SHAREHOLDER]->(redgold),
(:Officer {name:"FAGATE MINING CORPORATION"})-[:IOO_SHAREHOLDER]->(redgold),
(:Officer {name:"GLOBEX INTERNATIONAL LLP"})-[:IOO_SHAREHOLDER]->(redgold),
(:Client {name:"Associated Trustees"})-[:REGISTERED]->(redgold)
흥미로운 쿼리
성을 통한 가족 관계:
MATCH (o:Officer)
WHERE toLower(o.name) CONTAINS "aliyev"
RETURN o
가족 참여:
MATCH (o:Officer) WHERE toLower(o.name) CONTAINS "aliyev"
MATCH (o)-[r]-(c:Company)
RETURN o,r,c
회사의 임원은 누구이며 그 역할은 무엇일까요?
MATCH (c:Company)-[r]-(o:Officer) WHERE c.name = "Exaltation Limited"
RETURN *
가족 구성원의 합작 회사 참여 표시
MATCH (o1:Officer)-[r1]->(c:Company)<-[r2]-(o2:Officer)
WITH o1.name AS first, o2.name AS second, count(*) AS c,
collect({ name: c.name, kind1: type(r1), kind2:type(r2)}) AS involvements
WHERE c > 1 AND first < second
RETURN first, second, involvements, c
중복 Entity 해결
MATCH (o:Officer)
RETURN toLower(split(o.name," ")[0]), collect(o.name) as names, count(*) as count
이름의 첫 번째 부분과 마지막 부분으로 중복 Entity 해결
MATCH (o:Officer)
WITH split(toLower(o.name), " ") AS name_parts, o
WITH name_parts[0] + " " + name_parts[-1] as name, collect(o.name) AS names, count(*) AS count
WHERE count > 1
RETURN name, names, count
ORDER BY count DESC
해당 예시에서 Mossack에서 Officers로의 전이 경로
MATCH path=(:Client {name: "Mossack Fonseca & Co (UK)"})-[*]-(o:Officer)
WHERE none(r in rels WHERE type(r) = "HAS_SIMILIAR_NAME")
RETURN [n in nodes(path) | n.name] as hops, length(path)
두 사람 사이의 최단 경로
MATCH (a:Officer {name: "Mehriban Aliyeva"})
MATCH (b:Officer {name: "Arzu Aliyeva"})
MATCH p=shortestPath((a)-[*]-(b))
RETURN p
추가 작업 – 모델 확장
중복 병합
개인 `Node`를 생성하고 모든 임원을 해당 개인에게 연결해볼게요. 중복 감지 명령문을 재사용하면 되겠죠?
MATCH (o:Officer)
WITH split(toLower(o.name), " ") AS name_parts, o
WITH name_parts[0]+ " " + name_parts[-1] AS name, collect(o) AS officers
// originally natural people have a “citizenship” property
WHERE name CONTAINS "aliyev"
CREATE (p:Person { name:name })
FOREACH (o IN officers | CREATE (o)-[:IDENTITY]->(p))
그 사람들 사이에 가족 관계를 추가해볼까요?
CREATE (ilham:Person {name:"ilham aliyev"})
CREATE (heydar:Person {name:"heydar aliyev"})
WITH ilham, heydar
MATCH (mehriban:Person {name:"mehriban aliyeva"})
MATCH (leyla:Person {name:"leyla aliyeva"})
MATCH (arzu:Person {name:"arzu aliyeva"})
FOREACH (child in [leyla,arzu,heydar] | CREATE (ilham)-[:CHILD_OF]->(child) CREATE (mehriban)-[:CHILD_OF]->(child))
CREATE (leyla)-[:SIBLING_OF]->(arzu)
CREATE (leyla)-[:SIBLING_OF]->(heydar)
CREATE (arzu)-[:SIBLING_OF]->(heydar)
CREATE (ilham)-[:MARRIED_TO]->(mehriban)
가족 관계를 시각화해봐요
MATCH (p:Person) RETURN p
회사와의 가족 관계도 알아볼까요?
MATCH (p:Person) WHERE p.name CONTAINS "aliyev"
OPTIONAL MATCH (c:Company)<--(o:Officer)-[:IDENTITY]-(p)
RETURN c,o,p
GraphGist
여기서 예제 데이터 세트를 직접 탐색해볼 수 있어요. 대화형 그래프 모델 문서(GraphGist라고 해요). 다양한 사용 사례와 산업에 대한 더 많은 정보는 GraphGist 포털에서 찾아볼 수 있답니다.
관련 정보
- Neo4j를 사용한 Gmail 이메일 분석
- 받은 편지함 및 그래프
- 기존 GraphGists
- ICIJ 역외 관할권
- 아제르바이잔 대통령의 개입에 대한 상세한 분석
Neo4j를 사용해서 이와 비슷한 자신만의 프로젝트를 시작하고 싶으신가요? 아래를 클릭해서 O'Reilly eBook의 무료 사본을 받고 지금 바로 Graph Database를 시작해보세요!
- 아제르바이잔
- Cypher
- icij
- 링크리어스
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.
'Neo4j' 카테고리의 다른 글
| Neo4j로 롤랑 가로스와 US 오픈 테니스 토너먼트 분석하기 (1) | 2026.09.08 |
|---|---|
| Neo4j로 파라다이스 페이퍼 분석: 쿼리, 데이터 모델 심층 탐구 (0) | 2026.09.08 |
| Neo4j로 FinCEN 파일 분석하기 (0) | 2026.09.08 |
| Neo4j 사용자 정의 함수로 복잡한 네트워크 분석하기 (0) | 2026.09.08 |
| Neo4j에서 분석적 서브그래프 오버레이 활용하기 (0) | 2026.09.07 |
