두 텍스트의 차이를 비교하는 방법? Diff 알고리즘 원리와 텍스트 비교 도구 완벽 가이드

문서를 저장하거나 코드를 커밋하거나 계약서를 검토에 보낼 때마다 하나의 질문이 생깁니다. "이 버전과 이전 버전, 도대체 뭐가 달라진 거야?" 텍스트 비교(diff)는 이 질문에 답하는 기술의 핵심입니다. Unix의 diff 명령어부터 Git 커밋 이력, 온라인 협업 도구의 변경 추적 모드까지, 배경에는 모두 같은 로직이 있습니다. 이 글에서는 알고리즘 원리부터 시작해 텍스트 비교의 작동 방식을 폭넓게 설명합니다.

1. Diff란 무엇인가?

Diff(difference의 줄임말)는 두 텍스트 사이의 최소 변경 집합을 계산하는 기술입니다. "구 버전"(A)과 "신 버전"(B)가 주어지면, diff 알고리즘은 다음을 찾아냅니다:

  • B에서 새로 추가된 줄(또는 문자)
  • B에서 삭제된 줄(또는 문자)
  • 변경되지 않은 줄(또는 문자)

이 변경 집합이 작을수록 좋습니다——이것이 "최소 편집 거리(Minimum Edit Distance)" 문제의 핵심이며, 대부분의 diff 알고리즘의 최적화 목표이기도 합니다.

용어 설명
"Diff"는 기술 자체와 그 출력 결과(차이점 보고서) 모두를 의미합니다. 동사로: "이 두 파일을 diff해 보자", 명사로: "이 diff에는 세 곳의 변경이 있다".

2. 핵심 알고리즘: LCS와 Myers Diff

2.1 최장 공통 부분 수열 (LCS)

대부분의 diff 알고리즘의 이론적 기반은 최장 공통 부분 수열(Longest Common Subsequence, LCS)입니다. LCS는 두 수열 모두에 나타나면서 상대적인 순서를 유지하는 가장 긴 부분 수열입니다.

예시:

  • 수열 A: 고양이, 개, 물고기, 새
  • 수열 B: 고양이, 물고기, 토끼, 새
  • LCS: 고양이, 물고기, 새 (길이 3)

LCS를 찾은 후, LCS에 없는 A의 요소는 "삭제", LCS에 없는 B의 요소는 "추가"가 됩니다. LCS 알고리즘의 시간 복잡도는 O(mn)으로, m과 n은 각각 두 텍스트의 길이입니다.

2.2 Myers Diff 알고리즘

1986년 Eugene Myers는 순수 LCS보다 더 효율적인 diff 알고리즘인 Myers diff를 발표했습니다. 주요 특징:

  • 최적의 경우 시간 복잡도 O(n + d²) (d는 차이 수)
  • 차이가 적을 때(실제로 가장 흔한 경우) O(mn)보다 훨씬 빠름
  • "원래 구조를 최대한 유지"하려는 경향이 있어 가독성 높은 diff 생성

Myers diff는 현재 Git, GNU diff 등 주류 도구의 기본 알고리즘입니다.

2.3 Patience Diff

Patience diff는 Bram Cohen(BitTorrent 제작자)이 설계한 알고리즘으로, Git에서 --diff-algorithm=patience로 사용할 수 있습니다. 핵심 아이디어:

  1. 두 버전 모두에서 "정확히 한 번만" 나타나는 줄을 앵커로 설정
  2. 앵커를 기반으로 파일을 구간으로 분할
  3. 각 구간에 LCS를 재귀적으로 적용

실제 효과: 대규모 코드 리팩토링(함수 이동이 많은 경우)에서 Myers diff보다 훨씬 직관적이고 읽기 쉬운 출력을 생성합니다.

알고리즘시간 복잡도적합한 상황기본 채택
LCS (동적 프로그래밍)O(mn)이론적 기초, 소규모 파일
Myers diffO(n + d²)일반 코드 비교Git, GNU diff
Patience diffO(n log n)코드 리팩토링, 함수 이동Bazaar (선택)
Histogram diffO(n log n)Myers의 개선판Git (선택)

3. Unified Diff 형식

어떤 알고리즘을 사용하든, 차이 결과는 일반적으로 "Unified diff" 형식으로 출력됩니다——업계 표준이자 git diff의 기본 형식입니다.

일반적인 Unified diff 출력 예시:

--- a/hello.txt
+++ b/hello.txt
@@ -1,5 +1,5 @@
 1행은 변경 없음
-구 2행
+신 2행
 3행은 변경 없음
-삭제된 4행
 5행은 변경 없음
+추가된 6행

형식 설명:

  • ---: 구 버전(a)
  • +++: 신 버전(b)
  • @@: 헝크 헤더. -1,5는 구 버전의 1행부터 5행, +1,5는 신 버전의 1행부터 5행
  • 공백으로 시작하는 줄: 변경되지 않은 컨텍스트 줄 (기본 3줄 표시)
  • -로 시작하는 줄: 삭제된 줄
  • +로 시작하는 줄: 추가된 줄

4. 문자 단위 vs 줄 단위 비교

표준 diff는 "줄" 단위로 비교하지만, 더 세밀한 비교 모드를 제공하는 도구도 있습니다:

