텍스트 비교
두 텍스트의 추가·삭제·변경된 줄을 한눈에 비교
비교 결과
두 텍스트를 입력하고 비교하기를 눌러주세요.
처리 중…
0.0
멈춘 것이 아닙니다. 계산이 끝나면 결과가 표시됩니다.
텍스트 비교 소개
이 도구는 두 텍스트를 줄 단위로 나눈 뒤, 양쪽에 공통으로 남길 수 있는 줄을 최대한 많이 고르는 LCS(최장 공통 부분 수열) 방식으로 비교합니다. 공통으로 고른 줄은 그대로, 왼쪽에만 있는 줄은 삭제(-), 오른쪽에만 있는 줄은 추가(+)로 표시합니다. 줄 안에서 어느 글자가 바뀌었는지는 따로 표시하지 않습니다.
diff 결과가 「내가 고친 것」과 다르게 보일 때가 많습니다. 알고리즘이 찾는 것은 편집 의도가 아니라 「바뀐 줄 수가 가장 적은 설명」이기 때문입니다. 아래에서 그 원리와, 결과를 제대로 읽는 요령을 설명합니다.
diff는 최소 편집을 찾을 뿐, 의도를 모른다
두 문서의 차이를 구하는 문제는 「A를 B로 바꾸는 가장 짧은 삽입·삭제 목록」을 찾는 문제와 같습니다. 1976년 유닉스 diff가 Hunt–McIlroy 알고리즘으로 이를 풀었고, 1986년 Eugene Myers가 논문 「An O(ND) Difference Algorithm and Its Variations」에서 차이가 적을수록 빨리 끝나는 방법을 발표했습니다. N은 두 입력 길이의 합, D는 최소 편집 수입니다. Git의 기본 diff가 이 Myers 알고리즘입니다.
이 도구도 Myers 알고리즘을 씁니다. 두 입력을 반씩 나눠 가며 푸는 선형 공간 판이라 메모리는 줄 수에 비례하고, 두 글이 비슷할수록 빨리 끝납니다. 2만 줄끼리 1%가 바뀐 경우도 1초 안에 비교합니다. 다만 전혀 다른 두 글처럼 차이가 큰 입력은 시간이 차이에 비례해 늘어나서, 수만 줄이면 몇 초 걸릴 수 있습니다. 편집 수는 최소값이지만 최소 해가 여러 개일 때 Git과 다른 해를 고를 수 있고, 바뀐 구간 안에서는 삭제를 먼저 표시합니다.
diff가 「틀려」 보이는 흔한 경우
코드에서 기존 블록 위에 비슷한 블록을 새로 끼워 넣으면, diff는 닫는 괄호 }를 엉뚱한 쪽과 짝지어 새 블록의 끝과 옛 블록의 시작이 섞인 것처럼 보여 줍니다. 틀린 것이 아니라 똑같이 짧은 설명이 여러 개 있고 그중 하나를 고른 것입니다. Git이 --diff-algorithm=patience나 histogram 옵션을 따로 두는 이유가 이것으로, 이 방식들은 한 번만 나오는 줄을 먼저 기준점으로 삼아 사람이 보기에 자연스러운 결과를 내는 경우가 많습니다.
줄 순서만 바꾼 경우도 diff에는 「이동」이라는 개념이 없어서, 한쪽에서 지우고 다른 곳에 추가한 것으로 나옵니다.
줄 하나에서 한 글자만 고쳐도 줄 전체가 삭제 1 + 추가 1로 나옵니다. 문장이 긴 원고라면 문단이 한 줄이라 거의 모든 수정이 이렇게 보입니다. 원고 교정 비교는 한 문장씩 줄을 나눈 뒤 넣으면 훨씬 읽기 쉽습니다.
눈에 안 보이는 차이
화면에서 같아 보이는 두 줄이 다르다고 나오면 보이지 않는 문자를 의심하세요. 줄바꿈 없는 공백(NBSP, U+00A0)은 일반 공백과 다른 문자이고, 웹 페이지나 워드 문서에서 복사하면 자주 섞입니다. 줄 끝 공백도 마찬가지입니다. 「앞뒤 공백 무시」 옵션을 켜면 줄 끝 공백과 NBSP까지 잘라 내고 비교합니다(JavaScript trim은 NBSP도 공백으로 봅니다). 단, 줄 가운데 있는 NBSP는 그대로 남습니다.
줄바꿈 방식 차이(Windows의 CRLF와 macOS·Linux의 LF)는 이 도구가 비교 전에 모두 LF로 통일하므로 차이로 나오지 않습니다. Git에서 파일 전체가 바뀌었다고 나오는데 여기서는 같다고 나온다면 줄바꿈 방식이 원인일 가능성이 큽니다.
- 대소문자 무시: 비교할 때만 소문자로 바꾸고, 표시는 원문 그대로 합니다.
- 빈 줄 무시: 양쪽에서 빈 줄(공백만 있는 줄 포함)을 빼고 비교합니다. 줄 번호는 원래 번호를 유지합니다.
- 마지막 줄 뒤에 줄바꿈이 하나 더 있으면 빈 줄 하나가 추가된 것으로 나옵니다.
예시
블록을 고치고 새 블록을 추가했는데
- 입력
왼쪽: if (a) { x(); } 오른쪽: if (a) { y(); } if (b) { x(); }- 결과
if (a) { + y(); + } + if (b) { x(); } (추가 3, 삭제 0, 동일 3)
사람은 「x를 y로 바꾸고 if (b) 블록을 추가했다」고 생각하지만, 그렇게 설명하면 삭제 1 + 추가 4 = 5줄이 바뀝니다. 알고리즘은 3줄만 추가하는 더 짧은 설명을 고릅니다.
같아 보이는데 다르다고 나올 때
- 입력
왼쪽: a[NBSP]b 오른쪽: a b- 결과
- a b + a b (추가 1, 삭제 1)
가운데 공백이 U+00A0과 U+0020으로 다릅니다. 앞뒤 공백 무시 옵션으로도 줄 가운데 문자는 바뀌지 않습니다.
CRLF와 LF
- 입력
왼쪽: line1\r\nline2 오른쪽: line1\nline2- 결과
line1 line2 (동일 2)
줄바꿈을 통일하고 비교하므로 차이가 없습니다.
사용 방법
- 왼쪽에 원본, 오른쪽에 수정본을 붙여 넣습니다.
- 필요하면 대소문자·앞뒤 공백·빈 줄 무시 옵션을 켭니다.
- 초록(추가)과 빨강(삭제) 줄을 확인하고, 필요하면 결과를 복사합니다.
자주 묻는 질문
한 글자만 고쳤는데 줄 전체가 바뀌었다고 나와요.
줄 단위로 비교하기 때문입니다. 긴 문단은 문장마다 줄을 나눠 넣으면 차이가 좁혀집니다.
Git diff와 결과가 달라요.
바뀐 줄 수는 같아도, 최소 해가 여러 개일 때 고르는 방식이 다릅니다. 또 이 도구는 CRLF와 LF를 같게 봅니다.
복사한 결과를 patch 명령에 쓸 수 있나요?
네. 「unified diff 복사」는 파일 헤더(--- a/text.txt, +++ b/text.txt)와 @@ -시작,줄수 +시작,줄수 @@ 헤더, 앞뒤 3줄 문맥을 넣은 표준 형식이라 원본 파일에 patch -p1이나 git apply로 적용할 수 있습니다. 파일 이름만 실제 이름으로 바꾸세요. 패치가 정확히 적용되도록 대소문자·공백·빈 줄 무시 옵션과 상관없이 글자 그대로 비교해 만듭니다.
아주 긴 파일도 비교되나요?
네. 메모리는 줄 수에 비례하므로 수만 줄도 비교할 수 있습니다. 두 파일이 비슷하면 빠르고, 거의 모든 줄이 다르면 수만 줄에서 몇 초 걸릴 수 있습니다.
출처
- Myers, E. W. (1986). An O(ND) Difference Algorithm and Its Variations. Algorithmica 1
- Git documentation — git diff (--diff-algorithm)
- MDN — String.prototype.trim
기준일: