알고리즘이란 무엇인가

알고리즘의 정의와 좋은 알고리즘이 갖춰야 할 5가지 필수 조건을 예제 코드와 함께 알아봅니다.

· 7 min read · PALDYN Team

컴퓨터 과학을 공부하다 보면 “알고리즘”이라는 단어를 수도 없이 마주치게 됩니다. 그런데 막상 “알고리즘이 정확히 무엇인가요?”라는 질문을 받으면 명쾌하게 답하기 어려울 수 있습니다. 이번 시리즈의 첫 글에서는 알고리즘의 정확한 정의와 좋은 알고리즘이 반드시 갖춰야 할 조건들을 살펴보겠습니다.

알고리즘의 정의

**알고리즘(Algorithm)**이란 주어진 문제를 해결하기 위한 유한한 단계의 명확한 절차입니다. 이름의 어원은 9세기 페르시아 수학자 알-콰리즈미(Al-Khwarizmi)의 라틴어 이름 ‘Algoritmi’에서 유래했습니다.

핵심은 입력을 받아서, 명확히 정의된 절차를 수행하고, 결과를 출력한다는 흐름에 있습니다.

알고리즘 개념 다이어그램

알고리즘을 요리 레시피에 비유하면 이해하기 쉽습니다. “파스타를 맛있게 끓여라”는 알고리즘이 아닙니다. 하지만 “물 500mL를 끓이고 → 면을 넣고 8분 삶고 → 소스를 넣고 2분 볶는다”는 알고리즘입니다. 각 단계가 누가 봐도 동일하게 수행할 수 있을 만큼 명확하기 때문입니다.

좋은 알고리즘의 5가지 조건

컴퓨터 과학에서는 알고리즘이 반드시 갖춰야 할 다섯 가지 조건을 정의합니다.

좋은 알고리즘의 5가지 조건

① 입력 (Input)

알고리즘은 0개 이상의 입력을 받을 수 있습니다. 입력이 없어도 되지만(예: 랜덤 숫자 생성), 입력이 있다면 그 형식과 범위가 명확해야 합니다.

② 출력 (Output)

반드시 1개 이상의 결과를 출력해야 합니다. 아무 결과도 내지 않는 절차는 알고리즘이라 할 수 없습니다.

③ 명확성 (Definiteness)

각 단계는 모호함이 없어야 합니다. “적당히 섞어라”처럼 해석이 여러 개인 지시는 알고리즘에서 허용되지 않습니다. “배열의 i번째 원소와 i+1번째 원소를 비교해 arr[i] > arr[i+1]이면 교환한다”처럼 누가 읽어도 동일하게 수행해야 합니다.

④ 유한성 (Finiteness)

알고리즘은 반드시 종료해야 합니다. 유한한 단계를 거쳐 결과를 내지 않는 무한 루프는 알고리즘이 아닙니다. (운영체제처럼 의도적으로 무한히 실행되는 것은 알고리즘이 아니라 프로세스라 부릅니다.)

⑤ 효과성 (Effectiveness)

각 연산은 사람이(또는 컴퓨터가) 실제로 수행할 수 있는 기본 단위여야 합니다. “π번째 소수를 즉시 반환”처럼 계산 불가능한 연산은 효과적이지 않습니다.

알고리즘과 프로그램의 차이

알고리즘은 **아이디어(절차의 명세)**이고, 프로그램은 알고리즘의 구체적인 구현입니다. 같은 알고리즘을 Python으로도, Java로도, C로도 구현할 수 있습니다.

# 알고리즘: 배열에서 최댓값 찾기
# 입력: 정수 배열 arr (비어 있지 않음)
# 출력: 배열에서 가장 큰 정수

def find_max(arr):
    max_val = arr[0]        # Step 1: 첫 원소를 최댓값으로 초기화
    for num in arr[1:]:     # Step 2: 나머지 원소를 순회
        if num > max_val:   # Step 3: 더 크면 갱신
            max_val = num
    return max_val          # Step 4: 결과 반환

print(find_max([3, 1, 4, 1, 5, 9, 2, 6]))  # 9

위 코드는 5가지 조건을 모두 만족합니다. 입력이 있고(배열), 출력이 있고(최댓값), 각 단계가 명확하고, 배열 길이 n번 만에 반드시 종료되고, 각 연산(비교, 대입)이 기본 연산입니다.

왜 알고리즘을 공부해야 하는가

좋은 알고리즘과 나쁜 알고리즘의 차이는 단순히 코드 스타일 문제가 아닙니다. 입력 크기 n이 1,000만이 될 때 O(n²) 알고리즘은 1조 번의 연산을 필요로 하지만, O(n log n) 알고리즘은 약 2,300만 번만으로 끝납니다. 현실적인 실행 시간의 차이가 수백만 배에 달할 수 있습니다.

import time

def naive_search(arr, target):        # O(n)
    for x in arr:
        if x == target:
            return True
    return False

def sorted_binary_search(arr, target): # O(log n)
    lo, hi = 0, len(arr) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if arr[mid] == target:
            return True
        elif arr[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return False

n=10,000,000일 때 선형 탐색은 최악 1,000만 번 비교가 필요하지만, 이진 탐색은 최악 24번 비교로 끝납니다.

정리

  • 알고리즘 = 문제를 해결하는 유한하고 명확한 절차
  • 5조건: 입력, 출력, 명확성, 유한성, 효과성
  • 프로그램은 알고리즘의 구현체 — 같은 알고리즘을 여러 언어로 구현 가능
  • 알고리즘의 효율 차이는 현실에서 수백만 배 성능 격차를 만든다

다음 글: 알고리즘 분석 입문


읽어주셔서 감사합니다. 😊