💡 핵심 인사이트 PageRank와 BFS(너비 우선 탐색)는 **"그래프(Network) 구조에서 핵심적인 순회(Traversal) 및 중요도 산출 알고리즘"**입니다. PageRank는 **"다른 노드에서 많이 링크되는 노드가重要"**라는 아이디어로 웹 페이지 순위를 매기는算法이며, BFS는 **"시작점에서 가까운 노드부터 체계적으로 탐색"**하는 그래프 순회 알고리즘입니다. PageRank가 Google 검색엔진의根基라면, BFS는 소셜 네트워크 분석, 경로 탐색, 레벨 오더婚礼请客配席 등 다양한实际问题에서 활용됩니다.


Ⅰ. PageRank: 웹의 중요도를測る算法

PageRank의 핵심 아이디어

PageRank는 **"중요한 페이지는 다른 중요 페이지에서 링크를 많이 받는다는 가정"**에 기반합니다:

[PageRank 개념]

  웹 페이지들 사이의 링크 관계:

        Page A (importance = ?)
           │links
           ▼
        ┌────────┐     ┌────────┐
        │ Page B │────▶│ Page C │
        └────────┘     └────────┘
           │links          │links
           ▼               ▼
        ┌────────┐     ┌────────┐
        │ Page D │◀────│ Page E │
        └────────┘     └────────┘

  직관적 의미:
  - Page C: A, B, E에서 링크됨 (3개) → 중요!
  - Page B: C에게만 링크됨 (1개) → 덜 중요
  - Page D: B에게만 링크됨 (1개) → 덜 중요
  - PageRank:links의 질(출발점 중요도)도 고려

PageRank 공식

[PageRank 계산 공식]

  PR(A) = (1 - d)/N + d × Σ( PR(Ti) / C(Ti) )

  where:
  - PR(A): 페이지 A의 PageRank
  - d: damping factor (보통 0.85)
  - N: 전체 페이지 수
  - Ti: 페이지 A로 링크하는 페이지
  - C(Ti): 페이지 Ti가 가진 외부 링크 수
  - Σ: 모든 Ti에 대한 합산

  의미:
  - damping factor: 사용자가 무작위 페이지로 이동할 확률 (0.85)
  - 1-d: 무작위 점프할 확률 (0.15)

PageRank 코드 예시

import numpy as np

def pagerank(adj_matrix, d=0.85, max_iter=100, tol=1e-6):
    """
    adj_matrix: 인접 행렬 (N x N)
                adj_matrix[i][j] = 1 if i → j 링크 존재
    """
    N = adj_matrix.shape[0]

    # 초기 PageRank (균등 분배)
    pr = np.ones(N) / N

    # 반복 계산
    for _ in range(max_iter):
        new_pr = (1 - d) / N + d * adj_matrix.T.dot(pr / adj_matrix.sum(axis=1))

        # 수렴 판정
        if np.linalg.norm(new_pr - pr, 1) < tol:
            break
        pr = new_pr

    return pr

# 예시: 4개 페이지의 링크 관계
# A → B, C / B → C / C → A / D → C
adj = np.array([
    [0, 1, 1, 0],  # A → B, C
    [0, 0, 1, 0],  # B → C
    [1, 0, 0, 0],  # C → A
    [0, 0, 1, 0],  # D → C
])
pr = pagerank(adj)
print(f"PageRank: {pr}")
# 결과: C가 가장 높은 PageRank (링크를 3개 받음)

II. BFS (Breadth-First Search): 체계적 탐색의 기본

BFS의 원리

[BFS vs DFS]

  그래프:
       A
      / \
     B   C
    / \   \
   D   E   F

  BFS (Queue 기반, 레벨 순회):
  Queue: [A]
  1. A dequeue → 방문 → A의 이웃 B, C enqueue
  Queue: [B, C]
  2. B dequeue → 방문 → B의 이웃 D, E enqueue
  Queue: [C, D, E]
  3. C dequeue → 방문 → C의 이웃 F enqueue
  Queue: [D, E, F]
  4. D, E, F 순서로 dequeue/방문

  순서: A → B → C → D → E → F
  (레벨순: 0레벨 → 1레벨 → 2레벨)

  DFS (Stack 기반, 깊이 우선):
  순서: A → B → D → E → C → F
  (한 방향으로 최대한 파고들기)

BFS 코드

from collections import deque

def bfs(graph, start):
    """
    graph: 인접 리스트 {node: [neighbors]}
    start: 시작 노드
    """
    visited = set()
    queue = deque([start])
    order = []

    while queue:
        node = queue.popleft()  # 선입선출
        if node not in visited:
            visited.add(node)
            order.append(node)
            queue.extend(graph[node] - visited)

    return order

# 예시: 길찾기
graph = {
    'A': {'B', 'C'},
    'B': {'A', 'D', 'E'},
    'C': {'A', 'F'},
    'D': {'B'},
    'E': {'B', 'F'},
    'F': {'C', 'E'}
}

print(bfs(graph, 'A'))
# 출력: ['A', 'B', 'C', 'D', 'E', 'F']
# → A에서 F까지의 최단 경로: A → B → E → F 또는 A → C → F

III. PageRank와 BFS의 관계と活用

[PageRank와 BFS의 관계]

  공통점:
  - 둘 다 그래프/네트워크 순회 알고리즘
  - 연결된 노드들을 따라가며 정보 전파

  차이점:
  ┌────────────────┬────────────────────────┐
  │    PageRank    │         BFS            │
  ├────────────────┼────────────────────────┤
  │  모든 노드를   │ 한 시작점에서 체계적 탐색│
  │  동시에 평가   │                         │
  ├────────────────┼────────────────────────┤
  │  반복 계산으로 │ 한 번의 순회로 완료      │
  │  수렴 달성    │                         │
  ├────────────────┼────────────────────────┤
  │  중요도(순위) │ 최단 경로, 연결 요소,   │
  │  산출        │ 레벨별 탐색             │
  ├────────────────┼────────────────────────┤
  │  시간: O(I×E) │ 시간: O(V+E)            │
  │  (I=반복 횟수)│                        │
  └────────────────┴────────────────────────┘

실제 활용

[PageRank 활용 사례]

  1. 웹 검색 (원래 목적)
     - Google의 PageRank → 이후 더 정교한 알고리즘으로 발전
     - 현재도 인용 네트워크, 연구자 영향력 등에 활용

  2. 소셜 네트워크 중요 인물 탐지
     - 트위터에서 중요한 사용자 순위
     - 링크드인에서 영향력 있는 프로фессионал

  3. 학술 논문 인용 네트워크
     - 어떤 논문이 많이 인용되었는가?
     - H-index와 함께 활용

  4. 교통 네트워크
     - 도시별 중요도 평가
     - 고속도로 정체 구간 예측


[BFS 활용 사례]

  1. 최단 경로 찾기 (无权 그래프)
     - 미로 찾기, 네비게이션
     - 소셜 네트워크에서 "친구关系的度数" 계산

  2. 레벨별 순회
     - 조직도 레벨 탐색
     - 게임에서 동일 레벨 적 탐색

  3. 연결 요소 판별
     - 네트워크 분할 발견
     - 사회망에서 친구 그룹 분류

  4. 그레이햄 스캔 (Graham Scan)
     - 볼록 껍질(Convex Hull) 계산

IV. PageRank와 BFS의graph DB 적용

Neo4j (그래프 DB)에서 PageRank:

// Neo4j에서 PageRank 알고리즘 활용
// gds 라이브러리 사용

CALL gds.pageRank.stream({
  nodeProjection: 'Page',
  relationshipProjection: 'LINKS_TO'
})
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).url AS page, score
ORDER BY score DESC
LIMIT 10;

Neo4j에서 BFS:

// 최단 경로 찾기 (BFS 기반)
MATCH (start:User {name: 'Alice'}),
      (end:User {name: 'Eve'})
MATCH path = shortestPath((start)-[:KNOWS*]-(end))
RETURN path;

// BFS로 레벨별 탐색 (친구의 친구)
MATCH (start:User {name: 'Bob'})-[:KNOWS*1..2]-(friend)
RETURN DISTINCT friend.name, LENGTH(foo(path)) AS degree
ORDER BY degree;

Ⅴ. 알고리즘 선택 가이드と 📢 비유

어떤 알고리즘을 선택하는가?

[선택 기준]

  PageRank를 써야 할 때:
  - 전체 네트워크에서 "중요한 노드"를 찾고 싶다
  -links/인용/참조의 질을 평가하고 싶다
  - 반복적 수렴이許容된다

  BFS를 써야 할 때:
  - 시작점에서 가까운 노드를 체계적으로 찾고 싶다
  - 최단 경로를 찾고 싶다 (无权)
  - 한 번의 탐색으로 충분하다

📢 섹션 요약 비유: PageRank와 BFS는 **"도시의 importância를 평가하는 두 가지 방법"**과 같습니다. PageRank는 **"다른 중요한 도시에서 많이 연결되는 도시가 중요한 도시다"**라는 순환적定義로, 결국 모든 도시의重要性を迭代적으로 계산합니다. "이 도시에 사람들이 많이 오고 간다"를 직접 세는 것이 아니라, "어떤 도시에서 사람들이 많이 오고 가는가?"를繰り返し 계산해서 도달합니다. 반면 BFS는 **"시내 중심가에서 시작해서 1번으로 시작해서 바깥으로一圈一圈 넓혀나가는 것"**입니다.中心からの距離に応じて 순서대로 탐색하여, **"여기서 거기까지 가려면 어떻게 가야 가장 짧은가?"**를 확실히 찾아냅니다. PageRank가 **"全局적 중요도"**를评估한다면, BFS는 **"局部적最近접"**을探索합니다. 둘 다 그래프라는 같은 구조를 다루지만,問いと答える内容が根本的に異なります.