NetworkX로 구현하는 그래프 중심성·커뮤니티 분석

NetworkX 기반 네트워크 분석에서 그래프 모델링, 중심성 지표, 커뮤니티 탐지 알고리즘 선택과 재현성 관리 방법을 정리한다.

2026-08-14 · 최초 발행 2024-04-29

관계를 그래프로 바꾸면 보이는 구조

로그, 거래, 사용자 연결처럼 관계가 중심인 데이터는 개별 레코드만으로는 구조를 읽기 어렵다. 네트워크 분석은 이를 정점과 간선으로 구성된 그래프로 옮겨 영향력이 큰 노드, 연결의 병목, 밀집한 집단을 정량적으로 다룬다.

그래프 모델은 방향성 여부, 가중치 사용 여부, 다중 간선 허용 여부에 따라 달라진다. 분석 전에 노드 ID를 표준화하고 속성의 타입과 정규화 방식을 정해야 한다. 중복 간선, 자기루프, 고립 노드를 어떻게 처리할지와 시간축을 스냅샷으로 볼지 증분으로 관리할지도 함께 결정한다.

중심성은 네트워크 안에서 중요한 노드를 계산하는 지표군이다. Degree는 연결 수를 기준으로 지역적 영향도를 보며 계산 비용이 낮다. Betweenness와 Closeness는 전역 최단 경로를 기반으로 하므로 계산 비용이 커서 근사법을 고려할 수 있다. PageRank와 고유벡터 중심성은 확산과 권위 전파의 관계를 해석할 때 쓴다.

커뮤니티는 내부 연결은 촘촘하고 외부 연결은 상대적으로 성긴 노드 집합이다. Louvain은 모듈러리티를 극대화하며 대규모 그래프에 적합하지만 랜덤 초기화에 따른 재현성 관리가 필요하다. Label Propagation은 선형급으로 간단하고 빠르지만 결과 변동성이 크다. Girvan-Newman은 엣지 중심성을 바탕으로 계층적으로 분해해 설명력이 좋지만 계산량이 커서 소규모 분석에 맞는다.

분석 목적이 지표와 알고리즘을 가른다

금융 사기 분석에서는 중심성이 높은 이상치 노드와 커뮤니티 경계의 연결을 조사해 거래 그래프의 링 구조나 허브 계정을 찾을 수 있다. 보안과 위협 인텔리전스에서는 도메인-IP-파일 해시 그래프의 중개 노드를 통해 C2 인프라를 추적하고, 커뮤니티를 캠페인 클러스터 분할과 침해지표 전파 경로 분석에 활용한다.

추천과 소셜 그래프에서는 PageRank나 고유벡터 중심성으로 영향력자를 선정하고, 커뮤니티별로 관심사를 세분화한다. 사용자-아이템 이분 그래프라면 중심성 가중 추천에도 적용할 수 있다. IT 운영에서는 Betweenness가 높은 장비를 단일 장애점(SPoF) 후보로 식별하고, 커뮤니티 분석을 서브넷이나 도메인 경계 재설계에 연결할 수 있다.

규칙 기반 방식과 비교해 탐지 정확도는 F1 520%p 개선 가능하며, 이는 도메인에 의존한다. 근사·배치를 도입하면 계산 시간을 5090% 절감할 수 있고, 핵심 노드와 커뮤니티를 Top-K로 집약하면 조사 효율은 2~5배 높아질 수 있다. 관계 중심의 인사이트는 설명 가능한 의사결정과 구조적 리스크의 선제 대응에도 도움이 된다.

데이터 검증부터 운영 피드백까지

분석 흐름은 원천 로그, 트랜잭션, 관계 테이블과 ID 매핑 사전을 입력으로 받아 정합성을 검증하는 데서 시작한다. 방향성과 가중치를 적용해 그래프를 만든 뒤 중심성을 계산하고 커뮤니티를 탐지한다. 상위 노드와 커뮤니티 리포트, 시각화 결과를 검토해 운영 피드백과 파라미터 튜닝으로 이어간다.

누락·중복 ID, 음수·NaN 가중치, 고립 노드 비율 임계치 초과는 경고 또는 중단 조건으로 둔다. 랜덤 초기화가 있는 알고리즘은 seed를 고정하고, 결과가 불안정하면 여러 번 실행한 결과를 앙상블한다. 데이터 해시, 파라미터, 라이브러리 버전을 함께 관리해야 동일한 분석을 재현할 수 있다.

아니오입력 데이터(로그/트랜잭션/CSV/DB)검증/정제(스키마·ID·결측·중복)그래프 구축(방향/가중치/멀티에지)중심성 계산(Degree/Betweenness/Closeness/PageRank)커뮤니티 탐지(Louvain/LPA/GN)검증/해석(Top-K, 분포, 기준선)대규모 그래프?근사/샘플링/배치k-샘플, 반복 제한정밀 계산시각화/리포팅(대시보드/파일)운영 반영/피드백파라미터 튜닝/버전 고정

NetworkX로 중심성과 커뮤니티 계산하기

이 예제는 Python 3.10+, NetworkX 3.2+, pandas, matplotlib를 전제로 한다. Louvain을 사용하려면 python-louvain 설치가 필요하며, 설치 예시는 pip install "networkx>=3.2" pandas matplotlib python-louvain이다. 일부 API와 성능 특성은 최신 정보를 확인할 필요가 있다.

