본문 바로가기

정렬 알고리즘 비교: 버블 정렬부터 퀵 정렬까지, 실제 사용 사례 중심

📑 목차

    같은 정렬인데 왜 어떤 코드는 훨씬 빠를까

    엑셀에서 “정렬” 버튼을 누르거나, 쇼핑몰에서 “가격 낮은 순”을 선택하면 화면의 목록이 순서대로 정리된다. 겉으로 보기에는 단순히 “정렬 알고리즘이 한 번 돈 것”처럼 느껴지지만, 그 안에서는 서로 다른 방식의 정렬 알고리즘이 동작하고 있다.

    같은 데이터를 정렬하더라도

    • 어떤 코드는 몇 초 만에 끝나고,
    • 어떤 코드는 수십 초 이상 걸리기도 한다.

    이 차이를 이해하려면 정렬 알고리즘, 버블 정렬, 퀵 정렬, 시간 복잡도, 실제 사용 사례라는 키워드를 중심으로 살펴볼 필요가 있다.

    이 글에서는 전산학 비전공자도 이해할 수 있도록

    • 정렬 알고리즘이 무엇인지,
    • 버블 정렬과 퀵 정렬이 어떤 원리로 동작하는지,
    • 이론적인 시간 복잡도 차이가 실제 서비스 속도에 어떤 영향을 주는지,
    • 실무에서 어떤 상황에 어떤 정렬 알고리즘이 주로 쓰이는지
      를 전산학 입문서처럼 차근차근 설명한다.

    정렬 알고리즘의 기본 개념과 대표 종류 정리

    1. 정렬 알고리즘이란 무엇인가

    정렬 알고리즘(Sorting Algorithm)은 말 그대로 데이터의 순서를 일정한 기준에 따라 재배열하는 절차이다. 예를 들어,

    • 숫자를 작은 값부터 큰 값 순으로 정렬하거나,
    • 문자열을 가나다순, 알파벳순으로 정렬하거나,
    • 날짜를 오래된 순 혹은 최신 순으로 정렬하는 작업이 모두 정렬 알고리즘의 대상이다.

    정렬은 단순히 보기 좋게 만드는 데 그치지 않는다.

    1. 검색 효율 향상
      • 정렬된 상태에서는 이진 탐색과 같은 빠른 검색 알고리즘을 사용할 수 있다.
    2. 중복 제거와 그룹화
      • 같은 값을 옆에 모으기 쉽기 때문에, 중복 데이터를 제거하거나 통계를 내기 편하다.
    3. 정렬 전제 조건을 사용하는 다른 알고리즘의 기반
      • 많은 알고리즘이 “입력이 정렬되어 있다”는 전제를 사용한다.

    그래서 대부분의 프로그래밍 언어와 데이터베이스에는 정렬 알고리즘이 핵심 기능으로 내장된다.

    2. 버블 정렬(Bubble Sort) – 가장 단순하지만 비효율적인 방법

    버블 정렬(Bubble Sort)은 전산학 입문에서 가장 먼저 소개되는 정렬 알고리즘 중 하나이다. 원리는 간단하다.

    1. 리스트의 앞에서부터 이웃한 두 값을 비교한다.
    2. 순서가 잘못되어 있다면 두 값을 서로 교환한다.
    3. 리스트 끝까지 반복하면, 가장 큰 값이 맨 끝으로 “밀려 올라간다”.
    4. 다시 처음부터 반복하되, 이미 정렬된 끝 부분은 제외한다.
    5. 더 이상 교환이 필요 없을 때까지 반복한다.

    물 위로 거품이 조금씩 떠오르는 모습과 비슷하다고 해서 버블 정렬이라고 부른다.

    버블 정렬의 특징은 다음과 같다.

    • 구현이 매우 단순하다.
      • 이중 반복문으로 쉽게 구현할 수 있다.
    • 시간 복잡도는 O(n²)이다.
      • 데이터 개수가 n개라면, 최악의 경우 n²에 비례하는 비교와 교환이 필요하다.
    • 데이터가 조금만 많아져도 속도가 매우 느려진다.
      • n이 10배가 되면, 대략 100배 정도 시간이 늘어나는 셈이다.

    이론적으로는 비효율적이지만,

    • 학습용 예제로 적합하고,
    • 데이터 개수가 매우 적을 때는 허용 가능한 경우도 있다.

    3. 선택 정렬, 삽입 정렬 – O(n²) 계열의 다른 단순 정렬들

    버블 정렬 외에도 전산학 기초에서 자주 등장하는 정렬 알고리즘이 있다.

    1. 선택 정렬(Selection Sort)
      • 남아 있는 데이터 중에서 가장 작은 값을 찾아 맨 앞과 교환하는 방식을 반복한다.
      • 매 단계마다 “최소값을 선택한다”는 의미에서 선택 정렬이라고 부른다.
      • 비교 횟수는 항상 비슷하기 때문에, 시간 복잡도는 O(n²)이다.
    2. 삽입 정렬(Insertion Sort)
      • 앞부분은 이미 정렬된 구간이라고 가정하고,
      • 새로 들어온 값을 정렬된 구간의 알맞은 위치에 “삽입”하는 방식을 반복한다.
      • 카드 놀이에서 손에 든 카드를 정렬하면서 끼워 넣는 방식과 비슷하다.
      • 평균적으로 O(n²)이지만,
        • 이미 거의 정렬된 데이터라면 실제 성능이 꽤 좋다.

    이 알고리즘들은 모두 시간 복잡도 O(n²)이기 때문에,

    • 데이터 개수가 수십 개, 많아야 수백 개 정도일 때만 실용적이다.
    • 수만 개, 수십만 개 데이터에는 적합하지 않다.

    정렬 알고리즘 비교: 버블 정렬부터 퀵 정렬까지, 실제 사용 사례 중심
    버블 정렬·선택 정렬·삽입 정렬의 개념과 흐름 비교 다이어그램

    4. 퀵 정렬(Quick Sort) – 실무에서 많이 쓰이는 빠른 정렬

    퀵 정렬(Quick Sort)은 이름처럼 평균적으로 매우 빠른 정렬 알고리즘이다. 많은 언어의 정렬 함수 구현에 영향을 준 알고리즘이다.

    퀵 정렬의 기본 아이디어는 다음과 같다.

    1. 데이터 중 하나를 피벗(Pivot)으로 선택한다.
    2. 피벗보다 작은 값들은 왼쪽 그룹으로, 큰 값들은 오른쪽 그룹으로 나눈다.
    3. 왼쪽 그룹과 오른쪽 그룹에 대해 같은 작업을 재귀적으로 반복한다.
    4. 왼쪽 그룹 + 피벗 + 오른쪽 그룹을 이어 붙이면 정렬된 결과가 된다.

    퀵 정렬의 특징은 다음과 같다.

    • 평균 시간 복잡도는 O(n log n)이다.
      • n이 커질수록 버블 정렬(O(n²))보다 훨씬 빠르게 동작한다.
    • 피벗 선택을 잘못하면 최악의 경우 O(n²)까지 떨어질 수 있다.
      • 이를 방지하기 위해 랜덤 피벗 선택, 세 값 중 중앙값 선택 등 다양한 개선 기법을 사용한다.
    • 구현이 비교적 간단하면서도 평균적인 성능이 뛰어나,
      • 실무에서 널리 사용되는 정렬 알고리즘이다.

    5. 병합 정렬(Merge Sort) – 안정성과 일관된 성능이 강점인 정렬

    병합 정렬(Merge Sort)은 “나누고 합치는” 방식을 사용하는 정렬 알고리즘이다.

    1. 데이터를 반으로 나눈다.
    2. 각 부분 리스트에 대해 정렬을 재귀적으로 수행한다.
    3. 두 개의 정렬된 리스트를 하나로 “병합”한다.

    병합 정렬의 특징은 다음과 같다.

    • 시간 복잡도는 항상 O(n log n)이다.
      • 최선, 평균, 최악의 경우가 모두 동일한 상한을 가진다.
    • 안정 정렬(Stable Sort)을 구현하기 쉽다.
      • 값이 같은 원소들의 기존 순서를 유지할 수 있다.
    • 병합 과정에서 추가 메모리가 필요하다.

    실제 언어의 기본 정렬 구현에서는

    • 퀵 정렬과 병합 정렬의 아이디어를 적절히 조합한 하이브리드 정렬을 사용하는 경우가 많다.

    시간 복잡도와 실제 사용 사례로 보는 정렬 알고리즘 선택 기준

    1. O(n²) vs O(n log n): 데이터가 많을수록 성능 차이가 폭발적으로 커진다

    정렬 알고리즘을 비교할 때 가장 중요한 기준 중 하나가 시간 복잡도이다. 앞서 언급한 대표적인 정렬 알고리즘의 시간 복잡도를 정리해 보면 다음과 같다.

    • 버블 정렬: O(n²)
    • 선택 정렬: O(n²)
    • 삽입 정렬: O(n²)
    • 퀵 정렬: 평균 O(n log n), 최악 O(n²)
    • 병합 정렬: 항상 O(n log n)

    n이 작을 때는 O(n²)과 O(n log n)의 차이가 크게 느껴지지 않을 수 있다.
    그러나 n이 커질수록 차이가 눈에 띄게 벌어진다.

    예를 들어 정렬할 데이터 개수가 n = 10,000일 때,

    • O(n²) 알고리즘:
      • 대략 10,000² = 100,000,000(1억) 단위의 연산 필요
    • O(n log n) 알고리즘:
      • 대략 10,000 × log₂10,000 ≈ 10,000 × 14 = 140,000 정도의 연산 필요

    이 숫자는 실제 시간과 1:1로 대응되지는 않지만,

    • 성장 속도의 차이가 얼마나 큰지를 직관적으로 보여 준다.

    입력 데이터 개수가 증가할수록 O(n²) 정렬 알고리즘과 O(n log n) 정렬 알고리즘의 연산량 차이가 크게 벌어지는 모습을 보여 주는 선 그래프
    데이터 개수에 따른 O(n²)와 O(n log n) 정렬 알고리즘 성능 비교 그래프

    2. 실제 서비스에서 정렬 알고리즘이 쓰이는 대표적인 예

    실제 서비스에서 정렬 알고리즘은 눈에 보이지 않는 여러 곳에서 사용된다. 몇 가지 예를 통해 정렬 알고리즘이 어떤 방식으로 쓰이는지 살펴본다.

    1. 쇼핑몰 상품 목록 정렬
      • 가격, 인기, 리뷰 수, 최신 등록 순 등 여러 기준으로 상품을 정렬한다.
      • 보통 데이터베이스의 ORDER BY 기능이나, 애플리케이션 코드의 정렬 함수가 O(n log n)급 알고리즘을 사용한다.
    2. 로그 데이터 정렬과 분석
      • 서버 로그나 센서 데이터는 시간 순으로 정렬해야 분석이 쉬워진다.
      • 수백만 건 이상의 로그를 정렬할 때는 O(n²) 알고리즘은 사실상 사용 불가하고,
        병합 정렬이나 퀵 정렬 기반의 알고리즘이 필수적이다.
    3. 검색 결과 정렬
      • 검색 엔진이나 내부 검색 기능은
        • 관련도 점수,
        • 클릭률,
        • 최신성 등을 기준으로 결과를 정렬한다.
      • 이 과정에서도 빠른 정렬 알고리즘이 성능을 좌우한다.
    4. 리더보드와 순위표 생성
      • 게임, 스포츠, 주식 앱 등에서는 점수나 수익률에 따라 순위를 매겨야 한다.
      • 매번 전체 순위를 다시 정렬해야 한다면 정렬 알고리즘의 시간 복잡도가 직접적인 성능 지표가 된다.

    3. 언제 단순 정렬(버블·선택·삽입)을, 언제 퀵/병합 정렬을 쓰는가

    모든 상황에서 퀵 정렬, 병합 정렬만 사용하는 것은 아니다. 현실에서는 다음과 같은 기준으로 정렬 알고리즘을 선택한다.

    1. 데이터 개수가 아주 적을 때
      • 데이터가 10개, 20개 수준이라면 O(n²)와 O(n log n)의 차이가 거의 느껴지지 않는다.
      • 이럴 때는 구현이 단순한 버블 정렬, 삽입 정렬이 오히려 코드를 이해하기 쉽고 유지보수에 유리할 수 있다.
    2. 데이터가 이미 거의 정렬되어 있을 때
      • 삽입 정렬은 데이터가 “거의 정렬된 상태”라면 실제 속도가 매우 빠르다.
      • 실무에서는 큰 데이터에 고급 정렬 알고리즘을 적용한 뒤,
        • 작은 구간에서는 삽입 정렬로 마무리하는 하이브리드 방식이 자주 사용된다.
    3. 안정 정렬이 꼭 필요할 때
      • 값이 같은 원소들의 기존 순서를 유지해야 하는 상황에서는
        • 병합 정렬처럼 안정 정렬을 구현하기 쉬운 알고리즘이 선호된다.
      • 예를 들어, 먼저 “이름순”으로 정렬한 뒤 “나이순”으로 정렬하되,
        같은 나이에서는 기존 이름순이 유지되기를 원하는 경우가 있다.
    4. 메모리 사용량이 중요한 환경일 때
      • 병합 정렬은 추가 메모리가 필요하므로, 메모리가 매우 제한된 환경에서는 부담이 될 수 있다.
      • 이럴 때는 제자리(in-place) 정렬이 가능한 퀵 정렬 계열 알고리즘이 선호된다.
    5. 언어와 라이브러리가 제공하는 기본 정렬 사용
      • 대부분의 경우, 개발자는 직접 정렬 알고리즘을 새로 구현하지 않는다.
      • 언어가 제공하는 sort 함수, 라이브러리 함수를 사용하면 된다.
      • 이 함수들 내부에서 이미
        • 퀵 정렬, 병합 정렬, 힙 정렬, 삽입 정렬 등을 상황에 맞게 섞어 쓰도록 최적화되어 있다.

    4. 정렬 알고리즘을 볼 때 함께 고려해야 할 요소들

    정렬 알고리즘을 비교할 때 시간 복잡도 외에도 다음 요소들을 함께 고려해야 한다.

    1. 공간 복잡도(Space Complexity)
      • 추가 메모리가 얼마나 필요한지 보는 기준이다.
      • 메모리가 매우 중요한 환경에서는 O(1)에 가까운 공간 복잡도를 가진 알고리즘이 유리하다.
    2. 안정성(Stable vs Unstable)
      • 안정 정렬은 같은 값의 순서를 유지하고,
      • 불안정 정렬은 그 순서를 보장하지 않는다.
      • 데이터 처리 로직에 따라 안정성이 중요할 수도 있고, 그렇지 않을 수도 있다.
    3. 구현 난이도와 유지보수
      • 알고리즘이 아무리 빠르더라도 구현이 지나치게 복잡하면 버그가 생기기 쉽다.
      • 팀원의 실력, 코드 리뷰 환경, 프로젝트 규모에 따라 적절한 수준을 선택하는 것이 좋다.
    4. 실제 데이터 특성
      • 랜덤한 데이터인지, 거의 정렬된 데이터인지,
      • 중복 값이 많은지,
      • 데이터 크기가 일정한지 등에 따라 알고리즘의 실제 성능이 달라질 수 있다.

    정렬 알고리즘을 알면 “성능 좋은 코드”의 기준이 보인다

    이 글에서는 정렬 알고리즘 비교를 중심으로,
    버블 정렬부터 퀵 정렬까지 대표 알고리즘의 개념과 실제 사용 사례를 살펴보았다. 주요 내용을 정리하면 다음과 같다.

    1. 정렬 알고리즘은 데이터를 일정한 기준으로 재배열하는 절차이다.
      • 검색 효율, 중복 제거, 통계 분석 등 여러 작업의 기반이 된다.
    2. 버블 정렬, 선택 정렬, 삽입 정렬은 이해와 구현이 쉽지만 시간 복잡도가 O(n²)이다.
      • 데이터가 적을 때나 교육용 예제로는 적합하지만,
      • 대규모 데이터에는 적합하지 않다.
    3. 퀵 정렬과 병합 정렬은 평균적으로 O(n log n)의 시간 복잡도를 가진다.
      • 실제 프로그래밍 언어와 서비스의 기본 정렬 구현에서 널리 사용된다.
    4. O(n²)와 O(n log n)의 차이는 데이터가 많아질수록 극적으로 커진다.
      • 같은 기능이라도 정렬 알고리즘 선택에 따라 성능이 수백 배 이상 차이 날 수 있다.
    5. 실무에서는 데이터 크기, 정렬 안정성, 메모리, 코드 복잡도 등을 모두 고려해 알고리즘을 선택한다.
      • 대부분의 경우 언어가 제공하는 정렬 함수를 사용하는 것이 합리적이다.

    이제 “정렬 알고리즘과 시간 복잡도 때문에 같은 기능인데도 속도 차이가 나는 이유”를

    • 버블 정렬, 퀵 정렬, 병합 정렬의 특성과
    • O(n²), O(n log n) 시간 복잡도의 차이로 설명할 수 있을 것이다.

    다음 단계에서 자연스럽게 이어질 수 있는 학습 주제는 예를 들어 다음과 같다.

    • “자료 구조 기초: 배열, 연결 리스트, 힙 구조가 정렬 알고리즘과 성능에 미치는 영향”
    • “실제 언어별 정렬 구현: 파이썬, 자바, C++ 표준 라이브러리의 정렬 방식 비교”

    이러한 주제들을 함께 살펴보면, 전산학 기초를 바탕으로 실제 코드 성능을 분석하고 개선하는 능력을 더욱 키울 수 있다.