두 파일을 열어 보면 글자 하나 다르지 않은데, diff 는 모든 줄이 바뀌었다고 하거나 첫 줄·마지막 줄만 다르다고 할 때가 있습니다. 원인은 대개 화면에 보이지 않는 문자입니다. 이 글은 그런 "보이지 않는 차이"의 종류와 해결 방법을 정리합니다.
줄바꿈 문자: CRLF, LF, CR
줄을 바꾸는 방법은 운영체제마다 관례가 다릅니다.
| 표기 | 바이트 | 주로 쓰는 곳 |
|---|---|---|
| LF | 0A (\n) | Linux, macOS, 대부분의 개발 도구 |
| CRLF | 0D 0A (\r\n) | Windows 의 메모장 등 여러 프로그램, 이메일·HTTP 같은 인터넷 프로토콜 |
| CR | 0D (\r) | 아주 오래된 Mac OS(버전 9 이전) |
한 파일은 CRLF, 다른 파일은 LF 로 저장돼 있으면, 줄 단위로 비교할 때 모든 줄 끝에 보이지 않는 \r 하나씩이 차이로 잡혀 전체가 바뀐 것처럼 보입니다. GNU diff 는 --strip-trailing-cr, git diff 는 --ignore-cr-at-eol 로 이 차이를 무시할 수 있습니다.
파일 끝 줄바꿈
POSIX 관례에서 텍스트 파일의 줄은 줄바꿈 문자로 끝납니다. 그래서 많은 도구가 마지막 줄 뒤에도 줄바꿈을 넣지만, 어떤 편집기는 넣지 않습니다. 이 차이는 unified diff 에서 다음처럼 표시됩니다.
@@ -1,2 +1,2 @@ host=example.com-port=8080\ No newline at end of file+port=8080
\ No newline at end of file 은 바로 위 줄 끝에 줄바꿈이 없다는 뜻입니다. 위 예에서는 내용은 같고, 변경 후 파일에만 마지막 줄바꿈이 추가됐습니다. 많은 코드 스타일 가이드가 파일 끝 줄바꿈을 요구하며, 편집기에서 "파일 끝에 줄바꿈 넣기" 설정으로 통일할 수 있습니다.
BOM: 첫 줄만 다를 때
UTF-8 파일 맨 앞에 EF BB BF 세 바이트가 붙는 경우가 있습니다. 이것을 바이트 순서 표시(BOM) 라고 합니다. UTF-8 에서는 바이트 순서가 필요 없지만, 일부 프로그램이 "이 파일은 UTF-8"이라는 표시로 붙입니다. BOM 은 화면에 보이지 않으므로, 첫 줄만 다르다고 나오면 BOM 을 의심해 보세요. 이 사이트는 파일을 불러올 때 맨 앞의 BOM 을 제거하고, 공백 무시 옵션을 켜면 붙여 넣은 텍스트 속 BOM(U+FEFF)도 공백처럼 취급합니다.
탭과 공백, 특수 공백
- 탭과 스페이스: 탭 하나와 스페이스 4개는 화면에서 같아 보여도 다른 문자입니다.
- 줄 바꿈 없는 공백(NBSP, U+00A0): 웹 페이지나 워드프로세서에서 복사한 텍스트에 자주 섞여 들어옵니다.
- 전각 공백(U+3000): 한국어·일본어·중국어 입력기에서 들어갈 수 있습니다.
- 폭 없는 공백(U+200B): 폭이 0이라 전혀 보이지 않지만 글자로 셉니다.
이런 문자는 공백 무시 옵션을 켜면 대부분 걸러집니다(단, U+200B 처럼 공백 문자로 분류되지 않는 문자는 옵션을 켜도 남을 수 있습니다). 줄 안 비교를 글자 단위로 바꾸면 어느 위치에 보이지 않는 문자가 있는지 강조 표시로 찾을 수 있습니다.
유니코드 정규화: 같은 글자, 다른 바이트
한글 "가"는 완성형 한 글자(U+AC00)로도, 초성 ㄱ(U+1100)과 중성 ㅏ(U+1161)를 이어 쓴 조합형으로도 표현할 수 있습니다. 유니코드는 전자를 NFC, 후자를 NFD 정규화 형식이라고 부릅니다(UAX #15). 두 텍스트는 화면에서 똑같이 보이지만 비교하면 다른 글자입니다. macOS 에서 만든 파일 이름이 다른 운영체제에서 "ㄱㅏ"처럼 자모가 풀려 보이는 현상이 대표적인 예입니다. 비교 전에 한쪽을 NFC 로 변환해 맞추는 것이 해결책입니다.
git 에서 줄바꿈 통일하기
여러 운영체제에서 함께 작업하는 저장소라면 git 설정으로 줄바꿈을 통일할 수 있습니다.
core.autocrlf:true로 두면 체크아웃할 때 LF 를 CRLF 로, 커밋할 때 CRLF 를 LF 로 바꿉니다(주로 Windows).input은 커밋할 때만 CRLF 를 LF 로 바꿉니다..gitattributes: 저장소 단위로 규칙을 정하므로 사람마다 설정이 달라도 결과가 같습니다.
* text=auto
*.sh text eol=lf
*.bat text eol=crlf
text=auto 는 git 이 텍스트 파일로 판단한 파일의 줄바꿈을 저장소 안에서 LF 로 정규화하고, eol=lf·eol=crlf 는 작업 폴더에 내려받을 때의 줄바꿈을 지정합니다.
이 도구에서 해 보기
텍스트 비교기의 줄 끝 정규화는 기본으로 켜져 있어, CRLF·CR·LF 를 모두 같은 줄바꿈으로 보고 파일 끝 줄바꿈 유무도 무시합니다. 이 옵션을 끄면 줄 끝의 CR 은 ␍ 로, 마지막 줄바꿈이 없는 줄은 ∅ 로 표시되어 보이지 않던 차이를 확인할 수 있습니다. 공백 관련 옵션은 공백 무시 옵션에, 결과 기호의 의미는 unified diff 읽는 법에 정리돼 있습니다.