# Python 3.10+, NetworkX 3.2+ 가정
import networkx as nx
import pandas as pd

# 1) 예시 데이터: Karate Club 그래프
G = nx.karate_club_graph()

# 2) 중심성 지표 계산
deg = nx.degree_centrality(G)

# Betweenness: 대규모 그래프는 근사(k-샘플) 권장
bet = nx.betweenness_centrality(G, k=10, seed=42)  # k 생략 시 정확 계산(느림)

clo = nx.closeness_centrality(G)

# PageRank: 반복 수렴, alpha(감쇠) 조정
pr = nx.pagerank(G, alpha=0.85, max_iter=100)

# 3) 커뮤니티 탐지
from networkx.algorithms.community import girvan_newman, asyn_lpa_communities

# Girvan-Newman: 제너레이터의 첫 레벨 분할 사용(계층적)
gn_gen = girvan_newman(G)
comm_gn = [sorted(c) for c in next(gn_gen)]

# Label Propagation: 빠르나 결과 변동성, seed 고정
comm_lpa = [sorted(c) for c in asyn_lpa_communities(G, seed=42)]

# Louvain: python-louvain 필요
try:
    import community as community_louvain
    part = community_louvain.best_partition(G)  # node -> community id
    comm_louvain_map = {}
    for n, cid in part.items():
        comm_louvain_map.setdefault(cid, []).append(n)
    comm_louvain = [sorted(v) for v in comm_louvain_map.values()]
except Exception as e:
    print(f"[INFO] Louvain 미사용: {e}")
    comm_louvain = None

# 4) 결과 집계/상위 노드
df = pd.DataFrame({
    "node": list(G.nodes()),
    "degree_c": pd.Series(deg),
    "betweenness_c": pd.Series(bet),
    "closeness_c": pd.Series(clo),
    "pagerank": pd.Series(pr),
}).fillna(0)

top = df.sort_values("pagerank", ascending=False).head(10)
print(top)

# 5) 시각화(선택): PageRank로 크기, Louvain 커뮤니티로 색상
import matplotlib.pyplot as plt
pos = nx.spring_layout(G, seed=42)

if comm_louvain:
    color_map = {}
    for i, group in enumerate(comm_louvain):
        for n in group:
            color_map[n] = i
    node_color = [color_map[n] for n in G.nodes()]
else:
    node_color = "lightgray"

sizes = [300 + 2000 * df.set_index("node").loc[n, "pagerank"] for n in G.nodes()]

nx.draw_networkx(
    G, pos,
    with_labels=True,
    node_color=node_color,
    node_size=sizes,
    edge_color="#AAAAAA",
    font_size=8,
)
plt.title("Karate Club: PageRank size, Louvain color" if comm_louvain else "Karate Club: PageRank size")
plt.tight_layout()
plt.show()

Betweenness와 Closeness는 대규모 그래프에서 근사(k), 샘플링, 컴포넌트 단위 계산을 적용할 수 있다. PageRank는 max_itertol을 조정해 수렴과 실행 시간의 균형을 맞추고 Dangling 노드 처리도 확인한다. Louvain과 Label Propagation은 seed를 고정하고, 여러 번 실행한 결과의 합의(partition consensus)로 안정화한다.

운영 조건에 따른 선택 기준

알고리즘 성능(시간/공간) 확장성 일관성(재현성) 안정성(수렴/변동) 운영 편의
Degree Centrality 높음 우수 높음 높음 매우 쉬움
Betweenness (정확) 낮음 낮음/보통 높음 보통 보통
Betweenness (근사 k) 중간 보통/우수 보통(시드영향) 보통 보통
Closeness 중간 보통 높음 보통 보통
PageRank 중간(반복) 우수 높음 높음 쉬움
Louvain 높음 우수 보통(랜덤성) 보통 쉬움
Label Propagation 높음 우수 낮음 보통 쉬움
Girvan-Newman 낮음 낮음 높음 보통 낮음

“성능”은 일반적 경향을 요약한 것이며 실제 결과는 그래프 크기, 밀도, 구현에 따라 달라진다.

정확도와 비용은 충돌한다. Betweenness와 Closeness를 정확하게 계산하는 비용이 크다면 근사, 샘플링, PageRank 같은 대체 지표를 검토한다. Louvain과 Label Propagation은 변동성이 있으므로 여러 번 실행해 합의 결과를 사용하거나 Girvan-Newman으로 보조 검증할 수 있다. Girvan-Newman은 해석력이 좋지만 확장성이 낮아, 대규모 환경에서는 Louvain이나 LPA를 중심으로 운영하는 편이 맞다.

ID 유일성, 가중치 범위, 방향성 일관성을 확인하는 데이터 정합성 게이트를 둔다. seed, alpha, k, max_iter는 구성 파일로 외부화하고 결과와 함께 버전 관리한다. 최종 해석은 중심성이나 토폴로지 지표만으로 확정하지 않고 현업의 도메인 지식으로 검증하는 루프를 유지한다.

네트워크 분석그래프 이론중심성커뮤니티 탐지NetworkX