모드비교 단위적합한 상황
줄 단위 diff전체 줄코드, 설정 파일, 일반 문서
단어 단위 diff (word diff)단어자연어 텍스트, Markdown
문자 단위 diff (char diff)단일 문자세밀한 오타 수정, 법률 계약서

Git은 git diff --word-diff로 단어 단위 비교로 전환할 수 있습니다. 온라인 텍스트 비교 도구는 보통 줄 수준과 문자 수준의 차이를 동시에 표시하여 변경 내용을 한눈에 파악할 수 있게 합니다.

5. 실제 활용 사례

5.1 버전 관리 (Git)

Git의 모든 커밋에는 diff가 내장되어 있습니다. git diff, git show, git log -p는 변경 내용을 확인하는 일반적인 명령어입니다. GitHub, GitLab의 풀 리퀘스트 검토 인터페이스는 본질적으로 diff를 시각화한 것입니다.

5.2 문서 교정 (변경 추적)

Microsoft Word의 "변경 내용 추적"과 Google Docs의 "제안 모드"는 모두 diff 개념을 기반으로 합니다——누가 언제 어떤 내용을 변경했는지 기록하여 검토자가 각 변경을 개별적으로 수락하거나 거부할 수 있게 합니다.

5.3 계약서 및 법률 문서

계약서 수정 시 변호사는 모든 단어의 변경을 확인해야 합니다. 문자 단위 비교 모드를 사용하면 "originally"가 "previously"로 바뀐 것 같은 미묘한 표현 변화도 명확하게 표시되어 중요한 변경을 놓치지 않습니다.

5.4 설정 파일과 IaC

Terraform, Ansible 같은 IaC 도구는 적용 전에 "plan diff"를 표시하여 어떤 클라우드 리소스가 생성, 수정, 삭제될지 엔지니어가 확인할 수 있게 합니다.

5.5 데이터 비교

시점이 다른 CSV, JSON 데이터셋을 diff로 비교하면 어떤 필드가 변경되었고 어떤 레코드가 추가 또는 삭제되었는지 빠르게 찾을 수 있습니다. 데이터 감사와 문제 해결에 적합합니다.

6. 온라인 텍스트 비교 도구 사용법

온라인 텍스트 비교 도구(이 사이트의 도구 등)는 설치가 필요 없고 두 텍스트를 빠르게 비교하는 데 적합합니다:

  1. 텍스트 붙여넣기: 구 버전을 왼쪽 패널에, 신 버전을 오른쪽 패널에 붙여넣습니다
  2. 비교 모드 선택: 줄 단위 또는 문자 단위 (도구에 따라 다름)
  3. 결과 확인: 삭제된 내용은 빨간색, 추가된 내용은 초록색으로 표시, 변경되지 않은 부분은 원색 유지
  4. 차이 탐색: "이전" "다음" 버튼으로 각 차이 위치로 빠르게 이동

온라인 도구는 명령줄 환경에 익숙하지 않은 비기술 사용자의 문서 비교에 특히 유용하며, 직관적으로 조작할 수 있습니다.

7. 자주 묻는 질문

7.1 diff로 이미지나 PDF를 비교할 수 있나요?

표준 diff는 순수 텍스트 도구이며 이미지나 PDF 같은 바이너리 파일을 직접 비교할 수 없습니다. PDF는 텍스트 내용을 비교하려면 먼저 텍스트로 변환해야 합니다. 이미지 비교는 픽셀 차이를 비교하는 전용 이미지 diff 도구가 필요하며, 텍스트 diff와는 근본적으로 다른 개념입니다.

7.2 diff 결과가 예상과 다를 때는 왜 그럴까요?

가장 흔한 원인:

  • 공백 문자 차이: 들여쓰기 방식(탭 vs 스페이스)이나 줄 끝 문자(Windows CRLF vs Unix LF)가 달라 많은 가짜 차이가 발생합니다. -w(모든 공백 무시) 또는 -b(줄 끝 공백 무시) 옵션으로 필터링할 수 있습니다.
  • 인코딩 차이: 두 파일이 다른 문자 인코딩(UTF-8 vs EUC-KR 등)을 사용하는 경우 먼저 통일 후 비교하세요.
  • 알고리즘 선택: 알고리즘마다 같은 차이를 다르게 "분할"합니다. 알고리즘을 바꾸면 더 직관적인 결과를 얻을 수 있습니다.

7.3 diff와 merge는 어떤 관계인가요?

Merge는 diff의 확장 응용입니다: 두 사람이 같은 원본 파일을 각각 수정했을 때, merge 도구는 각각 diff를 수행한 후 두 변경 집합을 합치려 시도합니다. 두 변경이 같은 줄에 영향을 미치면 "병합 충돌(merge conflict)"이 발생하고 수동 해결이 필요합니다.

8. 정리

텍스트 비교 기술은 단순해 보이지만 배경에는 고전적인 알고리즘 문제가 있습니다. LCS에서 Myers diff까지, 줄 단위에서 문자 단위까지, 다양한 비교 전략은 각기 다른 상황에 적합합니다. 이 원리를 이해하면 Git 같은 버전 관리 도구를 더 효과적으로 사용할 수 있고, 문서 협업·계약 검토·일상적인 편집 작업에서도 모든 변경을 더 정확하게 추적할 수 있습니다.