윈도우와 맥의 줄바꿈이 다르다 — LF·CRLF 문제 정리
맥에서 받은 텍스트가 윈도우 옛 메모장에서 한 줄로 붙어 버리고, 깃 변경사항에는 ^M이라는 정체불명의 기호가 뜨고, 안 고친 파일이 전부 변경됐다고 나옵니다 — 범인은 모두 같습니다. 운영체제마다 다른 줄바꿈 문자. 원리와 처방을 정리합니다.
유래 — 타자기의 두 동작
타자기에서 줄을 바꾸는 일은 두 동작이었습니다 — 종이를 한 줄 위로 올리기(Line Feed)와, 잉크 머리를 줄 맨 앞으로 되돌리기(Carriage Return).
- 윈도우(CRLF) — 두 동작을 다 기록합니다:
\r\n(문자 2개) - 맥·리눅스(LF) — 하나로 충분하다고 봤습니다:
\n(문자 1개) - 같은 "엔터"인데 파일에 적히는 내용이 달라서, 서로의 파일을 읽을 때 어긋남이 생깁니다.
문제가 되는 곳
- 옛 윈도우 메모장 — LF만 있는 파일을 한 줄로 뭉쳐 보여 줬습니다(최신 메모장은 해결됨).
- git diff의
^M— CR(\r)이 표시된 것. CRLF 파일을 LF 기준 도구가 읽은 흔적입니다. - 전부 변경된 것처럼 보이는 diff — 에디터가 저장하며 줄바꿈을 일괄 변환하면, 내용이 같아도 모든 줄이 바뀐 걸로 잡힙니다.
- 스크립트 실행 오류 — 리눅스 서버에서 CRLF 셸 스크립트는
command not found\r같은 알 수 없는 에러를 냅니다.
해결 — 상황별 처방
- 받은 텍스트가 이상할 때 — 공백·줄바꿈 정리에 붙여 넣었다가 다시 복사하면 줄바꿈이 통일된 텍스트를 얻습니다.
- 코드 파일 — VS Code 하단 상태바의
LF/CRLF표시를 클릭해 바꾸고 저장합니다. - diff가 의심될 때 — 텍스트 비교로 두 버전을 견줘 보면 내용 차이인지 줄바꿈 차이인지 분간됩니다.
예방 — 팀에서 통일하기
.gitattributes 파일로 규칙을 못 박는 것입니다 — * text=auto 한 줄이면 깃이 커밋 시 LF로 통일해 주고, 특정 파일은 *.bat eol=crlf처럼 예외를 둡니다.- 에디터 설정(
.editorconfig)에end_of_line = lf를 두면 저장 단계부터 통일됩니다. - 규칙이 있으면 "전부 변경된 diff" 사고와 ^M 소동이 사라집니다 — 한 번 정해 두는 값어치가 큽니다.
줄을 끝내는 보이지 않는 문자의 개수가 다릅니다. LF(Line Feed, \n)는 문자 하나로 줄을 바꾸고 맥·리눅스가 사용합니다. CRLF(Carriage Return + Line Feed, \r\n)는 두 문자를 쓰며 윈도우의 방식입니다. 유래는 타자기입니다. 종이를 한 줄 올리는 동작(LF)과 잉크 머리를 줄 맨 앞으로 되돌리는 동작(CR)이 따로 있었고, 윈도우는 둘 다, 유닉스 계열은 하나만 남긴 것입니다.
줄바꿈 형식이 섞였다는 신호입니다. ^M은 CR(\r) 문자가 화면에 표시된 것으로, 윈도우에서 저장한 CRLF 파일을 LF 기준 도구가 읽을 때 나타납니다. 내용을 한 글자도 안 고쳤는데 파일 전체가 변경으로 잡히는 것도 에디터가 저장하며 줄바꿈을 일괄 변환했기 때문입니다. 저장소에 .gitattributes로 'text=auto' 또는 '*.확장자 eol=lf'를 정해 두면 팀 전체의 줄바꿈이 통일되어 재발을 막을 수 있습니다.
텍스트 정리 도구에 붙여 넣었다가 다시 복사하는 것이 가장 빠릅니다. 브라우저 입력창은 어떤 줄바꿈이든 통일된 형태로 처리하므로, 공백·줄바꿈 정리 도구를 거치면 CR 잔여물이 정리된 텍스트를 얻을 수 있습니다. 코드 파일이라면 VS Code 하단 상태바의 LF/CRLF 표시를 클릭해 형식을 바꿔 다시 저장하는 방법이 정석입니다.