T도구모음

텍스트 비교 (Diff)

두 텍스트를 비교하여 차이점을 시각적으로 표시합니다.

텍스트 차이 비교(Diff) — Myers 알고리즘부터 Git diff까지

코드 리뷰, 설정 파일 감사, 계약서 수정 추적 — 두 텍스트를 "정확히 어디가 달라졌는지" 보여주는 Diff는 개발자가 매일 수십 번 의존하는 핵심 도구입니다. Unix의 diff 명령어(1974, Hunt-McIlroy 알고리즘)에서 시작해, 현재 Git은 Eugene Myers의 O(ND) 차분 알고리즘(1986, "An O(ND) Difference Algorithm and Its Variations")을 기본 엔진으로 사용합니다. 이 도구는 LCS(Longest Common Subsequence) 기반의 동적 프로그래밍으로 두 텍스트의 최소 편집 거리를 계산하고, 추가(+) / 삭제(-) / 동일 줄을 시각적으로 구분해 보여줍니다. 모든 연산은 브라우저에서 로컬 실행되므로 민감한 코드나 계약서도 서버 전송 없이 안전하게 비교할 수 있습니다.

알고리즘 원리 — LCS와 Myers Diff

LCS(최장 공통 부분 수열)는 두 시퀀스에서 순서를 유지하면서 공통으로 나타나는 가장 긴 부분 수열을 찾는 문제입니다. Diff의 본질은 "LCS에 포함되지 않는 줄 = 변경된 줄"이라는 등식입니다. 기본 DP 접근은 O(MN) 시간/공간이지만, Myers 알고리즘은 편집 거리 D에 비례하는 O(ND) 시간으로 동작해 실제 차이가 적은 경우(코드 리뷰의 대부분) 극적으로 빠릅니다. Git은 여기에 patience diff(고유한 공통 줄을 앵커로 사용)와histogram diff(빈도 기반 앵커 선택)를 추가 전략으로 제공합니다.

알고리즘시간 복잡도특징사용처
Hunt-McIlroyO(MN)최초 Unix diff레거시 시스템
Myers (기본)O(ND)최소 편집 보장Git 기본값
PatienceO(N log N + ND)고유 줄 앵커링git diff --patience
HistogramO(ND) 평균빈도 기반git diff --histogram
LCS DPO(MN)이해 쉬움교육 / 이 도구

Diff 출력 형식 — Unified, Side-by-Side, Context

# Unified diff 형식 (git diff 기본)
--- a/config.json
+++ b/config.json
@@ -3,7 +3,7 @@
   "port": 3000,
-  "debug": true,
+  "debug": false,
   "logLevel": "info"

# Context diff (diff -c)
*** config.json.orig
--- config.json
***************
*** 3,5 ****
   "port": 3000,
!  "debug": true,
--- 3,5 ----
   "port": 3000,
!  "debug": false,

실무 활용 시나리오 5가지

  • PR 코드 리뷰 — GitHub/GitLab의 "Files changed" 탭이 바로 unified diff. 줄 단위 코멘트를 달 때 diff hunk 단위로 맥락을 파악합니다.
  • 서버 설정 감사 — nginx.conf, docker-compose.yml 변경 전후를 붙여넣어 의도하지 않은 포트 변경이나 환경변수 누락을 즉시 발견.
  • 계약서/약관 수정 추적 — 법무팀이 보낸 수정본과 원본을 비교해 "면책 조항 추가" 같은 실질 변경을 빠르게 식별.
  • DB 마이그레이션 스크립트 — ALTER TABLE 전후 스키마 덤프를 diff로 비교해 예상 변경과 실제 변경이 일치하는지 검증.
  • 번역 QA — 원문과 번역문의 줄 수/구조를 비교해 누락된 문단이 없는지 확인.

디버깅 경험 — "diff가 왜 이렇게 이상하게 나와요?"

Windows에서 작성한 파일과 Mac/Linux에서 작성한 파일을 비교할 때 "모든 줄이 다르다"고 나오는 경우를 겪어보셨을 겁니다. 원인은 줄바꿈 문자: Windows는 CRLF(\r\n), Unix는 LF(\n)를 사용하기 때문입니다. Git에서는 core.autocrlf 설정으로 자동 변환하지만, 이 도구에 직접 붙여넣을 때는 양쪽 텍스트의 줄바꿈을 통일하는 전처리가 필요합니다. 또 다른 함정은 trailing whitespace — 눈에는 안 보이지만 diff에서는 "변경"으로 잡힙니다. 프로덕션에서는 .editorconfig에 trim_trailing_whitespace = true를 설정하고, 비교 전에 Prettier나 sed 's/[[:space:]]*$//'로 정리하는 습관을 들이면 노이즈가 확 줄어듭니다.

대용량 Diff 성능 — 주의할 점

LCS DP의 공간 복잡도는 O(MN)이므로, 1만 줄 x 1만 줄 비교 시 약 400MB 메모리를 소비할 수 있습니다. Git이 Myers 알고리즘을 쓰는 이유가 바로 이것 — 실제 편집 거리가 작으면 선형에 가깝게 동작합니다. 브라우저 환경에서는 Web Worker로 diff 연산을 분리하면 UI 블로킹을 피할 수 있고, 정말 큰 파일은 chunk 단위 분할 비교 전략(파일을 함수/블록 단위로 잘라서 각각 diff)을 고려해야 합니다. Node.js 서버사이드에서는 diff npm 패키지(jsdiff)가 Myers 구현을 제공합니다.

보안 고려사항

  • Diff 결과에 시크릿(API 키, 비밀번호)이 노출될 수 있으므로 공유 시 반드시 마스킹 처리.
  • Git diff를 외부에 공유할 때는 git diff --stat으로 파일 목록만 먼저 확인.
  • CI/CD 파이프라인에서 diff 결과를 로그에 남길 때 .env 파일이 포함되지 않도록 .gitattributes에 diff=nodiff 설정.

관련 도구

Diff 결과에서 발견한 해시값 변경을 검증할 때는 해시 생성기로 직접 다이제스트를 확인하고, 변경된 정규식 패턴이 정상 작동하는지는 정규식 테스터에서 즉시 테스트할 수 있습니다. 색상 코드 변경이 포함된 CSS diff라면 색상 변환기로 HEX/RGB/HSL을 교차 확인하세요.

참고 자료

  • Eugene W. Myers — "An O(ND) Difference Algorithm and Its Variations" (Algorithmica, 1986)
  • Git Documentation — git-diff, diff algorithms (myers, patience, histogram)
  • RFC 5261 — XML Patch Operations (구조화 diff 표준)
  • MDN Web Docs — Web Workers API (대용량 diff 병렬 처리)
  • npm jsdiff — JavaScript diff 구현 라이브러리

자주 묻는 질문

관련 도구