Skip to main content

Command Palette

Search for a command to run...

A* 탐색 알고리즘

Published
A* 탐색 알고리즘

원문: Claire Lee, A* Search Algorithm

A* 탐색 알고리즘은 가중 그래프의 시작 노드(출발지)목표 노드(목적지) 사이의 단일 쌍 최단 경로를 찾는 경로 탐색 알고리즘입니다. 이 알고리즘은 시작 노드에서 현재 노드(g)까지의 실제 비용을 고려할 뿐만 아니라 휴리스틱(h)을 사용하여 현재 노드에서 목표 노드까지 소요되는 비용도 추정합니다. 그런 다음 목표 노드에 도달할 때까지 이동할 다음 노드로 가장 낮은 f값(f=g+h)을 가진 노드를 선택합니다. 다익스트라(Dijkstra's) 알고리즘은 모든 노드에서 휴리스틱이 0인 A* 알고리즘의 또 다른 예시입니다.

A* 알고리즘 요약 카드


A* 알고리즘은 어떻게 작동하나요?

A* 알고리즘은 g(n)과 h(n)라는 두 가지 함수를 고려합니다. 현재 노드 n에 있다고 생각해 봅시다. g(n)은 시작 노드에서 현재 노드까지 실제 소요된 비용을 알려줍니다. h(n)은 현재 노드에서 목표 노드에 도달하는 데 소요될 비용을 추정하는 휴리스틱 함수입니다. 따라서 h(n)은 학습된 추측이며 A* 알고리즘의 성능을 결정하는 데 매우 중요합니다. g(n)과 h(n)의 합인 f(n)을 기반으로 시작 노드에서 끝 노드까지의 총 비용을 추정할 수 있습니다.

f(n) = g(n) + h(n)

  • f(n): 시작 노드에서 목표 노드까지의 추정된 총 비용

  • g(n): 시작 노드에서 노드 n까지 실제 소요된 비용

  • h(n): 노드 n에서 목표 노드까지 소요될 추정된 비용

이 알고리즘은 최소 f(n)값을 갖는 노드를 다음 탐색할 현재 노드로 선택하고 발견한 노드에서 더 나은 경로가 발견되면 g(n) 및 h(n)을 지속적으로 업데이트합니다. 이 과정은 알고리즘이 목표 노드에 도달할 때까지 계속됩니다.

A* 알고리즘 vs 다익스트라(Dijkstra's) 알고리즘

A* 알고리즘시작 노드와 목표 노드 사이의 최단 경로만 찾는 반면, Dijkstra 알고리즘은 그래프의 모든 노드가 목표 노드기 때문에 시작 노드에서 다른 모든 노드까지의 최단 경로를 찾습니다.

A* 알고리즘휴리스틱을 사용하여 목표 노드로 향하는 올바른 방향으로 안내하기 때문에 Dijkstra 알고리즘보다 빠르게 실행됩니다. 그러나 Dijkstra 알고리즘은 목표 노드에 대한 사전 지식이 없기 때문에 사용 가능한 모든 방향으로 고르게 확장되며 항상 이미 소요된 비용이나 거리를 기준으로 시작 노드에 가장 가까운 노드를 계산합니다.

A* 탐색 알고리즘 vs 다익스트라(Dijkstra) 알고리즘

그래프 설명

휴리스틱은 A* 알고리즘의 성능에 매우 중요합니다. 여기서는 데모 목적으로만 휴리스틱 기능을 사용합니다.

그래프 예시

  1. 1단계
  • a: 시작 노드까지의 거리를 0으로 설정하고 다른 모든 노드까지의 거리를 무한대로 설정합니다.

  • b: 시작 노드의 f 값을 계산하고 이전 노드를 none/nil/null로 설정합니다.

  • c: 처음에는 비어 있는 열린 목록닫힌 목록을 초기화합니다.

1단계

  1. 2단계: 시작 노드열린 목록에 넣습니다.

    2단계

  2. 3단계

    • a: 열린 목록에서 최소 f(n)값을 갖는 노드를 찾아 목록에서 제거합니다. 이 노드를 현재 노드로 표시합니다.

    • b: 현재 노드대상 노드인지 아닌지 확인합니다.

    • c: 현재 노드의 모든 이웃 노드채우고 각 이웃 노드에 대해 다음을 확인합니다.

    1. 이웃 노드가 닫힌 목록에 있나요?
       - 네. 이 노드를 건너뜁니다.
       - 아니요. 2로 이동합니다.
    2. 이웃 노드의 g 값을 계산하고 더 나은 경로가 있는지 확인합니다. 더 나은 경로(더 낮은 g 값)를 찾았나요?
       - 아니요. 이 노드를 건너뜁니다.
       - 네. 3으로 이동합니다.
    3. 이웃 노드의 g, h, f 값을 계산하고 현재 노드를 이전 노드로 설정합니다.
    4. 이웃 노드가 열린 목록에 있는지 확인합니다.
       - 네. 열린 목록에서 이웃 노드의 g, h, f 값을 업데이트합니다.
       - 아니요. 이 이웃 노드를 열린 목록에 삽입합니다.
  • d: 현재 노드를 다음 노드로 확장했으므로 현재 노드를 닫힌 목록에 배치합니다.

3단계

  1. 4단계: 대상 노드에 도달할 때까지 3단계를 반복합니다.

데모 반복 1회 차

반복 1-1

반복 1-2

반복 1-3

데모 반복 2회 차

반복 2-1

반복 2-2

반복 2-3

데모 반복 3회 차

반복 3-1

반복 3-2

반복 3-3

데모 반복 4회 차

반복 4-1

반복 4-2

반복 4-3

데모 반복 5회 차

반복 5-1

최종 결과

최종 결과

결국 이전 노드를 기록했으니 이를 통해 최단 경로를 역추적할 수 있습니다. 이 데모에서는 A* 알고리즘을 사용하여 그래프를 모두 탐색하지 않고 최단 경로를 탐색합니다. (아직 노드 4를 검사하지 않았으므로 노드 4가 열린 목록에 있는 것을 볼 수 있습니다). 이건 그래프의 모든 노드를 확장해야 하는 Dijkstra 알고리즘과 다릅니다.

Dijkstra 알고리즘에 대한 자세한 내용은 여기에서 확인할 수 있습니다.

코드 구현

자료 구조

우선순위 큐를 통해 각 실행에 대해 가장 낮은 f값 노드를 가져옵니다. 이 데모에서는 최소 힙 자료 구조를 사용하여 코드를 구현합니다.

복잡도

시간 복잡도: O(nlog(n)), 공간 복잡도: O(n)
n: 그래프 내에서 노드 개수

의사코드

# 시작 노드를 포함하는 최소 힙을 초기화
minHeap = MinHeap([start])

While minHeap is not empty:
  # 최소 힙에서 최소 f값을 가지는 노드를 가져온 후 현재 노드로 표시
  current = minHeap.pop()
  # 현재 노드가 목표 노드인지 확인
  if current == target:
      break

  # 현재 노드의 모든 이웃을 채우기
  for neighbor in current.neighbors:
      compute neighbor's g, h, f value

      if neighbor in minHeap:
         if neighbor.g < neighbor.g in minHeap:
             update minHeap
      else:
         insert neighbor into minHeap

Golang

힙 자료 구조를 사용하여 시작 노드까지 거리가 가장 짧은 노드를 선택하면 닫힌 목록이 중복됩니다. 확장 노드에 도달하기 위한 최단 거리를 이미 찾았기 때문에 최소 힙에 다시 추가할 필요는 없습니다. (노드를 향한 더 짧은 경로를 찾으면 최소 힙에 추가합니다).

따라서 코드에서 닫힌 목록을 제거할 수 있습니다. (코드에서 닫힌 목록과 관련된 코드는 주석 처리했습니다).

  • 메인 코드

  • 최소 힙

Python

  • 메인 코드

  • 최소 힙


전체 코드는 여기에서 보실 수 있습니다.

아래에서 다른 최단 경로 알고리즘들도 확인하실 수 있습니다.

More from this blog

나의 오픈 소스 시작 이야기

원문: TkDoDo, “My Open Source Origin Story“ 가끔씩 제가 받는 질문이 하나 있는데, 바로 오픈 소스와 리액트 쿼리(React Query)를 어떻게 시작하게 되었는지입니다. 저의 기본 원칙은 어떤 질문을 세 번 받으면 더 이상 답변할 필요가 없도록 질문에 대해 글로 쓴다는 것입니다. 하지만 이 질문은 주로 직접 만났을 때 받는 질문이라 글로 작성할 생각을 한 적이 없었습니다. 최근에 오프라인 컨퍼런스에 더 많이 참...

Jul 30, 2025
나의 오픈 소스 시작 이야기

이더넷이란?

원문: baeldung, “What Is Ethernet?“ 1. 소개 이 튜토리얼에서는 이더넷(Ethernet)과 이를 통해 이루어지는 데이터 전송에 대해 알아보겠습니다. 2. 이더넷이란? 이더넷은 근거리 통신망(LAN) 또는 광역 네트워크(WAN) 내에서 장치들이 데이터를 주고받고 통신하기 쉽게 만들어 주는 널리 사용되는 기술입니다. 컴퓨터, 프린터, 서버는 물론 스마트 홈 기기까지도 이더넷으로 연결됩니다. 가정이나 사무실처럼 제한된 공간...

Jul 20, 2025
이더넷이란?

포스트 개발자 시대

원문: Josh W. Comeau, "The Post-Developer Era" 2년 전 2023년 3월, "프런트엔드 개발의 종말"이라는 제목의 블로그 글을 발행했습니다. 이는 OpenAI가 GPT-4 쇼케이스를 발표한 직후였고, 당시 업계 분위기는 머지않아 인간 소프트웨어 개발자는 필요 없어지고 앞으로는 소프트웨어 개발을 AI가 전담하게 될 것이라는 전망이 지배적이었습니다. 저는 이런 주장에 회의적이었고 그 블로그 글에서 소프트웨어 개발...

Jul 10, 2025
포스트 개발자 시대

널리 사용되는 네트워크 프로토콜

원문: Subham Datta, "Popular Network Protocols" 1. 개요 이 튜토리얼에서는 가장 널리 사용되고 인기 있는 네트워크 프로토콜들을 소개합니다. 2. 네트워크 프로토콜 소개 의사소통과 정보 교환은 현대 사회에서 가장 중요하고 강력한 역량입니다. 컴퓨터 네트워킹이란 여러 대의 컴퓨터와 장치를 케이블이나 위성을 통해 서로 연결하여, 거리와 상관없이 정보·자원·데이터베이스 등을 공유할 수 있게 하는 것을 말합니다. 네...

Jun 20, 2025
널리 사용되는 네트워크 프로토콜

커맨드 라인에 편해지는 법

원문: Julia Evans, "What helps people get comfortable on the command line?" 가끔 커맨드 라인을 써야 하는 친구들과 이야기하다 보면 많은 이들이 여전히 터미널을 두려워하고 있다는 걸 느낍니다. 그럴 때마다 어떤 조언을 할지 잘 모르겠더라고요. 저는 워낙 오래전부터 터미널을 써왔기 때문이죠. 그래서 Mastodon에 이렇게 물어봤습니다. 최근 1~3년 사이에 터미널 공포(?)를 극복한 분...

Jun 10, 2025
커맨드 라인에 편해지는 법
C

CodeSnap

84 posts

한국어로 전달하는 웹 개발 번역 매거진